From scipy-svn at scipy.org Tue Aug 17 20:35:48 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 17 Aug 2010 19:35:48 -0500 (CDT) Subject: [Scipy-svn] r6647 - in trunk/scipy/signal: . tests Message-ID: <20100818003548.177B939CB4B@scipy.org> Author: charris Date: 2010-08-17 19:35:47 -0500 (Tue, 17 Aug 2010) New Revision: 6647 Modified: trunk/scipy/signal/signaltools.py trunk/scipy/signal/tests/test_filter_design.py Log: ENH: Fix remez to recognize 'hilbert' option. Thanks to kumanna. Modified: trunk/scipy/signal/signaltools.py =================================================================== --- trunk/scipy/signal/signaltools.py 2010-07-30 17:33:38 UTC (rev 6646) +++ trunk/scipy/signal/signaltools.py 2010-08-18 00:35:47 UTC (rev 6647) @@ -514,6 +514,9 @@ type --- The type of filter: 'bandpass' : flat response in bands. 'differentiator' : frequency proportional response in bands. + 'hilbert' : filter with odd symmetry, that is, type III + (for even order) or type IV (for odd order) + linear phase filters Outputs: (out,) @@ -523,9 +526,9 @@ """ # Convert type try: - tnum = {'bandpass':1, 'differentiator':2}[type] + tnum = {'bandpass':1, 'differentiator':2, 'hilbert':3}[type] except KeyError: - raise ValueError, "Type must be 'bandpass', or 'differentiator'" + raise ValueError("Type must be 'bandpass', 'differentiator', or 'hilbert'") # Convert weight if weight is None: Modified: trunk/scipy/signal/tests/test_filter_design.py =================================================================== --- trunk/scipy/signal/tests/test_filter_design.py 2010-07-30 17:33:38 UTC (rev 6646) +++ trunk/scipy/signal/tests/test_filter_design.py 2010-08-18 00:35:47 UTC (rev 6647) @@ -1,9 +1,9 @@ import warnings import numpy as np -from numpy.testing import TestCase, assert_array_almost_equal +from numpy.testing import * -from scipy.signal import tf2zpk, bessel, BadCoefficients, kaiserord, firwin, freqz +from scipy.signal import tf2zpk, bessel, BadCoefficients, kaiserord, firwin, freqz, remez class TestTf2zpk(TestCase): @@ -40,7 +40,7 @@ class TestFirWin(TestCase): - + def test_lowpass(self): width = 0.04 ntaps, beta = kaiserord(120, width) @@ -49,3 +49,34 @@ freqs, response = freqz(taps, worN=np.pi*freq_samples) assert_array_almost_equal(np.abs(response), [1.0, 1.0, 1.0, 0.0, 0.0, 0.0], decimal=5) + +class TestRemez(TestCase): + + def test_hilbert(self): + N = 11 # number of taps in the filter + a = 0.1 # width of the transition band + + # design an unity gain hilbert bandpass filter from w to 0.5-w + h = remez(11, [ a, 0.5-a ], [ 1 ], type='hilbert') + + # make sure the filter has correct # of taps + assert_(len(h) == N, "Number of Taps") + + # make sure it is type III (anti-symmtric tap coefficients) + assert_array_almost_equal(h[:(N-1)/2], -h[:-(N-1)/2-1:-1]) + + # Since the requested response is symmetric, all even coeffcients + # should be zero (or in this case really small) + assert_((abs(h[1::2]) < 1e-15).all(), "Even Coefficients Equal Zero") + + # now check the frequency response + w, H = freqz(h, 1) + f = w/2/np.pi + Hmag = abs(H) + + # should have a zero at 0 and pi (in this case close to zero) + assert_((Hmag[ [0,-1] ] < 0.02).all(), "Zero at zero and pi") + + # check that the pass band is close to unity + idx = (f > a) * (f < 0.5-a) + assert_((abs(Hmag[idx] - 1) < 0.015).all(), "Pass Band Close To Unity") From scipy-svn at scipy.org Wed Aug 18 15:05:16 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 18 Aug 2010 14:05:16 -0500 (CDT) Subject: [Scipy-svn] r6648 - trunk/scipy/signal/tests Message-ID: <20100818190516.24CAB39CD34@scipy.org> Author: warren.weckesser Date: 2010-08-18 14:05:15 -0500 (Wed, 18 Aug 2010) New Revision: 6648 Modified: trunk/scipy/signal/tests/test_filter_design.py Log: TST: Don't use the * form of import. Modified: trunk/scipy/signal/tests/test_filter_design.py =================================================================== --- trunk/scipy/signal/tests/test_filter_design.py 2010-08-18 00:35:47 UTC (rev 6647) +++ trunk/scipy/signal/tests/test_filter_design.py 2010-08-18 19:05:15 UTC (rev 6648) @@ -1,7 +1,7 @@ import warnings import numpy as np -from numpy.testing import * +from numpy.testing import TestCase, assert_array_almost_equal, assert_ from scipy.signal import tf2zpk, bessel, BadCoefficients, kaiserord, firwin, freqz, remez From scipy-svn at scipy.org Wed Aug 18 17:23:03 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 18 Aug 2010 16:23:03 -0500 (CDT) Subject: [Scipy-svn] r6649 - in trunk/scipy/io: . tests tests/data Message-ID: <20100818212303.B1C7539CD02@scipy.org> Author: matthew.brett at gmail.com Date: 2010-08-18 16:23:03 -0500 (Wed, 18 Aug 2010) New Revision: 6649 Added: trunk/scipy/io/idlsave.py trunk/scipy/io/tests/data/array_float32_1d.sav trunk/scipy/io/tests/data/array_float32_2d.sav trunk/scipy/io/tests/data/array_float32_3d.sav trunk/scipy/io/tests/data/array_float32_4d.sav trunk/scipy/io/tests/data/array_float32_5d.sav trunk/scipy/io/tests/data/array_float32_6d.sav trunk/scipy/io/tests/data/array_float32_7d.sav trunk/scipy/io/tests/data/array_float32_8d.sav trunk/scipy/io/tests/data/scalar_byte.sav trunk/scipy/io/tests/data/scalar_complex32.sav trunk/scipy/io/tests/data/scalar_complex64.sav trunk/scipy/io/tests/data/scalar_float32.sav trunk/scipy/io/tests/data/scalar_float64.sav trunk/scipy/io/tests/data/scalar_heap_pointer.sav trunk/scipy/io/tests/data/scalar_int16.sav trunk/scipy/io/tests/data/scalar_int32.sav trunk/scipy/io/tests/data/scalar_int64.sav trunk/scipy/io/tests/data/scalar_string.sav trunk/scipy/io/tests/data/scalar_uint16.sav trunk/scipy/io/tests/data/scalar_uint32.sav trunk/scipy/io/tests/data/scalar_uint64.sav trunk/scipy/io/tests/data/struct_arrays.sav trunk/scipy/io/tests/data/struct_arrays_replicated.sav trunk/scipy/io/tests/data/struct_scalars.sav trunk/scipy/io/tests/data/struct_scalars_replicated.sav trunk/scipy/io/tests/data/various_compressed.sav trunk/scipy/io/tests/test_idlsave.py Modified: trunk/scipy/io/__init__.py Log: ENH - added idlsave module by Thomas Robitaille Modified: trunk/scipy/io/__init__.py =================================================================== --- trunk/scipy/io/__init__.py 2010-08-18 19:05:15 UTC (rev 6648) +++ trunk/scipy/io/__init__.py 2010-08-18 21:23:03 UTC (rev 6649) @@ -17,6 +17,7 @@ import matlab.byteordercodes as byteordercodes from data_store import save_as_module from mmio import mminfo, mmread, mmwrite +import idlsave __all__ = filter(lambda s:not s.startswith('_'),dir()) from numpy.testing import Tester Added: trunk/scipy/io/idlsave.py =================================================================== --- trunk/scipy/io/idlsave.py (rev 0) +++ trunk/scipy/io/idlsave.py 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,779 @@ +# IDLSave - a python module to read IDL 'save' files +# Copyright (c) 2010 Thomas P. Robitaille + +# Many thanks to Craig Markwardt for publishing the Unofficial Format +# Specification for IDL .sav files, without which this Python module would not +# exist (http://cow.physics.wisc.edu/~craigm/idl/savefmt). + +# This code was developed by with permission from ITT Visual Information +# Systems. IDL(r) is a registered trademark of ITT Visual Information Systems, +# Inc. for their Interactive Data Language software. + +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +import struct +import numpy as np +import tempfile +import zlib +import warnings + +# Define the different data types that can be found in an IDL save file +DTYPE_DICT = {} +DTYPE_DICT[1] = '>u1' +DTYPE_DICT[2] = '>i2' +DTYPE_DICT[3] = '>i4' +DTYPE_DICT[4] = '>f4' +DTYPE_DICT[5] = '>f8' +DTYPE_DICT[6] = '>c8' +DTYPE_DICT[7] = '|O' +DTYPE_DICT[8] = '|O' +DTYPE_DICT[9] = '>c16' +DTYPE_DICT[12] = '>u2' +DTYPE_DICT[13] = '>u4' +DTYPE_DICT[14] = '>i8' +DTYPE_DICT[15] = '>u8' + +# Define the different record types that can be found in an IDL save file +RECTYPE_DICT = {} +RECTYPE_DICT[0] = "START_MARKER" +RECTYPE_DICT[1] = "COMMON_VARIABLE" +RECTYPE_DICT[2] = "VARIABLE" +RECTYPE_DICT[3] = "SYSTEM_VARIABLE" +RECTYPE_DICT[6] = "END_MARKER" +RECTYPE_DICT[10] = "TIMESTAMP" +RECTYPE_DICT[12] = "COMPILED" +RECTYPE_DICT[13] = "IDENTIFICATION" +RECTYPE_DICT[14] = "VERSION" +RECTYPE_DICT[15] = "HEAP_HEADER" +RECTYPE_DICT[16] = "HEAP_DATA" +RECTYPE_DICT[17] = "PROMOTE64" +RECTYPE_DICT[19] = "NOTICE" + +# Define a dictionary to contain structure definitions +STRUCT_DICT = {} + + +def _align_32(f): + '''Align to the next 32-bit position in a file''' + + pos = f.tell() + if pos % 4 <> 0: + f.seek(pos + 4 - pos % 4) + return + + +def _skip_bytes(f, n): + '''Skip `n` bytes''' + f.read(n) + return + + +def _read_bytes(f, n): + '''Read the next `n` bytes''' + return f.read(n) + + +def _read_byte(f): + '''Read a single byte''' + return np.uint8(struct.unpack('>B', f.read(4)[0])[0]) + + +def _read_long(f): + '''Read a signed 32-bit integer''' + return np.int32(struct.unpack('>l', f.read(4))[0]) + + +def _read_int16(f): + '''Read a signed 16-bit integer''' + return np.int16(struct.unpack('>h', f.read(4)[2:4])[0]) + + +def _read_int32(f): + '''Read a signed 32-bit integer''' + return np.int32(struct.unpack('>i', f.read(4))[0]) + + +def _read_int64(f): + '''Read a signed 64-bit integer''' + return np.int64(struct.unpack('>q', f.read(8))[0]) + + +def _read_uint16(f): + '''Read an unsigned 16-bit integer''' + return np.uint16(struct.unpack('>H', f.read(4)[2:4])[0]) + + +def _read_uint32(f): + '''Read an unsigned 32-bit integer''' + return np.uint32(struct.unpack('>I', f.read(4))[0]) + + +def _read_uint64(f): + '''Read an unsigned 64-bit integer''' + return np.uint64(struct.unpack('>Q', f.read(8))[0]) + + +def _read_float32(f): + '''Read a 32-bit float''' + return np.float32(struct.unpack('>f', f.read(4))[0]) + + +def _read_float64(f): + '''Read a 64-bit float''' + return np.float64(struct.unpack('>d', f.read(8))[0]) + + +class Pointer(object): + '''Class used to define pointers''' + + def __init__(self, index): + self.index = index + return + + +def _read_string(f): + '''Read a string''' + length = _read_long(f) + if length > 0: + chars = _read_bytes(f, length) + _align_32(f) + else: + chars = None + return np.str(chars) + + +def _read_string_data(f): + '''Read a data string (length is specified twice)''' + length = _read_long(f) + if length > 0: + length = _read_long(f) + string = _read_bytes(f, length) + _align_32(f) + else: + string = None + return np.str(string) + + +def _read_data(f, dtype): + '''Read a variable with a specified data type''' + if dtype==1: + if _read_int32(f) <> 1: + raise Exception("Error occured while reading byte variable") + return _read_byte(f) + elif dtype==2: + return _read_int16(f) + elif dtype==3: + return _read_int32(f) + elif dtype==4: + return _read_float32(f) + elif dtype==5: + return _read_float64(f) + elif dtype==6: + real = _read_float32(f) + imag = _read_float32(f) + return np.complex64(real + imag * 1j) + elif dtype==7: + return _read_string_data(f) + elif dtype==8: + raise Exception("Should not be here - please report this") + elif dtype==9: + real = _read_float64(f) + imag = _read_float64(f) + return np.complex128(real + imag * 1j) + elif dtype==10: + return Pointer(_read_int32(f)) + elif dtype==11: + raise Exception("Object reference type not implemented") + elif dtype==12: + return _read_uint16(f) + elif dtype==13: + return _read_uint32(f) + elif dtype==14: + return _read_int64(f) + elif dtype==15: + return _read_uint64(f) + else: + raise Exception("Unknown IDL type: %i - please report this" % dtype) + + +def _read_structure(f, array_desc, struct_desc): + ''' + Read a structure, with the array and structure descriptors given as + `array_desc` and `structure_desc` respectively. + ''' + + nrows = array_desc['nelements'] + ncols = struct_desc['ntags'] + columns = struct_desc['tagtable'] + + dtype = [] + for col in columns: + if col['structure'] or col['array']: + dtype.append(((col['name'].lower(), col['name']), np.object_)) + else: + if col['typecode'] in DTYPE_DICT: + dtype.append(((col['name'].lower(), col['name']), + DTYPE_DICT[col['typecode']])) + else: + raise Exception("Variable type %i not implemented" % + col['typecode']) + + structure = np.recarray((nrows, ), dtype=dtype) + + for i in range(nrows): + for col in columns: + dtype = col['typecode'] + if col['structure']: + structure[col['name']][i] = _read_structure(f, \ + struct_desc['arrtable'][col['name']], \ + struct_desc['structtable'][col['name']]) + elif col['array']: + structure[col['name']][i] = _read_array(f, dtype, \ + struct_desc['arrtable'][col['name']]) + else: + structure[col['name']][i] = _read_data(f, dtype) + + return structure + + +def _read_array(f, typecode, array_desc): + ''' + Read an array of type `typecode`, with the array descriptor given as + `array_desc`. + ''' + + if typecode in [1, 3, 4, 5, 6, 9, 13, 14, 15]: + + if typecode == 1: + nbytes = _read_int32(f) + if nbytes <> array_desc['nbytes']: + raise Exception("Error occured while reading byte array") + + # Read bytes as numpy array + array = np.fromstring(f.read(array_desc['nbytes']), \ + dtype=DTYPE_DICT[typecode]) + + elif typecode in [2, 12]: + + # These are 2 byte types, need to skip every two as they are not packed + + array = np.fromstring(f.read(array_desc['nbytes']*2), \ + dtype=DTYPE_DICT[typecode])[1::2] + + else: + + # Read bytes into list + array = [] + for i in range(array_desc['nelements']): + dtype = typecode + data = _read_data(f, dtype) + array.append(data) + + array = np.array(array, dtype=np.object_) + + # Reshape array if needed + if array_desc['ndims'] > 1: + dims = array_desc['dims'][:array_desc['ndims']] + dims.reverse() + array = array.reshape(dims) + + # Go to next alignment position + _align_32(f) + + return array + + +def _read_record(f): + '''Function to read in a full record''' + + record = {} + + recpos = f.tell() + record['rectype'] = _read_long(f) + + nextrec = _read_uint32(f) + nextrec += _read_uint32(f) * 2**32 + + _skip_bytes(f, 4) + + if not record['rectype'] in RECTYPE_DICT: + raise Exception("Unknown RECTYPE: %i" % record['rectype']) + + record['rectype'] = RECTYPE_DICT[record['rectype']] + + if record['rectype'] in ["VARIABLE", "HEAP_DATA"]: + + if record['rectype'] == "VARIABLE": + record['varname'] = _read_string(f) + else: + record['heap_index'] = _read_long(f) + _skip_bytes(f, 4) + + rectypedesc = _read_typedesc(f) + + varstart = _read_long(f) + if varstart <> 7: + raise Exception("VARSTART is not 7") + + if rectypedesc['structure']: + record['data'] = _read_structure(f, rectypedesc['array_desc'], \ + rectypedesc['struct_desc']) + elif rectypedesc['array']: + record['data'] = _read_array(f, rectypedesc['typecode'], \ + rectypedesc['array_desc']) + else: + dtype = rectypedesc['typecode'] + record['data'] = _read_data(f, dtype) + + elif record['rectype'] == "TIMESTAMP": + + _skip_bytes(f, 4*256) + record['date'] = _read_string(f) + record['user'] = _read_string(f) + record['host'] = _read_string(f) + + elif record['rectype'] == "VERSION": + + record['format'] = _read_long(f) + record['arch'] = _read_string(f) + record['os'] = _read_string(f) + record['release'] = _read_string(f) + + elif record['rectype'] == "IDENTIFICATON": + + record['author'] = _read_string(f) + record['title'] = _read_string(f) + record['idcode'] = _read_string(f) + + elif record['rectype'] == "NOTICE": + + record['notice'] = _read_string(f) + + elif record['rectype'] == "HEAP_HEADER": + + record['nvalues'] = _read_long(f) + record['indices'] = [] + for i in range(record['nvalues']): + record['indices'].append(_read_long(f)) + + elif record['rectype'] == "COMMONBLOCK": + + record['nvars'] = _read_long(f) + record['name'] = _read_string(f) + record['varnames'] = [] + for i in range(record['nvars']): + record['varnames'].append(_read_string(f)) + + elif record['rectype'] == "END_MARKER": + + record['end'] = True + + elif record['rectype'] == "UNKNOWN": + + warnings.warn("Skipping UNKNOWN record") + + elif record['rectype'] == "SYSTEM_VARIABLE": + + warnings.warn("Skipping SYSTEM_VARIABLE record") + + else: + + raise Exception("record['rectype']=%s not implemented" % \ + record['rectype']) + + f.seek(nextrec) + + return record + + +def _read_typedesc(f): + '''Function to read in a type descriptor''' + + typedesc = {} + + typedesc['typecode'] = _read_long(f) + typedesc['varflags'] = _read_long(f) + + if typedesc['varflags'] & 2 == 2: + raise Exception("System variables not implemented") + + typedesc['array'] = typedesc['varflags'] & 4 == 4 + typedesc['structure'] = typedesc['varflags'] & 32 == 32 + + if typedesc['structure']: + typedesc['array_desc'] = _read_arraydesc(f) + typedesc['struct_desc'] = _read_structdesc(f) + elif typedesc['array']: + typedesc['array_desc'] = _read_arraydesc(f) + + return typedesc + + +def _read_arraydesc(f): + '''Function to read in an array descriptor''' + + arraydesc = {} + + arraydesc['arrstart'] = _read_long(f) + + if arraydesc['arrstart'] == 8: + + _skip_bytes(f, 4) + + arraydesc['nbytes'] = _read_long(f) + arraydesc['nelements'] = _read_long(f) + arraydesc['ndims'] = _read_long(f) + + _skip_bytes(f, 8) + + arraydesc['nmax'] = _read_long(f) + + arraydesc['dims'] = [] + for d in range(arraydesc['nmax']): + arraydesc['dims'].append(_read_long(f)) + + elif arraydesc['arrstart'] == 18: + + warnings.warn("Using experimental 64-bit array read") + + _skip_bytes(f, 8) + + arraydesc['nbytes'] = _read_uint64(f) + arraydesc['nelements'] = _read_uint64(f) + arraydesc['ndims'] = _read_long(f) + + _skip_bytes(f, 8) + + arraydesc['nmax'] = 8 + + arraydesc['dims'] = [] + for d in range(arraydesc['nmax']): + v = _read_long(f) + if v <> 0: + raise Exception("Expected a zero in ARRAY_DESC") + arraydesc['dims'].append(_read_long(f)) + + else: + + raise Exception("Unknown ARRSTART: %i" % arraydesc['arrstart']) + + return arraydesc + + +def _read_structdesc(f): + '''Function to read in a structure descriptor''' + + structdesc = {} + + structstart = _read_long(f) + if structstart <> 9: + raise Exception("STRUCTSTART should be 9") + + structdesc['name'] = _read_string(f) + structdesc['predef'] = _read_long(f) + structdesc['ntags'] = _read_long(f) + structdesc['nbytes'] = _read_long(f) + + if structdesc['predef'] & 1 == 0: + + structdesc['tagtable'] = [] + for t in range(structdesc['ntags']): + structdesc['tagtable'].append(_read_tagdesc(f)) + + for tag in structdesc['tagtable']: + tag['name'] = _read_string(f) + + structdesc['arrtable'] = {} + for tag in structdesc['tagtable']: + if tag['array']: + structdesc['arrtable'][tag['name']] = _read_arraydesc(f) + + structdesc['structtable'] = {} + for tag in structdesc['tagtable']: + if tag['structure']: + structdesc['structtable'][tag['name']] = _read_structdesc(f) + + STRUCT_DICT[structdesc['name']] = (structdesc['tagtable'], \ + structdesc['arrtable'], \ + structdesc['structtable']) + + else: + + if not structdesc['name'] in STRUCT_DICT: + raise Exception("PREDEF=1 but can't find definition") + + structdesc['tagtable'], \ + structdesc['arrtable'], \ + structdesc['structtable'] = STRUCT_DICT[structdesc['name']] + + return structdesc + + +def _read_tagdesc(f): + '''Function to read in a tag descriptor''' + + tagdesc = {} + + tagdesc['offset'] = _read_long(f) + + if tagdesc['offset'] == -1: + tagdesc['offset'] = _read_uint64(f) + + tagdesc['typecode'] = _read_long(f) + tagflags = _read_long(f) + + tagdesc['array'] = tagflags & 4 == 4 + tagdesc['structure'] = tagflags & 32 == 32 + tagdesc['scalar'] = tagdesc['typecode'] in DTYPE_DICT + # Assume '10'x is scalar + + return tagdesc + + +class AttrDict(dict): + ''' + A case-insensitive dictionary with access via item, attribute, and call + notations: + + >>> d = AttrDict() + >>> d['Variable'] = 123 + >>> d['Variable'] + 123 + >>> d.Variable + 123 + >>> d.variable + 123 + >>> d('VARIABLE') + 123 + ''' + + def __init__(self, init={}): + dict.__init__(self, init) + + def __getitem__(self, name): + return super(AttrDict, self).__getitem__(name.lower()) + + def __setitem__(self, key, value): + return super(AttrDict, self).__setitem__(key.lower(), value) + + __getattr__ = __getitem__ + __setattr__ = __setitem__ + __call__ = __getitem__ + + +def read(file_name, idict=None, python_dict=False, + uncompressed_file_name=None, verbose=True): + ''' + Read an IDL .sav file + + Parameters + ---------- + file_name : str + Name of the IDL save file. + idict : dict, optional + Dictionary in which to insert .sav file variables + python_dict: bool, optional + By default, the object return is not a Python dictionary, but a + case-insensitive dictionary with item, attribute, and call access + to variables. To get a standard Python dictionary, set this option + to True. If `idict` is specified, `attribute_access` is ignored. + uncompressed_file_name : str, optional + This option only has an effect for .sav files written with the + /compress option. If a file name is specified, compressed .sav + files are uncompressed to this file. Otherwise, idlsave will use + the `tempfile` module to determine a temporary filename + automatically, and will remove the temporary file upon successfully + reading it in. + verbose : bool, optional + Whether to print out information about the save file, including + the records read, and available variables. + + Returns + ---------- + idl_dict : AttrDict or dict + If `python_dict` is set to False (default), this function returns a + case-insensitive dictionary with item, attribute, and call access + to variables. If `python_dict` is set to True, this function + returns a Python dictionary with all variable names in lowercase. + If `idict` was specified, then variables are written to the + dictionary specified, and the updated dictionary is returned. + ''' + + # Initialize record and variable holders + records = [] + if python_dict or idict: + variables = {} + else: + variables = AttrDict() + + # Open the IDL file + f = file(file_name, 'rb') + + # Read the signature, which should be 'SR' + signature = _read_bytes(f, 2) + if signature <> 'SR': + raise Exception("Invalid SIGNATURE: %s" % signature) + + # Next, the record format, which is '\x00\x04' for normal .sav + # files, and '\x00\x06' for compressed .sav files. + recfmt = _read_bytes(f, 2) + + if recfmt == '\x00\x04': + pass + + elif recfmt == '\x00\x06': + + if verbose: + print "IDL Save file is compressed" + + if uncompressed_file_name: + fout = file(uncompressed_file_name, 'w+b') + else: + fout = tempfile.NamedTemporaryFile(suffix='.sav') + + if verbose: + print " -> expanding to %s" % fout.name + + # Write header + fout.write('SR\x00\x04') + + # Cycle through records + while True: + + # Read record type + rectype = _read_long(f) + fout.write(struct.pack('>l', rectype)) + + # Read position of next record and return as int + nextrec = _read_uint32(f) + nextrec += _read_uint32(f) * 2**32 + + # Read the unknown 4 bytes + unknown = f.read(4) + + # Check if the end of the file has been reached + if RECTYPE_DICT[rectype] == 'END_MARKER': + fout.write(struct.pack('>I', int(nextrec) % 2**32)) + fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32))) + fout.write(unknown) + break + + # Find current position + pos = f.tell() + + # Decompress record + string = zlib.decompress(f.read(nextrec-pos)) + + # Find new position of next record + nextrec = fout.tell() + len(string) + 12 + + # Write out record + fout.write(struct.pack('>I', int(nextrec % 2**32))) + fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32))) + fout.write(unknown) + fout.write(string) + + # Close the original compressed file + f.close() + + # Set f to be the decompressed file, and skip the first four bytes + f = fout + f.seek(4) + + else: + raise Exception("Invalid RECFMT: %s" % recfmt) + + # Loop through records, and add them to the list + while True: + r = _read_record(f) + records.append(r) + if 'end' in r: + if r['end']: + break + + # Close the file + f.close() + + # Find heap data variables + heap = {} + for r in records: + if r['rectype'] == "HEAP_DATA": + heap[r['heap_index']] = r['data'] + + # Find all variables + for r in records: + if r['rectype'] == "VARIABLE": + while isinstance(r['data'], Pointer): + r['data'] = heap[r['data'].index] + variables[r['varname'].lower()] = r['data'] + + if verbose: + + # Print out timestamp info about the file + for record in records: + if record['rectype'] == "TIMESTAMP": + print "-"*50 + print "Date: %s" % record['date'] + print "User: %s" % record['user'] + print "Host: %s" % record['host'] + break + + # Print out version info about the file + for record in records: + if record['rectype'] == "VERSION": + print "-"*50 + print "Format: %s" % record['format'] + print "Architecture: %s" % record['arch'] + print "Operating System: %s" % record['os'] + print "IDL Version: %s" % record['release'] + break + + # Print out identification info about the file + for record in records: + if record['rectype'] == "IDENTIFICATON": + print "-"*50 + print "Author: %s" % record['author'] + print "Title: %s" % record['title'] + print "ID Code: %s" % record['idcode'] + break + + print "-"*50 + print "Successfully read %i records of which:" % \ + (len(records)) + + # Create convenience list of record types + rectypes = [r['rectype'] for r in records] + + for rt in set(rectypes): + if rt <> 'END_MARKER': + print " - %i are of type %s" % (rectypes.count(rt), rt) + print "-"*50 + + if 'VARIABLE' in rectypes: + print "Available variables:" + for var in variables: + print " - %s [%s]" % (var, type(variables[var])) + print "-"*50 + + if idict: + for var in variables: + idict[var] = variables[var] + return idict + else: + return variables Added: trunk/scipy/io/tests/data/array_float32_1d.sav =================================================================== --- trunk/scipy/io/tests/data/array_float32_1d.sav (rev 0) +++ trunk/scipy/io/tests/data/array_float32_1d.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,19 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + +4ARRAY1D?{{ \ No newline at end of file Added: trunk/scipy/io/tests/data/array_float32_2d.sav =================================================================== --- trunk/scipy/io/tests/data/array_float32_2d.sav (rev 0) +++ trunk/scipy/io/tests/data/array_float32_2d.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + hARRAY2D   \ No newline at end of file Added: trunk/scipy/io/tests/data/array_float32_3d.sav =================================================================== --- trunk/scipy/io/tests/data/array_float32_3d.sav (rev 0) +++ trunk/scipy/io/tests/data/array_float32_3d.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +5?ARRAY3D-` X   \ No newline at end of file Added: trunk/scipy/io/tests/data/array_float32_4d.sav =================================================================== --- trunk/scipy/io/tests/data/array_float32_4d.sav (rev 0) +++ trunk/scipy/io/tests/data/array_float32_4d.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +?ARRAY4D?` \ No newline at end of file Added: trunk/scipy/io/tests/data/array_float32_5d.sav =================================================================== --- trunk/scipy/io/tests/data/array_float32_5d.sav (rev 0) +++ trunk/scipy/io/tests/data/array_float32_5d.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +?ARRAY5D?? \ No newline at end of file Added: trunk/scipy/io/tests/data/array_float32_6d.sav =================================================================== --- trunk/scipy/io/tests/data/array_float32_6d.sav (rev 0) +++ trunk/scipy/io/tests/data/array_float32_6d.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +K?ARRAY6DC?? \ No newline at end of file Added: trunk/scipy/io/tests/data/array_float32_7d.sav =================================================================== --- trunk/scipy/io/tests/data/array_float32_7d.sav (rev 0) +++ trunk/scipy/io/tests/data/array_float32_7d.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + ?ARRAY7D?  \ No newline at end of file Added: trunk/scipy/io/tests/data/array_float32_8d.sav =================================================================== --- trunk/scipy/io/tests/data/array_float32_8d.sav (rev 0) +++ trunk/scipy/io/tests/data/array_float32_8d.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +5HARRAY8D- @ \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_byte.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_byte.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_byte.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + I8U? \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_complex32.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_complex32.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_complex32.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + C32U?UD???? \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_complex64.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_complex64.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_complex64.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +C64 W3????*???o? \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_float32.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_float32.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_float32.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +F32???x \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_float64.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_float64.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_float64.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + F64??Cm?C? \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_heap_pointer.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_heap_pointer.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_heap_pointer.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,20 @@ +SR +DSun Jul 18 17:02:42 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +?, W3????*???o?\ C64_POINTER1 +? C64_POINTER2 + \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_int16.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_int16.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_int16.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +I16S???` \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_int32.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_int32.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_int32.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +I32S?i?. \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_int64.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_int64.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_int64.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + I64S?? \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_string.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_string.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_string.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +<S..The quick brown fox jumps over the lazy python \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_uint16.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_uint16.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_uint16.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +I16U ?? \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_uint32.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_uint32.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_uint32.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,19 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +I32U +???? \ No newline at end of file Added: trunk/scipy/io/tests/data/scalar_uint64.sav =================================================================== --- trunk/scipy/io/tests/data/scalar_uint64.sav (rev 0) +++ trunk/scipy/io/tests/data/scalar_uint64.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + I64U???????? \ No newline at end of file Added: trunk/scipy/io/tests/data/struct_arrays.sav =================================================================== --- trunk/scipy/io/tests/data/struct_arrays.sav (rev 0) +++ trunk/scipy/io/tests/data/struct_arrays.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,19 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + +ARRAYS4XXOD (ABCD?FLOI0UF@?@?@?@???@@?Acheesebaconspam \ No newline at end of file Added: trunk/scipy/io/tests/data/struct_arrays_replicated.sav =================================================================== --- trunk/scipy/io/tests/data/struct_arrays_replicated.sav (rev 0) +++ trunk/scipy/io/tests/data/struct_arrays_replicated.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,19 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + h +ARRAYS_REP4X?? (ABCD?FLOI0UF@?@?@?@???@@?Acheesebaconspam@?@?@?@???@@?Acheesebaconspam@?@?@?@???@@?Acheesebaconspam@?@?@?@???@@?Acheesebaconspam@?@?@?@???@@?Acheesebaconspam \ No newline at end of file Added: trunk/scipy/io/tests/data/struct_scalars.sav =================================================================== --- trunk/scipy/io/tests/data/struct_scalars.sav (rev 0) +++ trunk/scipy/io/tests/data/struct_scalars.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** +?SCALARS400 (ABCDEF@@@spam??@@ \ No newline at end of file Added: trunk/scipy/io/tests/data/struct_scalars_replicated.sav =================================================================== --- trunk/scipy/io/tests/data/struct_scalars_replicated.sav (rev 0) +++ trunk/scipy/io/tests/data/struct_scalars_replicated.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,18 @@ +SR +DSun Jul 18 14:10:53 2010usernamehostx x86_64linux7.0?R +***************************************************************** + NOTICE: + +IDL Save/Restore files embody unpublished proprietary information +about the IDL program. Reverse engineering of this file is therefore +forbidden under the terms of the IDL End User License Agreement +(IDL EULA). All IDL users are required to read and agree to the +terms of the IDL EULA at the time that they install IDL. +Software that reads or writes files in the IDL Save/Restore format +must have a license from ITT Visual Information Solutions +explicitly granting the right to do so. In this case, the license +will be included with the software for your inspection. Please +report software that does not have such a license to +ITT Visual Information Solutions (info at ittvis.com). +***************************************************************** + ? SCALARS_REP40?? (ABCDEF@@@spam??@@@@@spam??@@@@@spam??@@@@@spam??@@@@@spam??@@ \ No newline at end of file Added: trunk/scipy/io/tests/data/various_compressed.sav =================================================================== --- trunk/scipy/io/tests/data/various_compressed.sav (rev 0) +++ trunk/scipy/io/tests/data/various_compressed.sav 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,14 @@ +SR +Ox?c`?`?` \???U??`h?`hbeh`ej?`d`h??()?O?,I??Yr???? +??x?c``?d```??0?73a????? +0???\??N(?6x??SM??0??-R??w +wNT??J???.w'?$#?#;???3v?????q?????l6om??_????/????????}???????DF?a?}?W?a???4??????b? +???????Y at f?????????g???a???&???(U???U ?F???????? ?O+i??~???A??#z ???????????s????h0??L?A$??X0?e +??)m?????Y? y???t???.?R?q?K???b?B &?tk??O??;?e???I`?O`???=?N'?F)?{??1?\&I??}Q +??????]???YJD!?N?? &???xqj? i?^w& .[??B2WLz???p??K?????W?? +0.????a?f??,?a~O???o?????H"gJ??}???? ??{' `x?c```??eF`?_ ???x?c```v36b`???O??x?c```v63aN`7? ??M????????^d?!x???? ? D? ???N, at H??MJI?.dA???vVRl???^2?%[???#??z??|??????D??????x?c```s +r? f 6??P??@???c$?9!??jY? ?E??Al f??5???ft??at???P?a6T/3??bo?r01\?( +????$GH?T?Ry"???~?^T????~v( +???????a? ? >? + +GP8?%g?????? ?????????? 1??` \ No newline at end of file Added: trunk/scipy/io/tests/test_idlsave.py =================================================================== --- trunk/scipy/io/tests/test_idlsave.py (rev 0) +++ trunk/scipy/io/tests/test_idlsave.py 2010-08-18 21:23:03 UTC (rev 6649) @@ -0,0 +1,224 @@ +from os import path + +DATA_PATH = path.join(path.dirname(__file__), 'data') + +import numpy as np + +from numpy.testing import assert_equal, assert_array_equal, run_module_suite +from nose.tools import assert_true + +from scipy.io import idlsave + + +def object_array(*args): + '''Constructs a numpy array of objects''' + array = np.empty(len(args), dtype=np.object) + for i in range(len(args)): + array[i] = args[i] + return array + + +def assert_identical(a, b): + '''Assert whether value AND type are the same''' + assert_equal(a, b) + if type(b) is np.str: + assert_equal(type(a), type(b)) + else: + assert_equal(a.dtype.type, b.dtype.type) + + +def assert_array_identical(a, b): + '''Assert whether values AND type are the same''' + assert_array_equal(a, b) + assert_equal(a.dtype.type, b.dtype.type) + + +class TestIdict: + '''Test the idict= argument to read''' + + def test_idict(self): + custom_dict = {'a': np.int16(999)} + original_id = id(custom_dict) + s = idlsave.read(path.join(DATA_PATH, 'scalar_byte.sav'), idict=custom_dict, verbose=False) + assert_equal(original_id, id(s)) + assert_true('a' in s) + assert_identical(s['a'], np.int16(999)) + assert_identical(s['i8u'], np.uint8(234)) + + +class TestScalars: + '''Test that scalar values are read in with the correct value and type''' + + def test_byte(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_byte.sav'), verbose=False) + assert_identical(s.i8u, np.uint8(234)) + + def test_int16(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_int16.sav'), verbose=False) + assert_identical(s.i16s, np.int16(-23456)) + + def test_int32(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_int32.sav'), verbose=False) + assert_identical(s.i32s, np.int32(-1234567890)) + + def test_float32(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_float32.sav'), verbose=False) + assert_identical(s.f32, np.float32(-3.1234567e+37)) + + def test_float64(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_float64.sav'), verbose=False) + assert_identical(s.f64, np.float64(-1.1976931348623157e+307)) + + def test_complex32(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_complex32.sav'), verbose=False) + assert_identical(s.c32, np.complex64(3.124442e13-2.312442e31j)) + + def test_string(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_string.sav'), verbose=False) + assert_identical(s.s, np.str("The quick brown fox jumps over the lazy python")) + + def test_structure(self): + pass + + def test_complex64(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_complex64.sav'), verbose=False) + assert_identical(s.c64, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j)) + + def test_heap_pointer(self): + pass + + def test_object_reference(self): + pass + + def test_uint16(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_uint16.sav'), verbose=False) + assert_identical(s.i16u, np.uint16(65511)) + + def test_uint32(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_uint32.sav'), verbose=False) + assert_identical(s.i32u, np.uint32(4294967233)) + + def test_int64(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_int64.sav'), verbose=False) + assert_identical(s.i64s, np.int64(-9223372036854774567)) + + def test_uint64(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_uint64.sav'), verbose=False) + assert_identical(s.i64u, np.uint64(18446744073709529285)) + + +class TestCompressed(TestScalars): + '''Test that compressed .sav files can be read in''' + + def test_compressed(self): + s = idlsave.read(path.join(DATA_PATH, 'various_compressed.sav'), verbose=False) + assert_identical(s.i8u, np.uint8(234)) + assert_identical(s.f32, np.float32(-3.1234567e+37)) + assert_identical(s.c64, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j)) + assert_equal(s.array5d.shape, (4, 3, 4, 6, 5)) + assert_identical(s.arrays.a[0], np.array([1, 2, 3], dtype=np.int16)) + assert_identical(s.arrays.b[0], np.array([4., 5., 6., 7.], dtype=np.float32)) + assert_identical(s.arrays.c[0], np.array([np.complex64(1+2j), np.complex64(7+8j)])) + assert_identical(s.arrays.d[0], np.array(["cheese", "bacon", "spam"], dtype=np.object)) + + +class TestArrayDimensions: + '''Test that multi-dimensional arrays are read in with the correct dimensions''' + + def test_1d(self): + s = idlsave.read(path.join(DATA_PATH, 'array_float32_1d.sav'), verbose=False) + assert_equal(s.array1d.shape, (123, )) + + def test_2d(self): + s = idlsave.read(path.join(DATA_PATH, 'array_float32_2d.sav'), verbose=False) + assert_equal(s.array2d.shape, (22, 12)) + + def test_3d(self): + s = idlsave.read(path.join(DATA_PATH, 'array_float32_3d.sav'), verbose=False) + assert_equal(s.array3d.shape, (11, 22, 12)) + + def test_4d(self): + s = idlsave.read(path.join(DATA_PATH, 'array_float32_4d.sav'), verbose=False) + assert_equal(s.array4d.shape, (4, 5, 8, 7)) + + def test_5d(self): + s = idlsave.read(path.join(DATA_PATH, 'array_float32_5d.sav'), verbose=False) + assert_equal(s.array5d.shape, (4, 3, 4, 6, 5)) + + def test_6d(self): + s = idlsave.read(path.join(DATA_PATH, 'array_float32_6d.sav'), verbose=False) + assert_equal(s.array6d.shape, (3, 6, 4, 5, 3, 4)) + + def test_7d(self): + s = idlsave.read(path.join(DATA_PATH, 'array_float32_7d.sav'), verbose=False) + assert_equal(s.array7d.shape, (2, 1, 2, 3, 4, 3, 2)) + + def test_8d(self): + s = idlsave.read(path.join(DATA_PATH, 'array_float32_8d.sav'), verbose=False) + assert_equal(s.array8d.shape, (4, 3, 2, 1, 2, 3, 5, 4)) + + +class TestStructures: + '''Test that structures are correctly read in''' + + def test_scalars(self): + s = idlsave.read(path.join(DATA_PATH, 'struct_scalars.sav'), verbose=False) + assert_identical(s.scalars.a, np.array(np.int16(1))) + assert_identical(s.scalars.b, np.array(np.int32(2))) + assert_identical(s.scalars.c, np.array(np.float32(3.))) + assert_identical(s.scalars.d, np.array(np.float64(4.))) + assert_identical(s.scalars.e, np.array(["spam"], dtype=np.object)) + assert_identical(s.scalars.f, np.array(np.complex64(-1.+3j))) + + def test_scalars_replicated(self): + s = idlsave.read(path.join(DATA_PATH, 'struct_scalars_replicated.sav'), verbose=False) + assert_identical(s.scalars_rep.a, np.repeat(np.int16(1), 5)) + assert_identical(s.scalars_rep.b, np.repeat(np.int32(2), 5)) + assert_identical(s.scalars_rep.c, np.repeat(np.float32(3.), 5)) + assert_identical(s.scalars_rep.d, np.repeat(np.float64(4.), 5)) + assert_identical(s.scalars_rep.e, np.repeat("spam", 5).astype(np.object)) + assert_identical(s.scalars_rep.f, np.repeat(np.complex64(-1.+3j), 5)) + + def test_arrays(self): + s = idlsave.read(path.join(DATA_PATH, 'struct_arrays.sav'), verbose=False) + assert_array_identical(s.arrays.a[0], np.array([1, 2, 3], dtype=np.int16)) + assert_array_identical(s.arrays.b[0], np.array([4., 5., 6., 7.], dtype=np.float32)) + assert_array_identical(s.arrays.c[0], np.array([np.complex64(1+2j), np.complex64(7+8j)])) + assert_array_identical(s.arrays.d[0], np.array(["cheese", "bacon", "spam"], dtype=np.object)) + + def test_arrays_replicated(self): + + s = idlsave.read(path.join(DATA_PATH, 'struct_arrays_replicated.sav'), verbose=False) + + # Check column types + assert_true(s.arrays_rep.a.dtype.type is np.object_) + assert_true(s.arrays_rep.b.dtype.type is np.object_) + assert_true(s.arrays_rep.c.dtype.type is np.object_) + assert_true(s.arrays_rep.d.dtype.type is np.object_) + + # Check column shapes + assert_equal(s.arrays_rep.a.shape, (5, )) + assert_equal(s.arrays_rep.b.shape, (5, )) + assert_equal(s.arrays_rep.c.shape, (5, )) + assert_equal(s.arrays_rep.d.shape, (5, )) + + # Check values + for i in range(5): + assert_array_identical(s.arrays_rep.a[i], np.array([1, 2, 3], dtype=np.int16)) + assert_array_identical(s.arrays_rep.b[i], np.array([4., 5., 6., 7.], dtype=np.float32)) + assert_array_identical(s.arrays_rep.c[i], np.array([np.complex64(1+2j), np.complex64(7+8j)])) + assert_array_identical(s.arrays_rep.d[i], np.array(["cheese", "bacon", "spam"], dtype=np.object)) + + +class TestPointers: + '''Check that pointers in .sav files produce references to the same object in Python''' + + def test_pointers(self): + s = idlsave.read(path.join(DATA_PATH, 'scalar_heap_pointer.sav'), verbose=False) + assert_identical(s.c64_pointer1, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j)) + assert_identical(s.c64_pointer2, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j)) + assert_true(s.c64_pointer1 is s.c64_pointer2) + + +if __name__ == "__main__": + run_module_suite() From scipy-svn at scipy.org Wed Aug 18 17:23:07 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 18 Aug 2010 16:23:07 -0500 (CDT) Subject: [Scipy-svn] r6650 - trunk/scipy/io Message-ID: <20100818212307.DD71D39CD4C@scipy.org> Author: matthew.brett at gmail.com Date: 2010-08-18 16:23:07 -0500 (Wed, 18 Aug 2010) New Revision: 6650 Modified: trunk/scipy/io/idlsave.py Log: RF - turning off default verbose as suggested by Pauli Modified: trunk/scipy/io/idlsave.py =================================================================== --- trunk/scipy/io/idlsave.py 2010-08-18 21:23:03 UTC (rev 6649) +++ trunk/scipy/io/idlsave.py 2010-08-18 21:23:07 UTC (rev 6650) @@ -578,7 +578,7 @@ def read(file_name, idict=None, python_dict=False, - uncompressed_file_name=None, verbose=True): + uncompressed_file_name=None, verbose=False): ''' Read an IDL .sav file @@ -592,7 +592,7 @@ By default, the object return is not a Python dictionary, but a case-insensitive dictionary with item, attribute, and call access to variables. To get a standard Python dictionary, set this option - to True. If `idict` is specified, `attribute_access` is ignored. + to True. uncompressed_file_name : str, optional This option only has an effect for .sav files written with the /compress option. If a file name is specified, compressed .sav From scipy-svn at scipy.org Wed Aug 18 17:23:13 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Wed, 18 Aug 2010 16:23:13 -0500 (CDT) Subject: [Scipy-svn] r6651 - in trunk/scipy/io: . tests Message-ID: <20100818212313.73B2039CD3F@scipy.org> Author: matthew.brett at gmail.com Date: 2010-08-18 16:23:13 -0500 (Wed, 18 Aug 2010) New Revision: 6651 Added: trunk/scipy/io/idl.py Removed: trunk/scipy/io/idlsave.py Modified: trunk/scipy/io/__init__.py trunk/scipy/io/tests/test_idlsave.py Log: RF - move idlsave to idl, rename read to readsav Modified: trunk/scipy/io/__init__.py =================================================================== --- trunk/scipy/io/__init__.py 2010-08-18 21:23:07 UTC (rev 6650) +++ trunk/scipy/io/__init__.py 2010-08-18 21:23:13 UTC (rev 6651) @@ -17,7 +17,7 @@ import matlab.byteordercodes as byteordercodes from data_store import save_as_module from mmio import mminfo, mmread, mmwrite -import idlsave +from idl import readsav __all__ = filter(lambda s:not s.startswith('_'),dir()) from numpy.testing import Tester Copied: trunk/scipy/io/idl.py (from rev 6650, trunk/scipy/io/idlsave.py) =================================================================== --- trunk/scipy/io/idl.py (rev 0) +++ trunk/scipy/io/idl.py 2010-08-18 21:23:13 UTC (rev 6651) @@ -0,0 +1,779 @@ +# IDLSave - a python module to read IDL 'save' files +# Copyright (c) 2010 Thomas P. Robitaille + +# Many thanks to Craig Markwardt for publishing the Unofficial Format +# Specification for IDL .sav files, without which this Python module would not +# exist (http://cow.physics.wisc.edu/~craigm/idl/savefmt). + +# This code was developed by with permission from ITT Visual Information +# Systems. IDL(r) is a registered trademark of ITT Visual Information Systems, +# Inc. for their Interactive Data Language software. + +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +import struct +import numpy as np +import tempfile +import zlib +import warnings + +# Define the different data types that can be found in an IDL save file +DTYPE_DICT = {} +DTYPE_DICT[1] = '>u1' +DTYPE_DICT[2] = '>i2' +DTYPE_DICT[3] = '>i4' +DTYPE_DICT[4] = '>f4' +DTYPE_DICT[5] = '>f8' +DTYPE_DICT[6] = '>c8' +DTYPE_DICT[7] = '|O' +DTYPE_DICT[8] = '|O' +DTYPE_DICT[9] = '>c16' +DTYPE_DICT[12] = '>u2' +DTYPE_DICT[13] = '>u4' +DTYPE_DICT[14] = '>i8' +DTYPE_DICT[15] = '>u8' + +# Define the different record types that can be found in an IDL save file +RECTYPE_DICT = {} +RECTYPE_DICT[0] = "START_MARKER" +RECTYPE_DICT[1] = "COMMON_VARIABLE" +RECTYPE_DICT[2] = "VARIABLE" +RECTYPE_DICT[3] = "SYSTEM_VARIABLE" +RECTYPE_DICT[6] = "END_MARKER" +RECTYPE_DICT[10] = "TIMESTAMP" +RECTYPE_DICT[12] = "COMPILED" +RECTYPE_DICT[13] = "IDENTIFICATION" +RECTYPE_DICT[14] = "VERSION" +RECTYPE_DICT[15] = "HEAP_HEADER" +RECTYPE_DICT[16] = "HEAP_DATA" +RECTYPE_DICT[17] = "PROMOTE64" +RECTYPE_DICT[19] = "NOTICE" + +# Define a dictionary to contain structure definitions +STRUCT_DICT = {} + + +def _align_32(f): + '''Align to the next 32-bit position in a file''' + + pos = f.tell() + if pos % 4 <> 0: + f.seek(pos + 4 - pos % 4) + return + + +def _skip_bytes(f, n): + '''Skip `n` bytes''' + f.read(n) + return + + +def _read_bytes(f, n): + '''Read the next `n` bytes''' + return f.read(n) + + +def _read_byte(f): + '''Read a single byte''' + return np.uint8(struct.unpack('>B', f.read(4)[0])[0]) + + +def _read_long(f): + '''Read a signed 32-bit integer''' + return np.int32(struct.unpack('>l', f.read(4))[0]) + + +def _read_int16(f): + '''Read a signed 16-bit integer''' + return np.int16(struct.unpack('>h', f.read(4)[2:4])[0]) + + +def _read_int32(f): + '''Read a signed 32-bit integer''' + return np.int32(struct.unpack('>i', f.read(4))[0]) + + +def _read_int64(f): + '''Read a signed 64-bit integer''' + return np.int64(struct.unpack('>q', f.read(8))[0]) + + +def _read_uint16(f): + '''Read an unsigned 16-bit integer''' + return np.uint16(struct.unpack('>H', f.read(4)[2:4])[0]) + + +def _read_uint32(f): + '''Read an unsigned 32-bit integer''' + return np.uint32(struct.unpack('>I', f.read(4))[0]) + + +def _read_uint64(f): + '''Read an unsigned 64-bit integer''' + return np.uint64(struct.unpack('>Q', f.read(8))[0]) + + +def _read_float32(f): + '''Read a 32-bit float''' + return np.float32(struct.unpack('>f', f.read(4))[0]) + + +def _read_float64(f): + '''Read a 64-bit float''' + return np.float64(struct.unpack('>d', f.read(8))[0]) + + +class Pointer(object): + '''Class used to define pointers''' + + def __init__(self, index): + self.index = index + return + + +def _read_string(f): + '''Read a string''' + length = _read_long(f) + if length > 0: + chars = _read_bytes(f, length) + _align_32(f) + else: + chars = None + return np.str(chars) + + +def _read_string_data(f): + '''Read a data string (length is specified twice)''' + length = _read_long(f) + if length > 0: + length = _read_long(f) + string = _read_bytes(f, length) + _align_32(f) + else: + string = None + return np.str(string) + + +def _read_data(f, dtype): + '''Read a variable with a specified data type''' + if dtype==1: + if _read_int32(f) <> 1: + raise Exception("Error occured while reading byte variable") + return _read_byte(f) + elif dtype==2: + return _read_int16(f) + elif dtype==3: + return _read_int32(f) + elif dtype==4: + return _read_float32(f) + elif dtype==5: + return _read_float64(f) + elif dtype==6: + real = _read_float32(f) + imag = _read_float32(f) + return np.complex64(real + imag * 1j) + elif dtype==7: + return _read_string_data(f) + elif dtype==8: + raise Exception("Should not be here - please report this") + elif dtype==9: + real = _read_float64(f) + imag = _read_float64(f) + return np.complex128(real + imag * 1j) + elif dtype==10: + return Pointer(_read_int32(f)) + elif dtype==11: + raise Exception("Object reference type not implemented") + elif dtype==12: + return _read_uint16(f) + elif dtype==13: + return _read_uint32(f) + elif dtype==14: + return _read_int64(f) + elif dtype==15: + return _read_uint64(f) + else: + raise Exception("Unknown IDL type: %i - please report this" % dtype) + + +def _read_structure(f, array_desc, struct_desc): + ''' + Read a structure, with the array and structure descriptors given as + `array_desc` and `structure_desc` respectively. + ''' + + nrows = array_desc['nelements'] + ncols = struct_desc['ntags'] + columns = struct_desc['tagtable'] + + dtype = [] + for col in columns: + if col['structure'] or col['array']: + dtype.append(((col['name'].lower(), col['name']), np.object_)) + else: + if col['typecode'] in DTYPE_DICT: + dtype.append(((col['name'].lower(), col['name']), + DTYPE_DICT[col['typecode']])) + else: + raise Exception("Variable type %i not implemented" % + col['typecode']) + + structure = np.recarray((nrows, ), dtype=dtype) + + for i in range(nrows): + for col in columns: + dtype = col['typecode'] + if col['structure']: + structure[col['name']][i] = _read_structure(f, \ + struct_desc['arrtable'][col['name']], \ + struct_desc['structtable'][col['name']]) + elif col['array']: + structure[col['name']][i] = _read_array(f, dtype, \ + struct_desc['arrtable'][col['name']]) + else: + structure[col['name']][i] = _read_data(f, dtype) + + return structure + + +def _read_array(f, typecode, array_desc): + ''' + Read an array of type `typecode`, with the array descriptor given as + `array_desc`. + ''' + + if typecode in [1, 3, 4, 5, 6, 9, 13, 14, 15]: + + if typecode == 1: + nbytes = _read_int32(f) + if nbytes <> array_desc['nbytes']: + raise Exception("Error occured while reading byte array") + + # Read bytes as numpy array + array = np.fromstring(f.read(array_desc['nbytes']), \ + dtype=DTYPE_DICT[typecode]) + + elif typecode in [2, 12]: + + # These are 2 byte types, need to skip every two as they are not packed + + array = np.fromstring(f.read(array_desc['nbytes']*2), \ + dtype=DTYPE_DICT[typecode])[1::2] + + else: + + # Read bytes into list + array = [] + for i in range(array_desc['nelements']): + dtype = typecode + data = _read_data(f, dtype) + array.append(data) + + array = np.array(array, dtype=np.object_) + + # Reshape array if needed + if array_desc['ndims'] > 1: + dims = array_desc['dims'][:array_desc['ndims']] + dims.reverse() + array = array.reshape(dims) + + # Go to next alignment position + _align_32(f) + + return array + + +def _read_record(f): + '''Function to read in a full record''' + + record = {} + + recpos = f.tell() + record['rectype'] = _read_long(f) + + nextrec = _read_uint32(f) + nextrec += _read_uint32(f) * 2**32 + + _skip_bytes(f, 4) + + if not record['rectype'] in RECTYPE_DICT: + raise Exception("Unknown RECTYPE: %i" % record['rectype']) + + record['rectype'] = RECTYPE_DICT[record['rectype']] + + if record['rectype'] in ["VARIABLE", "HEAP_DATA"]: + + if record['rectype'] == "VARIABLE": + record['varname'] = _read_string(f) + else: + record['heap_index'] = _read_long(f) + _skip_bytes(f, 4) + + rectypedesc = _read_typedesc(f) + + varstart = _read_long(f) + if varstart <> 7: + raise Exception("VARSTART is not 7") + + if rectypedesc['structure']: + record['data'] = _read_structure(f, rectypedesc['array_desc'], \ + rectypedesc['struct_desc']) + elif rectypedesc['array']: + record['data'] = _read_array(f, rectypedesc['typecode'], \ + rectypedesc['array_desc']) + else: + dtype = rectypedesc['typecode'] + record['data'] = _read_data(f, dtype) + + elif record['rectype'] == "TIMESTAMP": + + _skip_bytes(f, 4*256) + record['date'] = _read_string(f) + record['user'] = _read_string(f) + record['host'] = _read_string(f) + + elif record['rectype'] == "VERSION": + + record['format'] = _read_long(f) + record['arch'] = _read_string(f) + record['os'] = _read_string(f) + record['release'] = _read_string(f) + + elif record['rectype'] == "IDENTIFICATON": + + record['author'] = _read_string(f) + record['title'] = _read_string(f) + record['idcode'] = _read_string(f) + + elif record['rectype'] == "NOTICE": + + record['notice'] = _read_string(f) + + elif record['rectype'] == "HEAP_HEADER": + + record['nvalues'] = _read_long(f) + record['indices'] = [] + for i in range(record['nvalues']): + record['indices'].append(_read_long(f)) + + elif record['rectype'] == "COMMONBLOCK": + + record['nvars'] = _read_long(f) + record['name'] = _read_string(f) + record['varnames'] = [] + for i in range(record['nvars']): + record['varnames'].append(_read_string(f)) + + elif record['rectype'] == "END_MARKER": + + record['end'] = True + + elif record['rectype'] == "UNKNOWN": + + warnings.warn("Skipping UNKNOWN record") + + elif record['rectype'] == "SYSTEM_VARIABLE": + + warnings.warn("Skipping SYSTEM_VARIABLE record") + + else: + + raise Exception("record['rectype']=%s not implemented" % \ + record['rectype']) + + f.seek(nextrec) + + return record + + +def _read_typedesc(f): + '''Function to read in a type descriptor''' + + typedesc = {} + + typedesc['typecode'] = _read_long(f) + typedesc['varflags'] = _read_long(f) + + if typedesc['varflags'] & 2 == 2: + raise Exception("System variables not implemented") + + typedesc['array'] = typedesc['varflags'] & 4 == 4 + typedesc['structure'] = typedesc['varflags'] & 32 == 32 + + if typedesc['structure']: + typedesc['array_desc'] = _read_arraydesc(f) + typedesc['struct_desc'] = _read_structdesc(f) + elif typedesc['array']: + typedesc['array_desc'] = _read_arraydesc(f) + + return typedesc + + +def _read_arraydesc(f): + '''Function to read in an array descriptor''' + + arraydesc = {} + + arraydesc['arrstart'] = _read_long(f) + + if arraydesc['arrstart'] == 8: + + _skip_bytes(f, 4) + + arraydesc['nbytes'] = _read_long(f) + arraydesc['nelements'] = _read_long(f) + arraydesc['ndims'] = _read_long(f) + + _skip_bytes(f, 8) + + arraydesc['nmax'] = _read_long(f) + + arraydesc['dims'] = [] + for d in range(arraydesc['nmax']): + arraydesc['dims'].append(_read_long(f)) + + elif arraydesc['arrstart'] == 18: + + warnings.warn("Using experimental 64-bit array read") + + _skip_bytes(f, 8) + + arraydesc['nbytes'] = _read_uint64(f) + arraydesc['nelements'] = _read_uint64(f) + arraydesc['ndims'] = _read_long(f) + + _skip_bytes(f, 8) + + arraydesc['nmax'] = 8 + + arraydesc['dims'] = [] + for d in range(arraydesc['nmax']): + v = _read_long(f) + if v <> 0: + raise Exception("Expected a zero in ARRAY_DESC") + arraydesc['dims'].append(_read_long(f)) + + else: + + raise Exception("Unknown ARRSTART: %i" % arraydesc['arrstart']) + + return arraydesc + + +def _read_structdesc(f): + '''Function to read in a structure descriptor''' + + structdesc = {} + + structstart = _read_long(f) + if structstart <> 9: + raise Exception("STRUCTSTART should be 9") + + structdesc['name'] = _read_string(f) + structdesc['predef'] = _read_long(f) + structdesc['ntags'] = _read_long(f) + structdesc['nbytes'] = _read_long(f) + + if structdesc['predef'] & 1 == 0: + + structdesc['tagtable'] = [] + for t in range(structdesc['ntags']): + structdesc['tagtable'].append(_read_tagdesc(f)) + + for tag in structdesc['tagtable']: + tag['name'] = _read_string(f) + + structdesc['arrtable'] = {} + for tag in structdesc['tagtable']: + if tag['array']: + structdesc['arrtable'][tag['name']] = _read_arraydesc(f) + + structdesc['structtable'] = {} + for tag in structdesc['tagtable']: + if tag['structure']: + structdesc['structtable'][tag['name']] = _read_structdesc(f) + + STRUCT_DICT[structdesc['name']] = (structdesc['tagtable'], \ + structdesc['arrtable'], \ + structdesc['structtable']) + + else: + + if not structdesc['name'] in STRUCT_DICT: + raise Exception("PREDEF=1 but can't find definition") + + structdesc['tagtable'], \ + structdesc['arrtable'], \ + structdesc['structtable'] = STRUCT_DICT[structdesc['name']] + + return structdesc + + +def _read_tagdesc(f): + '''Function to read in a tag descriptor''' + + tagdesc = {} + + tagdesc['offset'] = _read_long(f) + + if tagdesc['offset'] == -1: + tagdesc['offset'] = _read_uint64(f) + + tagdesc['typecode'] = _read_long(f) + tagflags = _read_long(f) + + tagdesc['array'] = tagflags & 4 == 4 + tagdesc['structure'] = tagflags & 32 == 32 + tagdesc['scalar'] = tagdesc['typecode'] in DTYPE_DICT + # Assume '10'x is scalar + + return tagdesc + + +class AttrDict(dict): + ''' + A case-insensitive dictionary with access via item, attribute, and call + notations: + + >>> d = AttrDict() + >>> d['Variable'] = 123 + >>> d['Variable'] + 123 + >>> d.Variable + 123 + >>> d.variable + 123 + >>> d('VARIABLE') + 123 + ''' + + def __init__(self, init={}): + dict.__init__(self, init) + + def __getitem__(self, name): + return super(AttrDict, self).__getitem__(name.lower()) + + def __setitem__(self, key, value): + return super(AttrDict, self).__setitem__(key.lower(), value) + + __getattr__ = __getitem__ + __setattr__ = __setitem__ + __call__ = __getitem__ + + +def readsav(file_name, idict=None, python_dict=False, + uncompressed_file_name=None, verbose=False): + ''' + Read an IDL .sav file + + Parameters + ---------- + file_name : str + Name of the IDL save file. + idict : dict, optional + Dictionary in which to insert .sav file variables + python_dict: bool, optional + By default, the object return is not a Python dictionary, but a + case-insensitive dictionary with item, attribute, and call access + to variables. To get a standard Python dictionary, set this option + to True. + uncompressed_file_name : str, optional + This option only has an effect for .sav files written with the + /compress option. If a file name is specified, compressed .sav + files are uncompressed to this file. Otherwise, readsav will use + the `tempfile` module to determine a temporary filename + automatically, and will remove the temporary file upon successfully + reading it in. + verbose : bool, optional + Whether to print out information about the save file, including + the records read, and available variables. + + Returns + ---------- + idl_dict : AttrDict or dict + If `python_dict` is set to False (default), this function returns a + case-insensitive dictionary with item, attribute, and call access + to variables. If `python_dict` is set to True, this function + returns a Python dictionary with all variable names in lowercase. + If `idict` was specified, then variables are written to the + dictionary specified, and the updated dictionary is returned. + ''' + + # Initialize record and variable holders + records = [] + if python_dict or idict: + variables = {} + else: + variables = AttrDict() + + # Open the IDL file + f = file(file_name, 'rb') + + # Read the signature, which should be 'SR' + signature = _read_bytes(f, 2) + if signature <> 'SR': + raise Exception("Invalid SIGNATURE: %s" % signature) + + # Next, the record format, which is '\x00\x04' for normal .sav + # files, and '\x00\x06' for compressed .sav files. + recfmt = _read_bytes(f, 2) + + if recfmt == '\x00\x04': + pass + + elif recfmt == '\x00\x06': + + if verbose: + print "IDL Save file is compressed" + + if uncompressed_file_name: + fout = file(uncompressed_file_name, 'w+b') + else: + fout = tempfile.NamedTemporaryFile(suffix='.sav') + + if verbose: + print " -> expanding to %s" % fout.name + + # Write header + fout.write('SR\x00\x04') + + # Cycle through records + while True: + + # Read record type + rectype = _read_long(f) + fout.write(struct.pack('>l', rectype)) + + # Read position of next record and return as int + nextrec = _read_uint32(f) + nextrec += _read_uint32(f) * 2**32 + + # Read the unknown 4 bytes + unknown = f.read(4) + + # Check if the end of the file has been reached + if RECTYPE_DICT[rectype] == 'END_MARKER': + fout.write(struct.pack('>I', int(nextrec) % 2**32)) + fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32))) + fout.write(unknown) + break + + # Find current position + pos = f.tell() + + # Decompress record + string = zlib.decompress(f.read(nextrec-pos)) + + # Find new position of next record + nextrec = fout.tell() + len(string) + 12 + + # Write out record + fout.write(struct.pack('>I', int(nextrec % 2**32))) + fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32))) + fout.write(unknown) + fout.write(string) + + # Close the original compressed file + f.close() + + # Set f to be the decompressed file, and skip the first four bytes + f = fout + f.seek(4) + + else: + raise Exception("Invalid RECFMT: %s" % recfmt) + + # Loop through records, and add them to the list + while True: + r = _read_record(f) + records.append(r) + if 'end' in r: + if r['end']: + break + + # Close the file + f.close() + + # Find heap data variables + heap = {} + for r in records: + if r['rectype'] == "HEAP_DATA": + heap[r['heap_index']] = r['data'] + + # Find all variables + for r in records: + if r['rectype'] == "VARIABLE": + while isinstance(r['data'], Pointer): + r['data'] = heap[r['data'].index] + variables[r['varname'].lower()] = r['data'] + + if verbose: + + # Print out timestamp info about the file + for record in records: + if record['rectype'] == "TIMESTAMP": + print "-"*50 + print "Date: %s" % record['date'] + print "User: %s" % record['user'] + print "Host: %s" % record['host'] + break + + # Print out version info about the file + for record in records: + if record['rectype'] == "VERSION": + print "-"*50 + print "Format: %s" % record['format'] + print "Architecture: %s" % record['arch'] + print "Operating System: %s" % record['os'] + print "IDL Version: %s" % record['release'] + break + + # Print out identification info about the file + for record in records: + if record['rectype'] == "IDENTIFICATON": + print "-"*50 + print "Author: %s" % record['author'] + print "Title: %s" % record['title'] + print "ID Code: %s" % record['idcode'] + break + + print "-"*50 + print "Successfully read %i records of which:" % \ + (len(records)) + + # Create convenience list of record types + rectypes = [r['rectype'] for r in records] + + for rt in set(rectypes): + if rt <> 'END_MARKER': + print " - %i are of type %s" % (rectypes.count(rt), rt) + print "-"*50 + + if 'VARIABLE' in rectypes: + print "Available variables:" + for var in variables: + print " - %s [%s]" % (var, type(variables[var])) + print "-"*50 + + if idict: + for var in variables: + idict[var] = variables[var] + return idict + else: + return variables Deleted: trunk/scipy/io/idlsave.py =================================================================== --- trunk/scipy/io/idlsave.py 2010-08-18 21:23:07 UTC (rev 6650) +++ trunk/scipy/io/idlsave.py 2010-08-18 21:23:13 UTC (rev 6651) @@ -1,779 +0,0 @@ -# IDLSave - a python module to read IDL 'save' files -# Copyright (c) 2010 Thomas P. Robitaille - -# Many thanks to Craig Markwardt for publishing the Unofficial Format -# Specification for IDL .sav files, without which this Python module would not -# exist (http://cow.physics.wisc.edu/~craigm/idl/savefmt). - -# This code was developed by with permission from ITT Visual Information -# Systems. IDL(r) is a registered trademark of ITT Visual Information Systems, -# Inc. for their Interactive Data Language software. - -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -import struct -import numpy as np -import tempfile -import zlib -import warnings - -# Define the different data types that can be found in an IDL save file -DTYPE_DICT = {} -DTYPE_DICT[1] = '>u1' -DTYPE_DICT[2] = '>i2' -DTYPE_DICT[3] = '>i4' -DTYPE_DICT[4] = '>f4' -DTYPE_DICT[5] = '>f8' -DTYPE_DICT[6] = '>c8' -DTYPE_DICT[7] = '|O' -DTYPE_DICT[8] = '|O' -DTYPE_DICT[9] = '>c16' -DTYPE_DICT[12] = '>u2' -DTYPE_DICT[13] = '>u4' -DTYPE_DICT[14] = '>i8' -DTYPE_DICT[15] = '>u8' - -# Define the different record types that can be found in an IDL save file -RECTYPE_DICT = {} -RECTYPE_DICT[0] = "START_MARKER" -RECTYPE_DICT[1] = "COMMON_VARIABLE" -RECTYPE_DICT[2] = "VARIABLE" -RECTYPE_DICT[3] = "SYSTEM_VARIABLE" -RECTYPE_DICT[6] = "END_MARKER" -RECTYPE_DICT[10] = "TIMESTAMP" -RECTYPE_DICT[12] = "COMPILED" -RECTYPE_DICT[13] = "IDENTIFICATION" -RECTYPE_DICT[14] = "VERSION" -RECTYPE_DICT[15] = "HEAP_HEADER" -RECTYPE_DICT[16] = "HEAP_DATA" -RECTYPE_DICT[17] = "PROMOTE64" -RECTYPE_DICT[19] = "NOTICE" - -# Define a dictionary to contain structure definitions -STRUCT_DICT = {} - - -def _align_32(f): - '''Align to the next 32-bit position in a file''' - - pos = f.tell() - if pos % 4 <> 0: - f.seek(pos + 4 - pos % 4) - return - - -def _skip_bytes(f, n): - '''Skip `n` bytes''' - f.read(n) - return - - -def _read_bytes(f, n): - '''Read the next `n` bytes''' - return f.read(n) - - -def _read_byte(f): - '''Read a single byte''' - return np.uint8(struct.unpack('>B', f.read(4)[0])[0]) - - -def _read_long(f): - '''Read a signed 32-bit integer''' - return np.int32(struct.unpack('>l', f.read(4))[0]) - - -def _read_int16(f): - '''Read a signed 16-bit integer''' - return np.int16(struct.unpack('>h', f.read(4)[2:4])[0]) - - -def _read_int32(f): - '''Read a signed 32-bit integer''' - return np.int32(struct.unpack('>i', f.read(4))[0]) - - -def _read_int64(f): - '''Read a signed 64-bit integer''' - return np.int64(struct.unpack('>q', f.read(8))[0]) - - -def _read_uint16(f): - '''Read an unsigned 16-bit integer''' - return np.uint16(struct.unpack('>H', f.read(4)[2:4])[0]) - - -def _read_uint32(f): - '''Read an unsigned 32-bit integer''' - return np.uint32(struct.unpack('>I', f.read(4))[0]) - - -def _read_uint64(f): - '''Read an unsigned 64-bit integer''' - return np.uint64(struct.unpack('>Q', f.read(8))[0]) - - -def _read_float32(f): - '''Read a 32-bit float''' - return np.float32(struct.unpack('>f', f.read(4))[0]) - - -def _read_float64(f): - '''Read a 64-bit float''' - return np.float64(struct.unpack('>d', f.read(8))[0]) - - -class Pointer(object): - '''Class used to define pointers''' - - def __init__(self, index): - self.index = index - return - - -def _read_string(f): - '''Read a string''' - length = _read_long(f) - if length > 0: - chars = _read_bytes(f, length) - _align_32(f) - else: - chars = None - return np.str(chars) - - -def _read_string_data(f): - '''Read a data string (length is specified twice)''' - length = _read_long(f) - if length > 0: - length = _read_long(f) - string = _read_bytes(f, length) - _align_32(f) - else: - string = None - return np.str(string) - - -def _read_data(f, dtype): - '''Read a variable with a specified data type''' - if dtype==1: - if _read_int32(f) <> 1: - raise Exception("Error occured while reading byte variable") - return _read_byte(f) - elif dtype==2: - return _read_int16(f) - elif dtype==3: - return _read_int32(f) - elif dtype==4: - return _read_float32(f) - elif dtype==5: - return _read_float64(f) - elif dtype==6: - real = _read_float32(f) - imag = _read_float32(f) - return np.complex64(real + imag * 1j) - elif dtype==7: - return _read_string_data(f) - elif dtype==8: - raise Exception("Should not be here - please report this") - elif dtype==9: - real = _read_float64(f) - imag = _read_float64(f) - return np.complex128(real + imag * 1j) - elif dtype==10: - return Pointer(_read_int32(f)) - elif dtype==11: - raise Exception("Object reference type not implemented") - elif dtype==12: - return _read_uint16(f) - elif dtype==13: - return _read_uint32(f) - elif dtype==14: - return _read_int64(f) - elif dtype==15: - return _read_uint64(f) - else: - raise Exception("Unknown IDL type: %i - please report this" % dtype) - - -def _read_structure(f, array_desc, struct_desc): - ''' - Read a structure, with the array and structure descriptors given as - `array_desc` and `structure_desc` respectively. - ''' - - nrows = array_desc['nelements'] - ncols = struct_desc['ntags'] - columns = struct_desc['tagtable'] - - dtype = [] - for col in columns: - if col['structure'] or col['array']: - dtype.append(((col['name'].lower(), col['name']), np.object_)) - else: - if col['typecode'] in DTYPE_DICT: - dtype.append(((col['name'].lower(), col['name']), - DTYPE_DICT[col['typecode']])) - else: - raise Exception("Variable type %i not implemented" % - col['typecode']) - - structure = np.recarray((nrows, ), dtype=dtype) - - for i in range(nrows): - for col in columns: - dtype = col['typecode'] - if col['structure']: - structure[col['name']][i] = _read_structure(f, \ - struct_desc['arrtable'][col['name']], \ - struct_desc['structtable'][col['name']]) - elif col['array']: - structure[col['name']][i] = _read_array(f, dtype, \ - struct_desc['arrtable'][col['name']]) - else: - structure[col['name']][i] = _read_data(f, dtype) - - return structure - - -def _read_array(f, typecode, array_desc): - ''' - Read an array of type `typecode`, with the array descriptor given as - `array_desc`. - ''' - - if typecode in [1, 3, 4, 5, 6, 9, 13, 14, 15]: - - if typecode == 1: - nbytes = _read_int32(f) - if nbytes <> array_desc['nbytes']: - raise Exception("Error occured while reading byte array") - - # Read bytes as numpy array - array = np.fromstring(f.read(array_desc['nbytes']), \ - dtype=DTYPE_DICT[typecode]) - - elif typecode in [2, 12]: - - # These are 2 byte types, need to skip every two as they are not packed - - array = np.fromstring(f.read(array_desc['nbytes']*2), \ - dtype=DTYPE_DICT[typecode])[1::2] - - else: - - # Read bytes into list - array = [] - for i in range(array_desc['nelements']): - dtype = typecode - data = _read_data(f, dtype) - array.append(data) - - array = np.array(array, dtype=np.object_) - - # Reshape array if needed - if array_desc['ndims'] > 1: - dims = array_desc['dims'][:array_desc['ndims']] - dims.reverse() - array = array.reshape(dims) - - # Go to next alignment position - _align_32(f) - - return array - - -def _read_record(f): - '''Function to read in a full record''' - - record = {} - - recpos = f.tell() - record['rectype'] = _read_long(f) - - nextrec = _read_uint32(f) - nextrec += _read_uint32(f) * 2**32 - - _skip_bytes(f, 4) - - if not record['rectype'] in RECTYPE_DICT: - raise Exception("Unknown RECTYPE: %i" % record['rectype']) - - record['rectype'] = RECTYPE_DICT[record['rectype']] - - if record['rectype'] in ["VARIABLE", "HEAP_DATA"]: - - if record['rectype'] == "VARIABLE": - record['varname'] = _read_string(f) - else: - record['heap_index'] = _read_long(f) - _skip_bytes(f, 4) - - rectypedesc = _read_typedesc(f) - - varstart = _read_long(f) - if varstart <> 7: - raise Exception("VARSTART is not 7") - - if rectypedesc['structure']: - record['data'] = _read_structure(f, rectypedesc['array_desc'], \ - rectypedesc['struct_desc']) - elif rectypedesc['array']: - record['data'] = _read_array(f, rectypedesc['typecode'], \ - rectypedesc['array_desc']) - else: - dtype = rectypedesc['typecode'] - record['data'] = _read_data(f, dtype) - - elif record['rectype'] == "TIMESTAMP": - - _skip_bytes(f, 4*256) - record['date'] = _read_string(f) - record['user'] = _read_string(f) - record['host'] = _read_string(f) - - elif record['rectype'] == "VERSION": - - record['format'] = _read_long(f) - record['arch'] = _read_string(f) - record['os'] = _read_string(f) - record['release'] = _read_string(f) - - elif record['rectype'] == "IDENTIFICATON": - - record['author'] = _read_string(f) - record['title'] = _read_string(f) - record['idcode'] = _read_string(f) - - elif record['rectype'] == "NOTICE": - - record['notice'] = _read_string(f) - - elif record['rectype'] == "HEAP_HEADER": - - record['nvalues'] = _read_long(f) - record['indices'] = [] - for i in range(record['nvalues']): - record['indices'].append(_read_long(f)) - - elif record['rectype'] == "COMMONBLOCK": - - record['nvars'] = _read_long(f) - record['name'] = _read_string(f) - record['varnames'] = [] - for i in range(record['nvars']): - record['varnames'].append(_read_string(f)) - - elif record['rectype'] == "END_MARKER": - - record['end'] = True - - elif record['rectype'] == "UNKNOWN": - - warnings.warn("Skipping UNKNOWN record") - - elif record['rectype'] == "SYSTEM_VARIABLE": - - warnings.warn("Skipping SYSTEM_VARIABLE record") - - else: - - raise Exception("record['rectype']=%s not implemented" % \ - record['rectype']) - - f.seek(nextrec) - - return record - - -def _read_typedesc(f): - '''Function to read in a type descriptor''' - - typedesc = {} - - typedesc['typecode'] = _read_long(f) - typedesc['varflags'] = _read_long(f) - - if typedesc['varflags'] & 2 == 2: - raise Exception("System variables not implemented") - - typedesc['array'] = typedesc['varflags'] & 4 == 4 - typedesc['structure'] = typedesc['varflags'] & 32 == 32 - - if typedesc['structure']: - typedesc['array_desc'] = _read_arraydesc(f) - typedesc['struct_desc'] = _read_structdesc(f) - elif typedesc['array']: - typedesc['array_desc'] = _read_arraydesc(f) - - return typedesc - - -def _read_arraydesc(f): - '''Function to read in an array descriptor''' - - arraydesc = {} - - arraydesc['arrstart'] = _read_long(f) - - if arraydesc['arrstart'] == 8: - - _skip_bytes(f, 4) - - arraydesc['nbytes'] = _read_long(f) - arraydesc['nelements'] = _read_long(f) - arraydesc['ndims'] = _read_long(f) - - _skip_bytes(f, 8) - - arraydesc['nmax'] = _read_long(f) - - arraydesc['dims'] = [] - for d in range(arraydesc['nmax']): - arraydesc['dims'].append(_read_long(f)) - - elif arraydesc['arrstart'] == 18: - - warnings.warn("Using experimental 64-bit array read") - - _skip_bytes(f, 8) - - arraydesc['nbytes'] = _read_uint64(f) - arraydesc['nelements'] = _read_uint64(f) - arraydesc['ndims'] = _read_long(f) - - _skip_bytes(f, 8) - - arraydesc['nmax'] = 8 - - arraydesc['dims'] = [] - for d in range(arraydesc['nmax']): - v = _read_long(f) - if v <> 0: - raise Exception("Expected a zero in ARRAY_DESC") - arraydesc['dims'].append(_read_long(f)) - - else: - - raise Exception("Unknown ARRSTART: %i" % arraydesc['arrstart']) - - return arraydesc - - -def _read_structdesc(f): - '''Function to read in a structure descriptor''' - - structdesc = {} - - structstart = _read_long(f) - if structstart <> 9: - raise Exception("STRUCTSTART should be 9") - - structdesc['name'] = _read_string(f) - structdesc['predef'] = _read_long(f) - structdesc['ntags'] = _read_long(f) - structdesc['nbytes'] = _read_long(f) - - if structdesc['predef'] & 1 == 0: - - structdesc['tagtable'] = [] - for t in range(structdesc['ntags']): - structdesc['tagtable'].append(_read_tagdesc(f)) - - for tag in structdesc['tagtable']: - tag['name'] = _read_string(f) - - structdesc['arrtable'] = {} - for tag in structdesc['tagtable']: - if tag['array']: - structdesc['arrtable'][tag['name']] = _read_arraydesc(f) - - structdesc['structtable'] = {} - for tag in structdesc['tagtable']: - if tag['structure']: - structdesc['structtable'][tag['name']] = _read_structdesc(f) - - STRUCT_DICT[structdesc['name']] = (structdesc['tagtable'], \ - structdesc['arrtable'], \ - structdesc['structtable']) - - else: - - if not structdesc['name'] in STRUCT_DICT: - raise Exception("PREDEF=1 but can't find definition") - - structdesc['tagtable'], \ - structdesc['arrtable'], \ - structdesc['structtable'] = STRUCT_DICT[structdesc['name']] - - return structdesc - - -def _read_tagdesc(f): - '''Function to read in a tag descriptor''' - - tagdesc = {} - - tagdesc['offset'] = _read_long(f) - - if tagdesc['offset'] == -1: - tagdesc['offset'] = _read_uint64(f) - - tagdesc['typecode'] = _read_long(f) - tagflags = _read_long(f) - - tagdesc['array'] = tagflags & 4 == 4 - tagdesc['structure'] = tagflags & 32 == 32 - tagdesc['scalar'] = tagdesc['typecode'] in DTYPE_DICT - # Assume '10'x is scalar - - return tagdesc - - -class AttrDict(dict): - ''' - A case-insensitive dictionary with access via item, attribute, and call - notations: - - >>> d = AttrDict() - >>> d['Variable'] = 123 - >>> d['Variable'] - 123 - >>> d.Variable - 123 - >>> d.variable - 123 - >>> d('VARIABLE') - 123 - ''' - - def __init__(self, init={}): - dict.__init__(self, init) - - def __getitem__(self, name): - return super(AttrDict, self).__getitem__(name.lower()) - - def __setitem__(self, key, value): - return super(AttrDict, self).__setitem__(key.lower(), value) - - __getattr__ = __getitem__ - __setattr__ = __setitem__ - __call__ = __getitem__ - - -def read(file_name, idict=None, python_dict=False, - uncompressed_file_name=None, verbose=False): - ''' - Read an IDL .sav file - - Parameters - ---------- - file_name : str - Name of the IDL save file. - idict : dict, optional - Dictionary in which to insert .sav file variables - python_dict: bool, optional - By default, the object return is not a Python dictionary, but a - case-insensitive dictionary with item, attribute, and call access - to variables. To get a standard Python dictionary, set this option - to True. - uncompressed_file_name : str, optional - This option only has an effect for .sav files written with the - /compress option. If a file name is specified, compressed .sav - files are uncompressed to this file. Otherwise, idlsave will use - the `tempfile` module to determine a temporary filename - automatically, and will remove the temporary file upon successfully - reading it in. - verbose : bool, optional - Whether to print out information about the save file, including - the records read, and available variables. - - Returns - ---------- - idl_dict : AttrDict or dict - If `python_dict` is set to False (default), this function returns a - case-insensitive dictionary with item, attribute, and call access - to variables. If `python_dict` is set to True, this function - returns a Python dictionary with all variable names in lowercase. - If `idict` was specified, then variables are written to the - dictionary specified, and the updated dictionary is returned. - ''' - - # Initialize record and variable holders - records = [] - if python_dict or idict: - variables = {} - else: - variables = AttrDict() - - # Open the IDL file - f = file(file_name, 'rb') - - # Read the signature, which should be 'SR' - signature = _read_bytes(f, 2) - if signature <> 'SR': - raise Exception("Invalid SIGNATURE: %s" % signature) - - # Next, the record format, which is '\x00\x04' for normal .sav - # files, and '\x00\x06' for compressed .sav files. - recfmt = _read_bytes(f, 2) - - if recfmt == '\x00\x04': - pass - - elif recfmt == '\x00\x06': - - if verbose: - print "IDL Save file is compressed" - - if uncompressed_file_name: - fout = file(uncompressed_file_name, 'w+b') - else: - fout = tempfile.NamedTemporaryFile(suffix='.sav') - - if verbose: - print " -> expanding to %s" % fout.name - - # Write header - fout.write('SR\x00\x04') - - # Cycle through records - while True: - - # Read record type - rectype = _read_long(f) - fout.write(struct.pack('>l', rectype)) - - # Read position of next record and return as int - nextrec = _read_uint32(f) - nextrec += _read_uint32(f) * 2**32 - - # Read the unknown 4 bytes - unknown = f.read(4) - - # Check if the end of the file has been reached - if RECTYPE_DICT[rectype] == 'END_MARKER': - fout.write(struct.pack('>I', int(nextrec) % 2**32)) - fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32))) - fout.write(unknown) - break - - # Find current position - pos = f.tell() - - # Decompress record - string = zlib.decompress(f.read(nextrec-pos)) - - # Find new position of next record - nextrec = fout.tell() + len(string) + 12 - - # Write out record - fout.write(struct.pack('>I', int(nextrec % 2**32))) - fout.write(struct.pack('>I', int((nextrec - (nextrec % 2**32)) / 2**32))) - fout.write(unknown) - fout.write(string) - - # Close the original compressed file - f.close() - - # Set f to be the decompressed file, and skip the first four bytes - f = fout - f.seek(4) - - else: - raise Exception("Invalid RECFMT: %s" % recfmt) - - # Loop through records, and add them to the list - while True: - r = _read_record(f) - records.append(r) - if 'end' in r: - if r['end']: - break - - # Close the file - f.close() - - # Find heap data variables - heap = {} - for r in records: - if r['rectype'] == "HEAP_DATA": - heap[r['heap_index']] = r['data'] - - # Find all variables - for r in records: - if r['rectype'] == "VARIABLE": - while isinstance(r['data'], Pointer): - r['data'] = heap[r['data'].index] - variables[r['varname'].lower()] = r['data'] - - if verbose: - - # Print out timestamp info about the file - for record in records: - if record['rectype'] == "TIMESTAMP": - print "-"*50 - print "Date: %s" % record['date'] - print "User: %s" % record['user'] - print "Host: %s" % record['host'] - break - - # Print out version info about the file - for record in records: - if record['rectype'] == "VERSION": - print "-"*50 - print "Format: %s" % record['format'] - print "Architecture: %s" % record['arch'] - print "Operating System: %s" % record['os'] - print "IDL Version: %s" % record['release'] - break - - # Print out identification info about the file - for record in records: - if record['rectype'] == "IDENTIFICATON": - print "-"*50 - print "Author: %s" % record['author'] - print "Title: %s" % record['title'] - print "ID Code: %s" % record['idcode'] - break - - print "-"*50 - print "Successfully read %i records of which:" % \ - (len(records)) - - # Create convenience list of record types - rectypes = [r['rectype'] for r in records] - - for rt in set(rectypes): - if rt <> 'END_MARKER': - print " - %i are of type %s" % (rectypes.count(rt), rt) - print "-"*50 - - if 'VARIABLE' in rectypes: - print "Available variables:" - for var in variables: - print " - %s [%s]" % (var, type(variables[var])) - print "-"*50 - - if idict: - for var in variables: - idict[var] = variables[var] - return idict - else: - return variables Modified: trunk/scipy/io/tests/test_idlsave.py =================================================================== --- trunk/scipy/io/tests/test_idlsave.py 2010-08-18 21:23:07 UTC (rev 6650) +++ trunk/scipy/io/tests/test_idlsave.py 2010-08-18 21:23:13 UTC (rev 6651) @@ -7,7 +7,7 @@ from numpy.testing import assert_equal, assert_array_equal, run_module_suite from nose.tools import assert_true -from scipy.io import idlsave +from scipy.io.idl import readsav def object_array(*args): @@ -39,7 +39,7 @@ def test_idict(self): custom_dict = {'a': np.int16(999)} original_id = id(custom_dict) - s = idlsave.read(path.join(DATA_PATH, 'scalar_byte.sav'), idict=custom_dict, verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_byte.sav'), idict=custom_dict, verbose=False) assert_equal(original_id, id(s)) assert_true('a' in s) assert_identical(s['a'], np.int16(999)) @@ -50,38 +50,38 @@ '''Test that scalar values are read in with the correct value and type''' def test_byte(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_byte.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_byte.sav'), verbose=False) assert_identical(s.i8u, np.uint8(234)) def test_int16(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_int16.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_int16.sav'), verbose=False) assert_identical(s.i16s, np.int16(-23456)) def test_int32(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_int32.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_int32.sav'), verbose=False) assert_identical(s.i32s, np.int32(-1234567890)) def test_float32(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_float32.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_float32.sav'), verbose=False) assert_identical(s.f32, np.float32(-3.1234567e+37)) def test_float64(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_float64.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_float64.sav'), verbose=False) assert_identical(s.f64, np.float64(-1.1976931348623157e+307)) def test_complex32(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_complex32.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_complex32.sav'), verbose=False) assert_identical(s.c32, np.complex64(3.124442e13-2.312442e31j)) def test_string(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_string.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_string.sav'), verbose=False) assert_identical(s.s, np.str("The quick brown fox jumps over the lazy python")) def test_structure(self): pass def test_complex64(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_complex64.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_complex64.sav'), verbose=False) assert_identical(s.c64, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j)) def test_heap_pointer(self): @@ -91,19 +91,19 @@ pass def test_uint16(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_uint16.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_uint16.sav'), verbose=False) assert_identical(s.i16u, np.uint16(65511)) def test_uint32(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_uint32.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_uint32.sav'), verbose=False) assert_identical(s.i32u, np.uint32(4294967233)) def test_int64(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_int64.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_int64.sav'), verbose=False) assert_identical(s.i64s, np.int64(-9223372036854774567)) def test_uint64(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_uint64.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_uint64.sav'), verbose=False) assert_identical(s.i64u, np.uint64(18446744073709529285)) @@ -111,7 +111,7 @@ '''Test that compressed .sav files can be read in''' def test_compressed(self): - s = idlsave.read(path.join(DATA_PATH, 'various_compressed.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'various_compressed.sav'), verbose=False) assert_identical(s.i8u, np.uint8(234)) assert_identical(s.f32, np.float32(-3.1234567e+37)) assert_identical(s.c64, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j)) @@ -126,35 +126,35 @@ '''Test that multi-dimensional arrays are read in with the correct dimensions''' def test_1d(self): - s = idlsave.read(path.join(DATA_PATH, 'array_float32_1d.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'array_float32_1d.sav'), verbose=False) assert_equal(s.array1d.shape, (123, )) def test_2d(self): - s = idlsave.read(path.join(DATA_PATH, 'array_float32_2d.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'array_float32_2d.sav'), verbose=False) assert_equal(s.array2d.shape, (22, 12)) def test_3d(self): - s = idlsave.read(path.join(DATA_PATH, 'array_float32_3d.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'array_float32_3d.sav'), verbose=False) assert_equal(s.array3d.shape, (11, 22, 12)) def test_4d(self): - s = idlsave.read(path.join(DATA_PATH, 'array_float32_4d.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'array_float32_4d.sav'), verbose=False) assert_equal(s.array4d.shape, (4, 5, 8, 7)) def test_5d(self): - s = idlsave.read(path.join(DATA_PATH, 'array_float32_5d.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'array_float32_5d.sav'), verbose=False) assert_equal(s.array5d.shape, (4, 3, 4, 6, 5)) def test_6d(self): - s = idlsave.read(path.join(DATA_PATH, 'array_float32_6d.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'array_float32_6d.sav'), verbose=False) assert_equal(s.array6d.shape, (3, 6, 4, 5, 3, 4)) def test_7d(self): - s = idlsave.read(path.join(DATA_PATH, 'array_float32_7d.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'array_float32_7d.sav'), verbose=False) assert_equal(s.array7d.shape, (2, 1, 2, 3, 4, 3, 2)) def test_8d(self): - s = idlsave.read(path.join(DATA_PATH, 'array_float32_8d.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'array_float32_8d.sav'), verbose=False) assert_equal(s.array8d.shape, (4, 3, 2, 1, 2, 3, 5, 4)) @@ -162,7 +162,7 @@ '''Test that structures are correctly read in''' def test_scalars(self): - s = idlsave.read(path.join(DATA_PATH, 'struct_scalars.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'struct_scalars.sav'), verbose=False) assert_identical(s.scalars.a, np.array(np.int16(1))) assert_identical(s.scalars.b, np.array(np.int32(2))) assert_identical(s.scalars.c, np.array(np.float32(3.))) @@ -171,7 +171,7 @@ assert_identical(s.scalars.f, np.array(np.complex64(-1.+3j))) def test_scalars_replicated(self): - s = idlsave.read(path.join(DATA_PATH, 'struct_scalars_replicated.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'struct_scalars_replicated.sav'), verbose=False) assert_identical(s.scalars_rep.a, np.repeat(np.int16(1), 5)) assert_identical(s.scalars_rep.b, np.repeat(np.int32(2), 5)) assert_identical(s.scalars_rep.c, np.repeat(np.float32(3.), 5)) @@ -180,7 +180,7 @@ assert_identical(s.scalars_rep.f, np.repeat(np.complex64(-1.+3j), 5)) def test_arrays(self): - s = idlsave.read(path.join(DATA_PATH, 'struct_arrays.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'struct_arrays.sav'), verbose=False) assert_array_identical(s.arrays.a[0], np.array([1, 2, 3], dtype=np.int16)) assert_array_identical(s.arrays.b[0], np.array([4., 5., 6., 7.], dtype=np.float32)) assert_array_identical(s.arrays.c[0], np.array([np.complex64(1+2j), np.complex64(7+8j)])) @@ -188,7 +188,7 @@ def test_arrays_replicated(self): - s = idlsave.read(path.join(DATA_PATH, 'struct_arrays_replicated.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'struct_arrays_replicated.sav'), verbose=False) # Check column types assert_true(s.arrays_rep.a.dtype.type is np.object_) @@ -214,7 +214,7 @@ '''Check that pointers in .sav files produce references to the same object in Python''' def test_pointers(self): - s = idlsave.read(path.join(DATA_PATH, 'scalar_heap_pointer.sav'), verbose=False) + s = readsav(path.join(DATA_PATH, 'scalar_heap_pointer.sav'), verbose=False) assert_identical(s.c64_pointer1, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j)) assert_identical(s.c64_pointer2, np.complex128(1.1987253647623157e+112-5.1987258887729157e+307j)) assert_true(s.c64_pointer1 is s.c64_pointer2) From scipy-svn at scipy.org Tue Aug 31 17:55:50 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 16:55:50 -0500 (CDT) Subject: [Scipy-svn] r6653 - in trunk/scipy/spatial: . tests Message-ID: <20100831215550.D63BA39CC7C@scipy.org> Author: ptvirtan Date: 2010-08-31 16:55:50 -0500 (Tue, 31 Aug 2010) New Revision: 6653 Added: trunk/scipy/spatial/generate_qhull.py trunk/scipy/spatial/qhull.pxd trunk/scipy/spatial/qhull.pyx trunk/scipy/spatial/qhull_blas.h trunk/scipy/spatial/tests/test_qhull.py Modified: trunk/scipy/spatial/SConscript trunk/scipy/spatial/__init__.py trunk/scipy/spatial/setup.py Log: spatial: add wrappers for qhull's Delaunay tesselation Add a wrapper for the Delaunay tesselation routine from Qhull. Modified: trunk/scipy/spatial/SConscript =================================================================== --- trunk/scipy/spatial/SConscript 2010-08-31 21:54:55 UTC (rev 6652) +++ trunk/scipy/spatial/SConscript 2010-08-31 21:55:50 UTC (rev 6653) @@ -10,3 +10,12 @@ env.NumpyPythonExtension('_distance_wrap', source = [join('src', 'distance_wrap.c'), join('src', 'distance.c')]) + +# Build qhull +src = [pjoin('qhull', 'src', s) for s in [ + 'geom.c', 'geom2.c', 'global.c', 'io.c', 'mem.c', + 'merge.c', 'poly.c', 'poly2.c', 'qset.c', 'user.c', + 'stat.c', 'qhull.c']] +qhullsrc = env.DistutilsStaticExtLibrary('qhullsrc', source=src) + +env.NumpyPythonExtension('qhull', source = 'qhull.c', LIBS="qhullsrc") Modified: trunk/scipy/spatial/__init__.py =================================================================== --- trunk/scipy/spatial/__init__.py 2010-08-31 21:54:55 UTC (rev 6652) +++ trunk/scipy/spatial/__init__.py 2010-08-31 21:55:50 UTC (rev 6653) @@ -5,6 +5,7 @@ from info import __doc__ from kdtree import * from ckdtree import * +from qhull import * __all__ = filter(lambda s:not s.startswith('_'),dir()) __all__ += ['distance'] Added: trunk/scipy/spatial/generate_qhull.py =================================================================== --- trunk/scipy/spatial/generate_qhull.py (rev 0) +++ trunk/scipy/spatial/generate_qhull.py 2010-08-31 21:55:50 UTC (rev 6653) @@ -0,0 +1,29 @@ +#!/usr/bin/env python +import tempfile +import subprocess +import os +import sys +import re +import shutil + +tmp_dir = tempfile.mkdtemp() +try: + # Run Cython + dst_fn = os.path.join(tmp_dir, 'qhull.c') + ret = subprocess.call(['cython', '-o', dst_fn, 'qhull.pyx']) + if ret != 0: + sys.exit(ret) + + # Strip comments + f = open(dst_fn, 'r') + text = f.read() + f.close() + + r = re.compile(r'/\*(.*?)\*/', re.S) + + text = r.sub('', text) + f = open('qhull.c', 'w') + f.write(text) + f.close() +finally: + shutil.rmtree(tmp_dir) Property changes on: trunk/scipy/spatial/generate_qhull.py ___________________________________________________________________ Name: svn:executable + * Added: trunk/scipy/spatial/qhull.pxd =================================================================== --- trunk/scipy/spatial/qhull.pxd (rev 0) +++ trunk/scipy/spatial/qhull.pxd 2010-08-31 21:55:50 UTC (rev 6653) @@ -0,0 +1,89 @@ +# -*-cython-*- +""" +Qhull shared definitions, for use by other Cython modules + +""" +# +# Copyright (C) Pauli Virtanen, 2010. +# +# Distributed under the same BSD license as Scipy. +# + +cdef extern from "stdlib.h": + void *malloc(int size) + void free(void *ptr) + +cdef extern from "numpy/ndarraytypes.h": + cdef enum: + NPY_MAXDIMS + +ctypedef struct DelaunayInfo_t: + int ndim + int npoints + int nsimplex + double *points + int *vertices + int *neighbors + double *equations + double *transform + int *vertex_to_simplex + double paraboloid_scale + double paraboloid_shift + double *max_bound + double *min_bound + +cdef DelaunayInfo_t *_get_delaunay_info(obj, int compute_transform, + int compute_vertex_to_simplex) + +# +# N-D geometry +# + +cdef int _barycentric_inside(int ndim, double *transform, + double *x, double *c, double eps) nogil + +cdef void _barycentric_coordinate_single(int ndim, double *transform, + double *x, double *c, int i) nogil + +cdef void _barycentric_coordinates(int ndim, double *transform, + double *x, double *c) nogil + +# +# N+1-D geometry +# + +cdef void _lift_point(DelaunayInfo_t *d, double *x, double *z) nogil + +cdef double _distplane(DelaunayInfo_t *d, int isimplex, double *point) nogil + +# +# Finding simplices +# + +cdef int _is_point_fully_outside(DelaunayInfo_t *d, double *x, double eps) nogil + +cdef int _find_simplex_bruteforce(DelaunayInfo_t *d, double *c, double *x, + double eps) nogil + +cdef int _find_simplex_directed(DelaunayInfo_t *d, double *c, double *x, + int *start, double eps) nogil + +cdef int _find_simplex(DelaunayInfo_t *d, double *c, double *x, int *start, + double eps) nogil + +# +# Walking ridges connected to a vertex +# + +ctypedef struct RidgeIter2D_t: + DelaunayInfo_t *info + int vertex + int edge + int vertex2 + int triangle + int start_triangle + int start_edge + +cdef void _RidgeIter2D_init(RidgeIter2D_t *it, DelaunayInfo_t *d, + int vertex) nogil +cdef void _RidgeIter2D_next(RidgeIter2D_t *it) nogil Added: trunk/scipy/spatial/qhull.pyx =================================================================== --- trunk/scipy/spatial/qhull.pyx (rev 0) +++ trunk/scipy/spatial/qhull.pyx 2010-08-31 21:55:50 UTC (rev 6653) @@ -0,0 +1,1160 @@ +""" +Wrappers for Qhull triangulation, plus some additional N-D geometry utilities + +.. versionadded:: 0.9 + +""" +# +# Copyright (C) Pauli Virtanen, 2010. +# +# Distributed under the same BSD license as Scipy. +# + +import threading +import numpy as np +cimport numpy as np +cimport cython +cimport qhull + +__all__ = ['Delaunay', 'tsearch'] + +#------------------------------------------------------------------------------ +# Qhull interface +#------------------------------------------------------------------------------ + +cdef extern from "stdio.h": + extern void *stdin + extern void *stderr + extern void *stdout + +cdef extern from "qhull/src/qset.h": + ctypedef union setelemT: + void *p + int i + + ctypedef struct setT: + int maxsize + setelemT e[1] + +cdef extern from "qhull/src/qhull.h": + ctypedef double realT + ctypedef double coordT + ctypedef double pointT + ctypedef int boolT + ctypedef unsigned int flagT + + ctypedef struct facetT: + coordT offset + coordT *center + coordT *normal + facetT *next + facetT *previous + unsigned id + setT *vertices + setT *neighbors + flagT simplicial + flagT flipped + flagT upperdelaunay + + ctypedef struct vertexT: + vertexT *next + vertexT *previous + unsigned int id, visitid + pointT *point + setT *neighbours + + ctypedef struct qhT: + boolT DELAUNAY + boolT SCALElast + boolT KEEPcoplanar + boolT MERGEexact + boolT NOerrexit + boolT PROJECTdelaunay + boolT ATinfinity + int normal_size + char *qhull_command + facetT *facet_list + facetT *facet_tail + int num_facets + unsigned int facet_id + pointT *first_point + pointT *input_points + realT last_low + realT last_high + realT last_newhigh + realT max_outside + realT MINoutside + realT DISTround + + + extern qhT qh_qh + extern int qh_PRINToff + extern int qh_ALL + + void qh_init_A(void *inp, void *out, void *err, int argc, char **argv) + void qh_init_B(realT *points, int numpoints, int dim, boolT ismalloc) + void qh_checkflags(char *, char *) + void qh_initflags(char *) + void qh_option(char *, char*, char* ) + void qh_freeqhull(boolT) + void qh_memfreeshort(int *curlong, int *totlong) + void qh_qhull() + void qh_check_output() + void qh_produce_output() + void qh_triangulate() + void qh_checkpolygon() + void qh_findgood_all() + void qh_appendprint(int format) + realT *qh_readpoints(int* num, int *dim, boolT* ismalloc) + int qh_new_qhull(int dim, int numpoints, realT *points, + boolT ismalloc, char* qhull_cmd, void *outfile, + void *errfile) + int qh_pointid(pointT *point) + +# Qhull is not threadsafe: needs locking +_qhull_lock = threading.Lock() + + +#------------------------------------------------------------------------------ +# LAPACK interface +#------------------------------------------------------------------------------ + +cdef extern from "qhull_blas.h": + void qh_dgesv(int *n, int *nrhs, double *a, int *lda, int *ipiv, + double *b, int *ldb, int *info) + + +#------------------------------------------------------------------------------ +# Delaunay triangulation using Qhull +#------------------------------------------------------------------------------ + +def _construct_delaunay(np.ndarray[np.double_t, ndim=2] points): + """ + Perform Delaunay triangulation of the given set of points. + + """ + + # Run qhull with the options + # + # - d: perform delaunay triangulation + # - Qbb: scale last coordinate for Delaunay + # - Qz: reduces Delaunay precision errors for cospherical sites + # - Qt: output only simplical facets (can produce degenerate 0-area ones) + # + cdef char *options = "qhull d Qz Qbb Qt" + cdef int curlong, totlong + cdef int dim + cdef int numpoints + cdef int exitcode + + points = np.ascontiguousarray(points) + numpoints = points.shape[0] + dim = points.shape[1] + + if numpoints <= 0: + raise ValueError("No points to triangulate") + + if dim < 2: + raise ValueError("Need at least 2-D data to triangulate") + + _qhull_lock.acquire() + try: + qh_qh.NOerrexit = 1 + exitcode = qh_new_qhull(dim, numpoints, points.data, 0, + options, NULL, stderr) + try: + if exitcode != 0: + raise RuntimeError("Qhull error") + + qh_triangulate() # get rid of non-simplical facets + + if qh_qh.SCALElast: + paraboloid_scale = qh_qh.last_newhigh / ( + qh_qh.last_high - qh_qh.last_low) + paraboloid_shift = - qh_qh.last_low * paraboloid_scale + else: + paraboloid_scale = 1.0 + paraboloid_shift = 0.0 + + vertices, neighbors, equations = \ + _qhull_get_facet_array(dim, numpoints) + + return (vertices, neighbors, equations, + paraboloid_scale, paraboloid_shift) + finally: + qh_freeqhull(0) + qh_memfreeshort(&curlong, &totlong) + if curlong != 0 or totlong != 0: + raise RuntimeError("qhull: did not free %d bytes (%d pieces)" % + (totlong, curlong)) + finally: + _qhull_lock.release() + + +def _qhull_get_facet_array(int ndim, int numpoints): + """ + Return array of simplical facets currently in Qhull. + + Returns + ------- + vertices : array of int, shape (nfacets, ndim+1) + Indices of coordinates of vertices forming the simplical facets + neighbors : array of int, shape (nfacets, ndim) + Indices of neighboring facets. The kth neighbor is opposite + the kth vertex, and the first neighbor is the horizon facet + for the first vertex. + + Facets extending to infinity are denoted with index -1. + + """ + + cdef facetT* facet + cdef facetT* neighbor + cdef vertexT *vertex + cdef int i, j, point + cdef np.ndarray[np.int_t, ndim=2] vertices + cdef np.ndarray[np.int_t, ndim=2] neighbors + cdef np.ndarray[np.double_t, ndim=2] equations + cdef np.ndarray[np.int_t, ndim=1] id_map + + id_map = np.empty((qh_qh.facet_id,), dtype=np.int) + id_map.fill(-1) + + # Compute facet indices + facet = qh_qh.facet_list + j = 0 + while facet and facet.next: + if facet.simplicial and not facet.upperdelaunay: + id_map[facet.id] = j + j += 1 + facet = facet.next + + # Allocate output + vertices = np.zeros((j, ndim+1), dtype=np.int) + neighbors = np.zeros((j, ndim+1), dtype=np.int) + equations = np.zeros((j, ndim+2), dtype=np.double) + + # Retrieve facet information + facet = qh_qh.facet_list + j = 0 + while facet and facet.next: + if not facet.simplicial: + raise ValueError("non-simplical facet encountered") + + if facet.upperdelaunay: + facet = facet.next + continue + + # Save vertex info + for i in xrange(ndim+1): + vertex = facet.vertices.e[i].p + point = qh_pointid(vertex.point) + vertices[j, i] = point + + # Save neighbor info + for i in xrange(ndim+1): + neighbor = facet.neighbors.e[i].p + neighbors[j,i] = id_map[neighbor.id] + + # Save simplex equation info + for i in xrange(ndim+1): + equations[j,i] = facet.normal[i] + equations[j,ndim+1] = facet.offset + + j += 1 + facet = facet.next + + return vertices, neighbors, equations + + +#------------------------------------------------------------------------------ +# Barycentric coordinates +#------------------------------------------------------------------------------ + + at cython.boundscheck(False) +def _get_barycentric_transforms(np.ndarray[np.double_t, ndim=2] points, + np.ndarray[np.int_t, ndim=2] vertices): + """ + Compute barycentric affine coordinate transformations for given + simplices. + + Returns + ------- + Tinvs : array, shape (nsimplex, ndim+1, ndim) + Barycentric transforms for each simplex. + + Tinvs[i,:ndim,:ndim] contains inverse of the matrix ``T``, + and Tinvs[i,ndim,:] contains the vector ``r_n`` (see below). + + Notes + ----- + Barycentric transform from ``x`` to ``c`` is defined by:: + + T c = x - r_n + + where the ``r_1, ..., r_n`` are the vertices of the simplex. + The matrix ``T`` is defined by the condition:: + + T e_j = r_j - r_n + + where ``e_j`` is the unit axis vector, e.g, ``e_2 = [0,1,0,0,...]`` + This implies that ``T_ij = (r_j - r_n)_i``. + + For the barycentric transforms, we need to compute the inverse + matrix ``T^-1`` and store the vectors ``r_n`` for each vertex. + These are stacked into the `Tinvs` returned. + + """ + + cdef np.ndarray[np.double_t, ndim=2] T + cdef np.ndarray[np.double_t, ndim=3] Tinvs + cdef int ivertex + cdef int i, j, n, nrhs, lda, ldb, info + cdef int ipiv[NPY_MAXDIMS+1] + cdef int ndim, nvertex + cdef double nan + + cdef double x1, x2, x3 + cdef double y1, y2, y3 + cdef double det + + nan = np.nan + ndim = points.shape[1] + nvertex = vertices.shape[0] + + T = np.zeros((ndim, ndim), dtype=np.double) + Tinvs = np.zeros((nvertex, ndim+1, ndim), dtype=np.double) + + for ivertex in xrange(nvertex): + if ndim == 2: + # Manual unrolling of the generic barycentric transform + # code below. This is roughly 3.5x faster than the generic + # implementation; however, the time taken here is in any + # case a small fraction of `qh_new_qhull`, so optimization + # here is probably not very important. + + x1 = points[vertices[ivertex,0],0] + x2 = points[vertices[ivertex,1],0] + x3 = points[vertices[ivertex,2],0] + + y1 = points[vertices[ivertex,0],1] + y2 = points[vertices[ivertex,1],1] + y3 = points[vertices[ivertex,2],1] + + x1 -= x3 + x2 -= x3 + + y1 -= y3 + y2 -= y3 + + det = x1*y2 - x2*y1 + + if det == 0: + info = 1 + else: + info = 0 + Tinvs[ivertex,0,0] = y2/det + Tinvs[ivertex,0,1] = -x2/det + Tinvs[ivertex,1,0] = -y1/det + Tinvs[ivertex,1,1] = x1/det + Tinvs[ivertex,2,0] = x3 + Tinvs[ivertex,2,1] = y3 + else: + # General dimensions + + for i in xrange(ndim): + Tinvs[ivertex,ndim,i] = points[vertices[ivertex,ndim],i] + for j in xrange(ndim): + T[i,j] = (points[vertices[ivertex,j],i] + - Tinvs[ivertex,ndim,i]) + Tinvs[ivertex,i,i] = 1 + + n = ndim + nrhs = ndim + lda = ndim + ldb = ndim + qh_dgesv(&n, &nrhs, T.data, &lda, ipiv, + (Tinvs.data) + ndim*(ndim+1)*ivertex, &ldb, &info) + + if info != 0: + # degenerate simplex + for i in xrange(ndim+1): + for j in xrange(ndim): + Tinvs[ivertex,i,j] = nan + + return Tinvs + +cdef int _barycentric_inside(int ndim, double *transform, + double *x, double *c, double eps) nogil: + """ + Check whether point is inside a simplex, using barycentric + coordinates. `c` will be filled with barycentric coordinates, if + the point happens to be inside. + + """ + cdef int i, j + c[ndim] = 1.0 + for i in xrange(ndim): + c[i] = 0 + for j in xrange(ndim): + c[i] += transform[ndim*i + j] * (x[j] - transform[ndim*ndim + j]) + c[ndim] -= c[i] + + if not (-eps <= c[i] <= 1 + eps): + return 0 + if not (-eps <= c[ndim] <= 1 + eps): + return 0 + return 1 + +cdef void _barycentric_coordinate_single(int ndim, double *transform, + double *x, double *c, int i) nogil: + """ + Compute a single barycentric coordinate. + + Before the ndim+1'th coordinate can be computed, the other must have + been computed earlier. + + """ + cdef int j + + if i == ndim: + c[ndim] = 1.0 + for j in xrange(ndim): + c[ndim] -= c[j] + else: + c[i] = 0 + for j in xrange(ndim): + c[i] += transform[ndim*i + j] * (x[j] - transform[ndim*ndim + j]) + +cdef void _barycentric_coordinates(int ndim, double *transform, + double *x, double *c) nogil: + """ + Compute barycentric coordinates. + + """ + cdef int i, j + c[ndim] = 1.0 + for i in xrange(ndim): + c[i] = 0 + for j in xrange(ndim): + c[i] += transform[ndim*i + j] * (x[j] - transform[ndim*ndim + j]) + c[ndim] -= c[i] + + +#------------------------------------------------------------------------------ +# N-D geometry +#------------------------------------------------------------------------------ + +cdef void _lift_point(DelaunayInfo_t *d, double *x, double *z) nogil: + cdef int i + z[d.ndim] = 0 + for i in xrange(d.ndim): + z[i] = x[i] + z[d.ndim] += x[i]**2 + z[d.ndim] *= d.paraboloid_scale + z[d.ndim] += d.paraboloid_shift + +cdef double _distplane(DelaunayInfo_t *d, int isimplex, double *point) nogil: + """ + qh_distplane + """ + cdef double dist + cdef int k + dist = d.equations[isimplex*(d.ndim+2) + d.ndim+1] + for k in xrange(d.ndim+1): + dist += d.equations[isimplex*(d.ndim+2) + k] * point[k] + return dist + + +#------------------------------------------------------------------------------ +# Iterating over ridges connected to a vertex in 2D +#------------------------------------------------------------------------------ + +cdef void _RidgeIter2D_init(RidgeIter2D_t *it, DelaunayInfo_t *d, + int vertex) nogil: + """ + Start iteration over all triangles connected to the given vertex. + + """ + + cdef double c[3] + cdef int k, ivertex, start + + start = 0 + it.info = d + it.vertex = vertex + it.triangle = d.vertex_to_simplex[vertex] + it.start_triangle = it.triangle + + if it.triangle != -1: + # find some edge connected to this vertex; start from -1 edges + for k in xrange(3): + ivertex = it.info.vertices[it.triangle*3 + k] + if ivertex != vertex: + it.vertex2 = ivertex + it.edge = k + it.start_edge = k + break + else: + it.start_edge = -1 + it.edge = -1 + +cdef void _RidgeIter2D_next(RidgeIter2D_t *it) nogil: + cdef int itri, k, ivertex + + # + # Remember: k-th edge and k-th neigbour are opposite vertex k; + # imagine now we are iterating around vertex `O` + # + # .O------, + # ./ |\. | + # ./ | \. | + # \ | \. | + # \ |k \. | + # \ | \.| + # `+------k + # + + # jump to the next triangle + itri = it.info.neighbors[it.triangle*3 + it.edge] + + # if it's outside triangulation, restart it to the opposite direction + if itri == -1: + if it.start_edge == -1: + # we already did that -> we have iterated over everything + it.edge = -1 + return + + for k in xrange(3): + ivertex = it.info.vertices[it.triangle*3 + k] + if ivertex != it.vertex and k != it.start_edge: + it.edge = k + it.vertex2 = ivertex + break + + it.start_edge = -1 + return + + # Find at which edge we are now: + # + # it.vertex + # O-------k------. + # | \- / + # | \- E B / + # | \- / + # | A \- / + # +---------? + # + # A = it.triangle + # B = itri + # E = it.edge + # O = it.vertex + # + for k in xrange(3): + ivertex = it.info.vertices[itri*3 + k] + if it.info.neighbors[itri*3 + k] != it.triangle and \ + ivertex != it.vertex: + it.edge = k + it.vertex2 = ivertex + break + + it.triangle = itri + + # check termination + if it.triangle == it.start_triangle: + it.edge = -1 + return + +#------------------------------------------------------------------------------ +# Finding simplices +#------------------------------------------------------------------------------ + +cdef int _is_point_fully_outside(DelaunayInfo_t *d, double *x, + double eps) nogil: + """ + Is the point outside the bounding box of the triangulation? + + """ + + cdef int i + for i in xrange(d.ndim): + if x[i] < d.min_bound[i] - eps or x[i] > d.max_bound[i] + eps: + return 1 + return 0 + +cdef int _find_simplex_bruteforce(DelaunayInfo_t *d, double *c, + double *x, double eps) nogil: + """ + Find simplex containing point `x` by going through all simplices. + + """ + cdef int inside, isimplex + + if _is_point_fully_outside(d, x, eps): + return -1 + + for isimplex in xrange(d.nsimplex): + inside = _barycentric_inside( + d.ndim, + d.transform + isimplex*d.ndim*(d.ndim+1), + x, c, eps) + + if inside: + return isimplex + return -1 + +cdef int _find_simplex_directed(DelaunayInfo_t *d, double *c, + double *x, int *start, double eps) nogil: + """ + Find simplex containing point `x` via a directed walk in the tesselation. + + If the simplex is found, the array `c` is filled with the corresponding + barycentric coordinates. + + Notes + ----- + + The idea here is the following: + + 1) In a simplex, the k-th neighbour is opposite the k-th vertex. + Call the ridge between them the k-th ridge. + + 2) If the k-th barycentric coordinate of the target point is negative, + then the k-th vertex and the target point lie on the opposite sides + of the k-th ridge. + + 3) Consequently, the k-th neighbour simplex is *closer* to the target point + than the present simplex, if projected on the normal of the k-th ridge. + + 4) In a regular tesselation, hopping to any such direction is OK. + + Also, if one of the negative-coordinate neighbors happens to be -1, + then the target point is outside the tesselation (because the + tesselation is convex!). + + 5) If all barycentric coordinates are in [-eps, 1+eps], we have found the + simplex containing the target point. + + 6) If all barycentric coordinates are non-negative but 5) is not true, + we are in an inconsistent situation -- this should never happen. + + """ + cdef int k, m, ndim, inside, isimplex + cdef double *transform + cdef double v + + ndim = d.ndim + isimplex = start[0] + + if isimplex < 0 or isimplex >= d.nsimplex: + isimplex = 0 + + while isimplex != -1: + transform = d.transform + isimplex*ndim*(ndim+1) + + inside = 1 + for k in xrange(ndim+1): + _barycentric_coordinate_single(ndim, transform, x, c, k) + + if c[k] < -eps: + # The target point is in the direction of neighbor `k`! + + m = d.neighbors[(ndim+1)*isimplex + k] + if m == -1: + # The point is outside the triangulation: bail out + start[0] = isimplex + return -1 + + # Check that the target simplex is not degenerate. + v = d.transform[m*ndim*(ndim+1)] + if v != v: + # nan + continue + else: + isimplex = m + inside = -1 + break + elif c[k] > 1 + eps: + # we're outside this simplex + inside = 0 + + if inside == -1: + # hopped to another simplex + continue + elif inside == 1: + # we've found the right one! + break + else: + # we've failed utterly (degenerate simplices in the way). + # fall back to brute force + isimplex = _find_simplex_bruteforce(d, c, x, eps) + break + + start[0] = isimplex + return isimplex + +cdef int _find_simplex(DelaunayInfo_t *d, double *c, + double *x, int *start, double eps) nogil: + """ + Find simplex containing point `x` by walking the triangulation. + + Notes + ----- + This algorithm is similar as used by ``qh_findbest``. The idea + is the following: + + 1. Delaunay triangulation is a projection of the lower half of a convex + hull, of points lifted on a paraboloid. + + Simplices in the triangulation == facets on the convex hull. + + 2. If a point belongs to a given simplex in the triangulation, + its image on the paraboloid is on the positive side of + the corresponding facet. + + 3. However, it is not necessarily the *only* such facet. + + 4. Also, it is not necessarily the facet whose hyperplane distance + to the point on the paraboloid is the largest. + + ..note:: + + If I'm not mistaken, `qh_findbestfacet` finds a facet for + which the plane distance is maximized -- so it doesn't always + return the simplex containing the point given. For example: + + >>> p = np.array([(1 - 1e-4, 0.1)]) + >>> points = np.array([(0,0), (1, 1), (1, 0), (0.99189033, 0.37674127), + ... (0.99440079, 0.45182168)], dtype=np.double) + >>> tri = qhull.delaunay(points) + >>> tri.vertices + array([[4, 1, 0], + [4, 2, 1], + [3, 2, 0], + [3, 4, 0], + [3, 4, 2]]) + >>> dist = qhull.plane_distance(tri, p) + >>> dist + array([[-0.12231439, 0.00184863, 0.01049659, -0.04714842, + 0.00425905]]) + >>> tri.vertices[dist.argmax()] + array([3, 2, 0] + + Now, the maximally positive-distant simplex is [3, 2, 0], although + the simplex containing the point is [4, 2, 1]. + + In this algorithm, we walk around the tesselation trying to locate + a positive-distant facet. After finding one, we fall back to a + directed search. + + """ + cdef int isimplex, i, j, k, inside, ineigh, neighbor_found + cdef int ndim + cdef double z[NPY_MAXDIMS+1] + cdef double best_dist, dist + cdef int changed + + if _is_point_fully_outside(d, x, eps): + return -1 + if d.nsimplex <= 0: + return -1 + + ndim = d.ndim + isimplex = start[0] + + if isimplex < 0 or isimplex >= d.nsimplex: + isimplex = 0 + + # Lift point to paraboloid + _lift_point(d, x, z) + + # Walk the tesselation searching for a facet with a positive planar distance + best_dist = _distplane(d, isimplex, z) + changed = 1 + while changed: + if best_dist > 0: + break + changed = 0 + for k in xrange(ndim+1): + ineigh = d.neighbors[(ndim+1)*isimplex + k] + if ineigh == -1: + continue + dist = _distplane(d, ineigh, z) + if dist > best_dist: + # Note: this is intentional: we jump in the middle of the cycle, + # and continue the cycle from the next k. + # + # This apparently sweeps the different directions more + # efficiently. We don't need full accuracy, since we do + # a directed search afterwards in any case. + isimplex = ineigh + best_dist = dist + changed = 1 + + # We should now be somewhere near the simplex containing the point, + # locate it with a directed search + start[0] = isimplex + return _find_simplex_directed(d, c, x, start, eps) + + +#------------------------------------------------------------------------------ +# Delaunay triangulation interface, for Python +#------------------------------------------------------------------------------ + +class Delaunay(object): + """ + Delaunay(points) + + Delaunay tesselation in N dimensions + + .. versionadded:: 0.9 + + Parameters + ---------- + points : ndarray of floats, shape (npoints, ndim) + Coordinates of points to triangulate + + Attributes + ---------- + points : ndarray of double, shape (npoints, ndim) + Points in the triangulation + vertices : ndarray of ints, shape (nsimplex, ndim+1) + Indices of vertices forming simplices in the triangulation + neighbors : ndarray of ints, shape (nsimplex, ndim+1) + Indices of neighbor simplices for each simplex. + The kth neighbor is opposite to the kth vertex. + For simplices at the boundary, -1 denotes no neighbor. + equations : ndarray of double, shape (nsimplex, ndim+2) + [normal, offset] forming the hyperplane equation of the facet + on the paraboloid. (See [Qhull]_ documentation for more.) + paraboloid_scale, paraboloid_shift : float + Scale and shift for the extra paraboloid dimension. + (See [Qhull]_ documentation for more.) + transform : ndarray of double, shape (nsimplex, ndim+1, ndim) + Affine transform from ``x`` to the barycentric coordinates ``c``. + This is defined by:: + + T c = x - r + + At vertex ``j``, ``c_j = 1`` and the other coordinates zero. + + For simplex ``i``, ``transform[i,:ndim,:ndim]`` contains + inverse of the matrix ``T``, and ``transform[i,ndim,:]`` + contains the vector ``r``. + vertex_to_simplex : ndarray of int, shape (npoints,) + Lookup array, from a vertex, to some simplex which it is a part of. + convex_hull : ndarray of int, shape (nfaces, ndim) + Vertices of facets forming the convex hull of the point set. + The array contains the indices of the points belonging to + the (N-1)-dimensional facets that form the convex hull + of the triangulation. + + Notes + ----- + The tesselation is computed using the Qhull libary [Qhull]_. + + References + ---------- + + .. [Qhull] http://www.qhull.org/ + + """ + + def __init__(self, points): + vertices, neighbors, equations, paraboloid_scale, paraboloid_shift = \ + _construct_delaunay(points) + + self.ndim = points.shape[1] + self.npoints = points.shape[0] + self.nsimplex = vertices.shape[0] + self.points = points + self.vertices = vertices + self.neighbors = neighbors + self.equations = equations + self.paraboloid_scale = paraboloid_scale + self.paraboloid_shift = paraboloid_shift + self.min_bound = self.points.min(axis=0) + self.max_bound = self.points.max(axis=0) + self._transform = None + self._vertex_to_simplex = None + + @property + def transform(self): + """ + Affine transform from ``x`` to the barycentric coordinates ``c``. + + :type: ndarray of double, shape (nsimplex, ndim+1, ndim) + + This is defined by:: + + T c = x - r + + At vertex ``j``, ``c_j = 1`` and the other coordinates zero. + + For simplex ``i``, ``transform[i,:ndim,:ndim]`` contains + inverse of the matrix ``T``, and ``transform[i,ndim,:]`` + contains the vector ``r``. + + """ + if self._transform is None: + self._transform = _get_barycentric_transforms(self.points, + self.vertices) + return self._transform + + @property + def vertex_to_simplex(self): + """ + Lookup array, from a vertex, to some simplex which it is a part of. + + :type: ndarray of int, shape (npoints,) + """ + cdef int isimplex, k, ivertex, nsimplex, ndim + cdef np.ndarray[np.int_t, ndim=2] vertices + cdef np.ndarray[np.int_t, ndim=1] arr + + if self._vertex_to_simplex is None: + self._vertex_to_simplex = np.empty((self.npoints,), dtype=int) + self._vertex_to_simplex.fill(-1) + + arr = self._vertex_to_simplex + vertices = self.vertices + + nsimplex = self.nsimplex + ndim = self.ndim + + for isimplex in xrange(nsimplex): + for k in xrange(ndim+1): + ivertex = vertices[isimplex, k] + if arr[ivertex] == -1: + arr[ivertex] = isimplex + + return self._vertex_to_simplex + + @property + @cython.boundscheck(False) + def convex_hull(self): + """ + Vertices of facets forming the convex hull of the point set. + + :type: ndarray of int, shape (nfaces, ndim) + + The array contains the indices of the points + belonging to the (N-1)-dimensional facets that form the convex + hull of the triangulation. + + """ + cdef int isimplex, k, j, ndim, nsimplex, m, msize + cdef np.ndarray[np.int_t, ndim=2] arr + cdef np.ndarray[np.int_t, ndim=2] neighbors + cdef np.ndarray[np.int_t, ndim=2] vertices + + neighbors = self.neighbors + vertices = self.vertices + ndim = self.ndim + nsimplex = self.nsimplex + + msize = 10 + out = np.empty((msize, ndim), dtype=int) + arr = out + + m = 0 + for isimplex in xrange(nsimplex): + for k in xrange(ndim+1): + if neighbors[isimplex,k] == -1: + for j in xrange(ndim+1): + if j < k: + arr[m,j] = vertices[isimplex,j] + elif j > k: + arr[m,j-1] = vertices[isimplex,j] + m += 1 + + if m >= msize: + arr = None + msize = 2*msize + 1 + out.resize(msize, ndim) + arr = out + + arr = None + out.resize(m, ndim) + return out + + def find_simplex(self, xi, bruteforce=False): + """ + find_simplex(xi, bruteforce=False) + + Find the simplices containing the given points. + + Parameters + ---------- + tri : DelaunayInfo + Delaunay triangulation + xi : ndarray of double, shape (..., ndim) + Points to locate + bruteforce : bool, optional + Whether to only perform a brute-force search + + Returns + ------- + i : ndarray of int, same shape as `xi` + Indices of simplices containing each point. + Points outside the triangulation get the value -1. + + Notes + ----- + This uses an algorithm adapted from Qhull's qh_findbestfacet, + which makes use of the connection between a convex hull and a + Delaunay triangulation. After finding the simplex closest to + the point in N+1 dimensions, the algorithm falls back to + directed search in N dimensions. + + """ + cdef DelaunayInfo_t *info + cdef int isimplex + cdef double c[NPY_MAXDIMS] + cdef double eps + cdef int start + cdef int k + cdef np.ndarray[np.double_t, ndim=2] x + cdef np.ndarray[np.int_t, ndim=1] out_ + + xi = np.asanyarray(xi) + + if xi.shape[-1] != self.ndim: + raise ValueError("wrong dimensionality in xi") + + xi_shape = xi.shape + xi = xi.reshape(np.prod(xi.shape[:-1]), xi.shape[-1]) + x = np.ascontiguousarray(xi.astype(np.double)) + + start = 0 + + eps = np.finfo(np.double).eps * 10 + out = np.zeros((xi.shape[0],), dtype=np.int) + out_ = out + info = _get_delaunay_info(self, 1, 0) + + if bruteforce: + for k in xrange(x.shape[0]): + isimplex = _find_simplex_bruteforce( + info, c, + x.data + info.ndim*k, + eps) + out_[k] = isimplex + else: + for k in xrange(x.shape[0]): + isimplex = _find_simplex(info, c, x.data + info.ndim*k, + &start, eps) + out_[k] = isimplex + + free(info) + + return out.reshape(xi_shape[:-1]) + + def plane_distance(self, xi): + """ + plane_distance(xi) + + Compute hyperplane distances to the point `xi` from all simplices. + + """ + cdef np.ndarray[np.double_t, ndim=2] x + cdef np.ndarray[np.double_t, ndim=2] out_ + cdef DelaunayInfo_t *info + cdef double z[NPY_MAXDIMS+1] + cdef int i, j, k + + if xi.shape[-1] != self.ndim: + raise ValueError("xi has different dimensionality than " + "triangulation") + + xi_shape = xi.shape + xi = xi.reshape(np.prod(xi.shape[:-1]), xi.shape[-1]) + x = np.ascontiguousarray(xi.astype(np.double)) + + info = _get_delaunay_info(self, 0, 0) + + out = np.zeros((x.shape[0], info.nsimplex), dtype=np.double) + out_ = out + + for i in xrange(x.shape[0]): + for j in xrange(info.nsimplex): + _lift_point(info, (x.data) + info.ndim*i, z) + out_[i,j] = _distplane(info, j, z) + + free(info) + + return out.reshape(xi_shape[:-1] + (self.nsimplex,)) + + def lift_points(tri, x): + """ + lift_points(tri, x) + + Lift points to the Qhull paraboloid. + + """ + z = np.zeros(x.shape[:-1] + (x.shape[-1]+1,), dtype=np.double) + z[...,:-1] = x + z[...,-1] = (x**2).sum(axis=-1) + z[...,-1] *= tri.paraboloid_scale + z[...,-1] += tri.paraboloid_shift + return z + +# Alias familiar from other environments +def tsearch(tri, xi): + """ + tsearch(tri, xi) + + Find simplices containing the given points. This function does the + same thing as Delaunay.find_simplex. + + .. versionadded:: 0.9 + + See Also + -------- + Delaunay.find_simplex + + """ + return tri.find_simplex(xi) + + +#------------------------------------------------------------------------------ +# Delaunay triangulation interface, for low-level C +#------------------------------------------------------------------------------ + +cdef DelaunayInfo_t *_get_delaunay_info(obj, + int compute_transform, + int compute_vertex_to_simplex): + cdef DelaunayInfo_t *info + cdef np.ndarray[np.double_t, ndim=3] transform + cdef np.ndarray[np.int_t, ndim=1] vertex_to_simplex + cdef np.ndarray[np.double_t, ndim=2] points = obj.points + cdef np.ndarray[np.int_t, ndim=2] vertices = obj.vertices + cdef np.ndarray[np.int_t, ndim=2] neighbors = obj.neighbors + cdef np.ndarray[np.double_t, ndim=2] equations = obj.equations + cdef np.ndarray[np.double_t, ndim=1] min_bound = obj.min_bound + cdef np.ndarray[np.double_t, ndim=1] max_bound = obj.max_bound + + info = malloc(sizeof(DelaunayInfo_t)) + info.ndim = points.shape[1] + info.npoints = points.shape[0] + info.nsimplex = vertices.shape[0] + info.points = points.data + info.vertices = vertices.data + info.neighbors = neighbors.data + info.equations = equations.data + info.paraboloid_scale = obj.paraboloid_scale + info.paraboloid_shift = obj.paraboloid_shift + if compute_transform: + transform = obj.transform + info.transform = transform.data + else: + info.transform = NULL + if compute_vertex_to_simplex: + vertex_to_simplex = obj.vertex_to_simplex + info.vertex_to_simplex = vertex_to_simplex.data + else: + info.vertex_to_simplex = NULL + info.min_bound = min_bound.data + info.max_bound = max_bound.data + + return info Added: trunk/scipy/spatial/qhull_blas.h =================================================================== --- trunk/scipy/spatial/qhull_blas.h (rev 0) +++ trunk/scipy/spatial/qhull_blas.h 2010-08-31 21:55:50 UTC (rev 6653) @@ -0,0 +1,19 @@ +/* + * Handle different Fortran conventions. + */ + +#if defined(NO_APPEND_FORTRAN) +#if defined(UPPERCASE_FORTRAN) +#define F_FUNC(f,F) F +#else +#define F_FUNC(f,F) f +#endif +#else +#if defined(UPPERCASE_FORTRAN) +#define F_FUNC(f,F) F##_ +#else +#define F_FUNC(f,F) f##_ +#endif +#endif + +#define qh_dgesv F_FUNC(dgesv,DGESV) Modified: trunk/scipy/spatial/setup.py =================================================================== --- trunk/scipy/spatial/setup.py 2010-08-31 21:54:55 UTC (rev 6652) +++ trunk/scipy/spatial/setup.py 2010-08-31 21:55:50 UTC (rev 6653) @@ -4,10 +4,28 @@ def configuration(parent_package = '', top_path = None): from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs + from numpy.distutils.system_info import get_info + config = Configuration('spatial', parent_package, top_path) config.add_data_dir('tests') + qhull_src = ['geom.c', 'geom2.c', 'global.c', 'io.c', 'mem.c', + 'merge.c', 'poly.c', 'poly2.c', 'qset.c', 'user.c', + 'stat.c', 'qhull.c'] + + config.add_library('qhull', + sources=[join('qhull', 'src', x) for x in qhull_src], + # XXX: GCC dependency! + #extra_compiler_args=['-fno-strict-aliasing'], + ) + + lapack = get_info('lapack_opt') + config.add_extension('qhull', + sources=['qhull.c'], + libraries=['qhull'] + lapack['libraries'], + ) + config.add_extension('ckdtree', sources=['ckdtree.c']) # FIXME: cython config.add_extension('_distance_wrap', Added: trunk/scipy/spatial/tests/test_qhull.py =================================================================== --- trunk/scipy/spatial/tests/test_qhull.py (rev 0) +++ trunk/scipy/spatial/tests/test_qhull.py 2010-08-31 21:55:50 UTC (rev 6653) @@ -0,0 +1,158 @@ +import numpy as np +from numpy.testing import * + +import scipy.spatial.qhull as qhull + +class TestUtilities(object): + """ + Check that utility functions work. + + """ + + def test_find_simplex(self): + # Simple check that simplex finding works + points = np.array([(0,0), (0,1), (1,1), (1,0)], dtype=np.double) + tri = qhull.Delaunay(points) + + # +---+ + # |\ 0| + # | \ | + # |1 \| + # +---+ + + assert_equal(tri.vertices, [[3, 1, 2], [3, 1, 0]]) + + for p in [(0.25, 0.25, 1), + (0.75, 0.75, 0), + (0.3, 0.2, 1)]: + i = tri.find_simplex(p[:2]) + assert_equal(i, p[2], err_msg='%r' % (p,)) + j = qhull.tsearch(tri, p[:2]) + assert_equal(i, j) + + def test_plane_distance(self): + # Compare plane distance from hyperplane equations obtained from Qhull + # to manually computed plane equations + x = np.array([(0,0), (1, 1), (1, 0), (0.99189033, 0.37674127), + (0.99440079, 0.45182168)], dtype=np.double) + p = np.array([0.99966555, 0.15685619], dtype=np.double) + + tri = qhull.Delaunay(x) + + z = tri.lift_points(x) + pz = tri.lift_points(p) + + dist = tri.plane_distance(p) + + for j, v in enumerate(tri.vertices): + x1 = z[v[0]] + x2 = z[v[1]] + x3 = z[v[2]] + + n = np.cross(x1 - x3, x2 - x3) + n /= np.sqrt(np.dot(n, n)) + n *= -np.sign(n[2]) + + d = np.dot(n, pz - x3) + + assert_almost_equal(dist[j], d) + + def test_convex_hull(self): + # Simple check that the convex hull seems to works + points = np.array([(0,0), (0,1), (1,1), (1,0)], dtype=np.double) + tri = qhull.Delaunay(points) + + # +---+ + # |\ 0| + # | \ | + # |1 \| + # +---+ + + assert_equal(tri.convex_hull, [[1, 2], [3, 2], [1, 0], [3, 0]]) + + +class TestTriangulation(object): + """ + Check that triangulation works. + + """ + + def test_nd_simplex(self): + # simple smoke test: triangulate a n-dimensional simplex + for nd in xrange(2, 8): + points = np.zeros((nd+1, nd)) + for j in xrange(nd): + points[j,j] = 1.0 + points[-1,:] = 1.0 + + tri = qhull.Delaunay(points) + + tri.vertices.sort() + + assert_equal(tri.vertices, np.arange(nd+1, dtype=np.int)[None,:]) + assert_equal(tri.neighbors, -1 + np.zeros((nd+1), dtype=np.int)[None,:]) + + def test_2d_square(self): + # simple smoke test: 2d square + points = np.array([(0,0), (0,1), (1,1), (1,0)], dtype=np.double) + tri = qhull.Delaunay(points) + + assert_equal(tri.vertices, [[3, 1, 2], [3, 1, 0]]) + assert_equal(tri.neighbors, [[-1, -1, 1], [-1, -1, 0]]) + + def test_duplicate_points(self): + x = np.array([0, 1, 0, 1], dtype=np.float64) + y = np.array([0, 0, 1, 1], dtype=np.float64) + + xp = np.r_[x, x] + yp = np.r_[y, y] + + # shouldn't fail on duplicate points + tri = qhull.Delaunay(np.c_[x, y]) + tri2 = qhull.Delaunay(np.c_[xp, yp]) + + pathological_data_1 = np.array([ + [-3.14,-3.14], [-3.14,-2.36], [-3.14,-1.57], [-3.14,-0.79], + [-3.14,0.0], [-3.14,0.79], [-3.14,1.57], [-3.14,2.36], + [-3.14,3.14], [-2.36,-3.14], [-2.36,-2.36], [-2.36,-1.57], + [-2.36,-0.79], [-2.36,0.0], [-2.36,0.79], [-2.36,1.57], + [-2.36,2.36], [-2.36,3.14], [-1.57,-0.79], [-1.57,0.79], + [-1.57,-1.57], [-1.57,0.0], [-1.57,1.57], [-1.57,-3.14], + [-1.57,-2.36], [-1.57,2.36], [-1.57,3.14], [-0.79,-1.57], + [-0.79,1.57], [-0.79,-3.14], [-0.79,-2.36], [-0.79,-0.79], + [-0.79,0.0], [-0.79,0.79], [-0.79,2.36], [-0.79,3.14], + [0.0,-3.14], [0.0,-2.36], [0.0,-1.57], [0.0,-0.79], [0.0,0.0], + [0.0,0.79], [0.0,1.57], [0.0,2.36], [0.0,3.14], [0.79,-3.14], + [0.79,-2.36], [0.79,-0.79], [0.79,0.0], [0.79,0.79], + [0.79,2.36], [0.79,3.14], [0.79,-1.57], [0.79,1.57], + [1.57,-3.14], [1.57,-2.36], [1.57,2.36], [1.57,3.14], + [1.57,-1.57], [1.57,0.0], [1.57,1.57], [1.57,-0.79], + [1.57,0.79], [2.36,-3.14], [2.36,-2.36], [2.36,-1.57], + [2.36,-0.79], [2.36,0.0], [2.36,0.79], [2.36,1.57], + [2.36,2.36], [2.36,3.14], [3.14,-3.14], [3.14,-2.36], + [3.14,-1.57], [3.14,-0.79], [3.14,0.0], [3.14,0.79], + [3.14,1.57], [3.14,2.36], [3.14,3.14], + ]) + + pathological_data_2 = np.array([ + [-1, -1 ], [-1, 0], [-1, 1], + [ 0, -1 ], [ 0, 0], [ 0, 1], + [ 1, -1 - np.finfo(np.float_).eps], [ 1, 0], [ 1, 1], + ]) + + def test_pathological(self): + # both should succeed + tri = qhull.Delaunay(self.pathological_data_1) + assert_equal(tri.points[tri.vertices].max(), + self.pathological_data_1.max()) + assert_equal(tri.points[tri.vertices].min(), + self.pathological_data_1.min()) + + tri = qhull.Delaunay(self.pathological_data_2) + assert_equal(tri.points[tri.vertices].max(), + self.pathological_data_2.max()) + assert_equal(tri.points[tri.vertices].min(), + self.pathological_data_2.min()) + +if __name__ == "__main__": + run_module_suite() From scipy-svn at scipy.org Tue Aug 31 17:56:34 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 16:56:34 -0500 (CDT) Subject: [Scipy-svn] r6654 - trunk/scipy/spatial Message-ID: <20100831215634.5CA1039CCFC@scipy.org> Author: ptvirtan Date: 2010-08-31 16:56:34 -0500 (Tue, 31 Aug 2010) New Revision: 6654 Added: trunk/scipy/spatial/qhull.c Log: GEN: spatial: regenerate qhull.c Added: trunk/scipy/spatial/qhull.c =================================================================== --- trunk/scipy/spatial/qhull.c (rev 0) +++ trunk/scipy/spatial/qhull.c 2010-08-31 21:56:34 UTC (rev 6654) @@ -0,0 +1,9528 @@ + + +#define PY_SSIZE_T_CLEAN +#include "Python.h" +#include "structmember.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#else + +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#if PY_VERSION_HEX < 0x02040000 + #define METH_COEXIST 0 + #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) + #define PyDict_Contains(d,o) PySequence_Contains(d,o) +#endif + +#if PY_VERSION_HEX < 0x02050000 + typedef int Py_ssize_t; + #define PY_SSIZE_T_MAX INT_MAX + #define PY_SSIZE_T_MIN INT_MIN + #define PY_FORMAT_SIZE_T "" + #define PyInt_FromSsize_t(z) PyInt_FromLong(z) + #define PyInt_AsSsize_t(o) PyInt_AsLong(o) + #define PyNumber_Index(o) PyNumber_Int(o) + #define PyIndex_Check(o) PyNumber_Check(o) + #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message) +#endif + +#if PY_VERSION_HEX < 0x02060000 + #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) + #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) + #define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) + #define PyVarObject_HEAD_INIT(type, size) \ + PyObject_HEAD_INIT(type) size, + #define PyType_Modified(t) + + typedef struct { + void *buf; + PyObject *obj; + Py_ssize_t len; + Py_ssize_t itemsize; + int readonly; + int ndim; + char *format; + Py_ssize_t *shape; + Py_ssize_t *strides; + Py_ssize_t *suboffsets; + void *internal; + } Py_buffer; + + #define PyBUF_SIMPLE 0 + #define PyBUF_WRITABLE 0x0001 + #define PyBUF_FORMAT 0x0004 + #define PyBUF_ND 0x0008 + #define PyBUF_STRIDES (0x0010 | PyBUF_ND) + #define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) + #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) + #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) + #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) + +#endif + +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" +#endif + +#if PY_MAJOR_VERSION >= 3 + #define Py_TPFLAGS_CHECKTYPES 0 + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif + +#if (PY_VERSION_HEX < 0x02060000) || (PY_MAJOR_VERSION >= 3) + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif + +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyString_Type PyUnicode_Type + #define PyString_CheckExact PyUnicode_CheckExact +#else + #define PyBytes_Type PyString_Type + #define PyBytes_CheckExact PyString_CheckExact +#endif + +#if PY_MAJOR_VERSION >= 3 + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) + +#endif + +#if PY_MAJOR_VERSION >= 3 + #define PyMethod_New(func, self, klass) PyInstanceMethod_New(func) +#endif + +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#else + #define _USE_MATH_DEFINES +#endif + +#if PY_VERSION_HEX < 0x02050000 + #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),((char *)(n))) + #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),((char *)(n)),(a)) + #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),((char *)(n))) +#else + #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),(n)) + #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),(n),(a)) + #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),(n)) +#endif + +#if PY_VERSION_HEX < 0x02050000 + #define __Pyx_NAMESTR(n) ((char *)(n)) + #define __Pyx_DOCSTR(n) ((char *)(n)) +#else + #define __Pyx_NAMESTR(n) (n) + #define __Pyx_DOCSTR(n) (n) +#endif +#ifdef __cplusplus +#define __PYX_EXTERN_C extern "C" +#else +#define __PYX_EXTERN_C extern +#endif +#include +#define __PYX_HAVE_API__scipy__spatial__qhull +#include "stdlib.h" +#include "numpy/ndarraytypes.h" +#include "stdio.h" +#include "numpy/arrayobject.h" +#include "numpy/ufuncobject.h" +#include "qhull/src/qset.h" +#include "qhull/src/qhull.h" +#include "qhull_blas.h" + +#ifndef CYTHON_INLINE + #if defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #else + #define CYTHON_INLINE + #endif +#endif + +typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + + + + +#if PY_MAJOR_VERSION < 3 +#define __Pyx_PyBytes_FromString PyString_FromString +#define __Pyx_PyBytes_FromStringAndSize PyString_FromStringAndSize +#define __Pyx_PyBytes_AsString PyString_AsString +#else +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +#define __Pyx_PyBytes_AsString PyBytes_AsString +#endif + +#define __Pyx_PyBytes_FromUString(s) __Pyx_PyBytes_FromString((char*)s) +#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) __Pyx_PyBytes_AsString(s)) + +#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False)) +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); + +#if !defined(T_PYSSIZET) +#if PY_VERSION_HEX < 0x02050000 +#define T_PYSSIZET T_INT +#elif !defined(T_LONGLONG) +#define T_PYSSIZET \ + ((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \ + ((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : -1)) +#else +#define T_PYSSIZET \ + ((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \ + ((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : \ + ((sizeof(Py_ssize_t) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1))) +#endif +#endif + + +#if !defined(T_ULONGLONG) +#define __Pyx_T_UNSIGNED_INT(x) \ + ((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \ + ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \ + ((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \ + ((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : -1)))) +#else +#define __Pyx_T_UNSIGNED_INT(x) \ + ((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \ + ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \ + ((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \ + ((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : \ + ((sizeof(x) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1))))) +#endif +#if !defined(T_LONGLONG) +#define __Pyx_T_SIGNED_INT(x) \ + ((sizeof(x) == sizeof(char)) ? T_BYTE : \ + ((sizeof(x) == sizeof(short)) ? T_SHORT : \ + ((sizeof(x) == sizeof(int)) ? T_INT : \ + ((sizeof(x) == sizeof(long)) ? T_LONG : -1)))) +#else +#define __Pyx_T_SIGNED_INT(x) \ + ((sizeof(x) == sizeof(char)) ? T_BYTE : \ + ((sizeof(x) == sizeof(short)) ? T_SHORT : \ + ((sizeof(x) == sizeof(int)) ? T_INT : \ + ((sizeof(x) == sizeof(long)) ? T_LONG : \ + ((sizeof(x) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1))))) +#endif + +#define __Pyx_T_FLOATING(x) \ + ((sizeof(x) == sizeof(float)) ? T_FLOAT : \ + ((sizeof(x) == sizeof(double)) ? T_DOUBLE : -1)) + +#if !defined(T_SIZET) +#if !defined(T_ULONGLONG) +#define T_SIZET \ + ((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \ + ((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : -1)) +#else +#define T_SIZET \ + ((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \ + ((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : \ + ((sizeof(size_t) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1))) +#endif +#endif + +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*); + +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) + + +#ifdef __GNUC__ + +#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif + +static PyObject *__pyx_m; +static PyObject *__pyx_b; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; +static const char **__pyx_f; + + +#if !defined(CYTHON_CCOMPLEX) + #if defined(__cplusplus) + #define CYTHON_CCOMPLEX 1 + #elif defined(_Complex_I) + #define CYTHON_CCOMPLEX 1 + #else + #define CYTHON_CCOMPLEX 0 + #endif +#endif + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #include + #else + #include + #endif +#endif + +#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) + #undef _Complex_I + #define _Complex_I 1.0fj +#endif + +typedef npy_int8 __pyx_t_5numpy_int8_t; + +typedef npy_int16 __pyx_t_5numpy_int16_t; + +typedef npy_int32 __pyx_t_5numpy_int32_t; + +typedef npy_int64 __pyx_t_5numpy_int64_t; + +typedef npy_uint8 __pyx_t_5numpy_uint8_t; + +typedef npy_uint16 __pyx_t_5numpy_uint16_t; + +typedef npy_uint32 __pyx_t_5numpy_uint32_t; + +typedef npy_uint64 __pyx_t_5numpy_uint64_t; + +typedef npy_float32 __pyx_t_5numpy_float32_t; + +typedef npy_float64 __pyx_t_5numpy_float64_t; + +typedef npy_long __pyx_t_5numpy_int_t; + +typedef npy_longlong __pyx_t_5numpy_long_t; + +typedef npy_intp __pyx_t_5numpy_intp_t; + +typedef npy_uintp __pyx_t_5numpy_uintp_t; + +typedef npy_ulong __pyx_t_5numpy_uint_t; + +typedef npy_ulonglong __pyx_t_5numpy_ulong_t; + +typedef npy_double __pyx_t_5numpy_float_t; + +typedef npy_double __pyx_t_5numpy_double_t; + +typedef npy_longdouble __pyx_t_5numpy_longdouble_t; + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< float > __pyx_t_float_complex; + #else + typedef float _Complex __pyx_t_float_complex; + #endif +#else + typedef struct { float real, imag; } __pyx_t_float_complex; +#endif + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< double > __pyx_t_double_complex; + #else + typedef double _Complex __pyx_t_double_complex; + #endif +#else + typedef struct { double real, imag; } __pyx_t_double_complex; +#endif + + + +typedef npy_cfloat __pyx_t_5numpy_cfloat_t; + +typedef npy_cdouble __pyx_t_5numpy_cdouble_t; + +typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; + +typedef npy_cdouble __pyx_t_5numpy_complex_t; + + + +typedef struct { + int ndim; + int npoints; + int nsimplex; + double *points; + int *vertices; + int *neighbors; + double *equations; + double *transform; + int *vertex_to_simplex; + double paraboloid_scale; + double paraboloid_shift; + double *max_bound; + double *min_bound; +} __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t; + + + +typedef struct { + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *info; + int vertex; + int edge; + int vertex2; + int triangle; + int start_triangle; + int start_edge; +} __pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t; + +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif + +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct * __Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule((char *)modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); + end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; + } + #define __Pyx_RefNannySetupContext(name) void *__pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) + #define __Pyx_RefNannyFinishContext() __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r);} } while(0) +#else + #define __Pyx_RefNannySetupContext(name) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) +#endif +#define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);} } while(0) +#define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r);} } while(0) + + +struct __Pyx_StructField_; + +typedef struct { + const char* name; + struct __Pyx_StructField_* fields; + size_t size; + char typegroup; +} __Pyx_TypeInfo; + +typedef struct __Pyx_StructField_ { + __Pyx_TypeInfo* type; + const char* name; + size_t offset; +} __Pyx_StructField; + +typedef struct { + __Pyx_StructField* field; + size_t parent_offset; +} __Pyx_BufFmt_StackElem; + + +static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info); +static int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); + +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); + +static void __Pyx_RaiseBufferFallbackError(void); + +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); + +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void); + +static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); +static int __Pyx_EndUnpack(PyObject *); + +static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); + +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, PyObject* kw_name); + +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name); +static void __Pyx_RaiseBufferIndexError(int axis); +#define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0) +#define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1) +#define __Pyx_BufPtrStrided3d(type, buf, i0, s0, i1, s1, i2, s2) (type)((char*)buf + i0 * s0 + i1 * s1 + i2 * s2) + + +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { + PyObject *r; + if (!j) return NULL; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + return r; +} + + +#define __Pyx_GetItemInt_List(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \ + __Pyx_GetItemInt_List_Fast(o, i, size <= sizeof(long)) : \ + __Pyx_GetItemInt_Generic(o, to_py_func(i))) + +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, int fits_long) { + if (likely(o != Py_None)) { + if (likely((0 <= i) & (i < PyList_GET_SIZE(o)))) { + PyObject *r = PyList_GET_ITEM(o, i); + Py_INCREF(r); + return r; + } + else if ((-PyList_GET_SIZE(o) <= i) & (i < 0)) { + PyObject *r = PyList_GET_ITEM(o, PyList_GET_SIZE(o) + i); + Py_INCREF(r); + return r; + } + } + return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i)); +} + +#define __Pyx_GetItemInt_Tuple(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \ + __Pyx_GetItemInt_Tuple_Fast(o, i, size <= sizeof(long)) : \ + __Pyx_GetItemInt_Generic(o, to_py_func(i))) + +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, int fits_long) { + if (likely(o != Py_None)) { + if (likely((0 <= i) & (i < PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, i); + Py_INCREF(r); + return r; + } + else if ((-PyTuple_GET_SIZE(o) <= i) & (i < 0)) { + PyObject *r = PyTuple_GET_ITEM(o, PyTuple_GET_SIZE(o) + i); + Py_INCREF(r); + return r; + } + } + return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i)); +} + + +#define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \ + __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \ + __Pyx_GetItemInt_Generic(o, to_py_func(i))) + +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) { + PyObject *r; + if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) { + r = PyList_GET_ITEM(o, i); + Py_INCREF(r); + } + else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) { + r = PyTuple_GET_ITEM(o, i); + Py_INCREF(r); + } + else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) { + r = PySequence_GetItem(o, i); + } + else { + r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i)); + } + return r; +} + +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); + +static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); + +static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, + const char *name, int exact); +#if PY_MAJOR_VERSION < 3 +static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); +static void __Pyx_ReleaseBuffer(Py_buffer *view); +#else +#define __Pyx_GetBuffer PyObject_GetBuffer +#define __Pyx_ReleaseBuffer PyBuffer_Release +#endif + +Py_ssize_t __Pyx_zeros[] = {0, 0, 0}; +Py_ssize_t __Pyx_minusones[] = {-1, -1, -1}; + +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); + +static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); + +static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); + +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); + +static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_npy_intp(npy_intp); + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #define __Pyx_CREAL(z) ((z).real()) + #define __Pyx_CIMAG(z) ((z).imag()) + #else + #define __Pyx_CREAL(z) (__real__(z)) + #define __Pyx_CIMAG(z) (__imag__(z)) + #endif +#else + #define __Pyx_CREAL(z) ((z).real) + #define __Pyx_CIMAG(z) ((z).imag) +#endif + +#if defined(_WIN32) && defined(__cplusplus) && CYTHON_CCOMPLEX + #define __Pyx_SET_CREAL(z,x) ((z).real(x)) + #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) +#else + #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) + #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) +#endif + +static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); + +#if CYTHON_CCOMPLEX + #define __Pyx_c_eqf(a, b) ((a)==(b)) + #define __Pyx_c_sumf(a, b) ((a)+(b)) + #define __Pyx_c_difff(a, b) ((a)-(b)) + #define __Pyx_c_prodf(a, b) ((a)*(b)) + #define __Pyx_c_quotf(a, b) ((a)/(b)) + #define __Pyx_c_negf(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zerof(z) ((z)==(float)0) + #define __Pyx_c_conjf(z) (::std::conj(z)) + + #else + #define __Pyx_c_is_zerof(z) ((z)==0) + #define __Pyx_c_conjf(z) (conjf(z)) + + #endif +#else + static CYTHON_INLINE int __Pyx_c_eqf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sumf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_difff(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prodf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quotf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_negf(__pyx_t_float_complex); + static CYTHON_INLINE int __Pyx_c_is_zerof(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conjf(__pyx_t_float_complex); + +#endif + +static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); + +#if CYTHON_CCOMPLEX + #define __Pyx_c_eq(a, b) ((a)==(b)) + #define __Pyx_c_sum(a, b) ((a)+(b)) + #define __Pyx_c_diff(a, b) ((a)-(b)) + #define __Pyx_c_prod(a, b) ((a)*(b)) + #define __Pyx_c_quot(a, b) ((a)/(b)) + #define __Pyx_c_neg(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero(z) ((z)==(double)0) + #define __Pyx_c_conj(z) (::std::conj(z)) + + #else + #define __Pyx_c_is_zero(z) ((z)==0) + #define __Pyx_c_conj(z) (conj(z)) + + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg(__pyx_t_double_complex); + static CYTHON_INLINE int __Pyx_c_is_zero(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj(__pyx_t_double_complex); + +#endif + +static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject *); + +static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject *); + +static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject *); + +static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject *); + +static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject *); + +static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject *); + +static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject *); + +static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject *); + +static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject *); + +static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject *); + +static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject *); + +static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject *); + +static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject *); + +static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject *); + +static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *); + +static void __Pyx_WriteUnraisable(const char *name); + +static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig); + +static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, long size, int strict); + +static PyObject *__Pyx_ImportModule(const char *name); + +static void __Pyx_AddTraceback(const char *funcname); + +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + + + + + + + + + + + + +static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; +static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; +static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; +static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; +static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *, PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *, PyObject *, PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *, PyObject *, PyObject *, PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *, PyObject *, PyObject *, PyObject *, PyObject *); +static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); +static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *, PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *); + + + + +static __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_f_5scipy_7spatial_5qhull__get_delaunay_info(PyObject *, int, int); +static int __pyx_f_5scipy_7spatial_5qhull__barycentric_inside(int, double *, double *, double *, double); +static void __pyx_f_5scipy_7spatial_5qhull__barycentric_coordinate_single(int, double *, double *, double *, int); +static void __pyx_f_5scipy_7spatial_5qhull__barycentric_coordinates(int, double *, double *, double *); +static void __pyx_f_5scipy_7spatial_5qhull__lift_point(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *); +static double __pyx_f_5scipy_7spatial_5qhull__distplane(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int, double *); +static int __pyx_f_5scipy_7spatial_5qhull__is_point_fully_outside(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double); +static int __pyx_f_5scipy_7spatial_5qhull__find_simplex_bruteforce(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, double); +static int __pyx_f_5scipy_7spatial_5qhull__find_simplex_directed(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, int *, double); +static int __pyx_f_5scipy_7spatial_5qhull__find_simplex(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, int *, double); +static void __pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_init(__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *, __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int); +static void __pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_next(__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *); +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_double_t = { "numpy.double_t", NULL, sizeof(__pyx_t_5numpy_double_t), 'R' }; +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_int_t = { "numpy.int_t", NULL, sizeof(__pyx_t_5numpy_int_t), 'I' }; +#define __Pyx_MODULE_NAME "scipy.spatial.qhull" +int __pyx_module_is_main_scipy__spatial__qhull = 0; + + +static PyObject *__pyx_builtin_object; +static PyObject *__pyx_builtin_property; +static PyObject *__pyx_builtin_ValueError; +static PyObject *__pyx_builtin_RuntimeError; +static PyObject *__pyx_builtin_xrange; +static PyObject *__pyx_builtin_range; +static char __pyx_k_1[] = "qhull d Qz Qbb Qt"; +static char __pyx_k_2[] = "No points to triangulate"; +static char __pyx_k_3[] = "Need at least 2-D data to triangulate"; +static char __pyx_k_4[] = "Qhull error"; +static char __pyx_k_5[] = "_qhull_get_facet_array"; +static char __pyx_k_6[] = "qhull: did not free %d bytes (%d pieces)"; +static char __pyx_k_7[] = "non-simplical facet encountered"; +static char __pyx_k_8[] = "_get_barycentric_transforms"; +static char __pyx_k_10[] = "wrong dimensionality in xi"; +static char __pyx_k_11[] = "xi has different dimensionality than triangulation"; +static char __pyx_k_12[] = "ndarray is not C contiguous"; +static char __pyx_k_13[] = "ndarray is not Fortran contiguous"; +static char __pyx_k_14[] = "Non-native byte order not supported"; +static char __pyx_k_15[] = "unknown dtype code in numpy.pxd (%d)"; +static char __pyx_k_16[] = "Format string allocated too short, see comment in numpy.pxd"; +static char __pyx_k_17[] = "Format string allocated too short."; +static char __pyx_k_18[] = "\nWrappers for Qhull triangulation, plus some additional N-D geometry utilities\n\n.. versionadded:: 0.9\n\n"; +static char __pyx_k_19[] = "\n Delaunay(points)\n\n Delaunay tesselation in N dimensions\n\n .. versionadded:: 0.9\n\n Parameters\n ----------\n points : ndarray of floats, shape (npoints, ndim)\n Coordinates of points to triangulate\n\n Attributes\n ----------\n points : ndarray of double, shape (npoints, ndim)\n Points in the triangulation\n vertices : ndarray of ints, shape (nsimplex, ndim+1)\n Indices of vertices forming simplices in the triangulation\n neighbors : ndarray of ints, shape (nsimplex, ndim+1)\n Indices of neighbor simplices for each simplex.\n The kth neighbor is opposite to the kth vertex.\n For simplices at the boundary, -1 denotes no neighbor.\n equations : ndarray of double, shape (nsimplex, ndim+2)\n [normal, offset] forming the hyperplane equation of the facet\n on the paraboloid. (See [Qhull]_ documentation for more.)\n paraboloid_scale, paraboloid_shift : float\n Scale and shift for the extra paraboloid dimension.\n (See [Qhull]_ documentation for more.)\n transform : ndarray of double, shape (nsimplex, ndim+1, ndim)\n Affine transform from ``x`` to the barycentric coordinates ``c``.\n This is defined by::\n\n T c = x - r\n\n At vertex ``j``, ``c_j = 1`` and the other coordinates zero.\n\n For simplex ``i``, ``transform[i,:ndim,:ndim]`` contains\n inverse of the matrix ``T``, and ``transform[i,ndim,:]``\n contains the vector ``r``.\n vertex_to_simplex : ndarray of int, shape (npoints,)\n Lookup array, from a vertex, to some simplex which it is a part of.\n convex_hull : ndarray of int, shape (nfaces, ndim)\n Vertices of facets forming the convex hull of the point set.\n The array contains the indices of the points belonging to\n the (N-1)-dimensional facets that form the convex hull\n of the triangulation.\n\n Notes\n -----\n The tesselation is computed using the Qhull libary [Qhull]_.\n\n References\n ----------\n\n .. [Qhull] http://www.qhull.org/\n\n "; +static char __pyx_k__B[] = "B"; +static char __pyx_k__H[] = "H"; +static char __pyx_k__I[] = "I"; +static char __pyx_k__L[] = "L"; +static char __pyx_k__O[] = "O"; +static char __pyx_k__Q[] = "Q"; +static char __pyx_k__b[] = "b"; +static char __pyx_k__d[] = "d"; +static char __pyx_k__e[] = "e"; +static char __pyx_k__f[] = "f"; +static char __pyx_k__g[] = "g"; +static char __pyx_k__h[] = "h"; +static char __pyx_k__i[] = "i"; +static char __pyx_k__l[] = "l"; +static char __pyx_k__p[] = "p"; +static char __pyx_k__q[] = "q"; +static char __pyx_k__x[] = "x"; +static char __pyx_k__Zd[] = "Zd"; +static char __pyx_k__Zf[] = "Zf"; +static char __pyx_k__Zg[] = "Zg"; +static char __pyx_k__id[] = "id"; +static char __pyx_k__np[] = "np"; +static char __pyx_k__xi[] = "xi"; +static char __pyx_k__buf[] = "buf"; +static char __pyx_k__eps[] = "eps"; +static char __pyx_k__int[] = "int"; +static char __pyx_k__max[] = "max"; +static char __pyx_k__min[] = "min"; +static char __pyx_k__nan[] = "nan"; +static char __pyx_k__obj[] = "obj"; +static char __pyx_k__sum[] = "sum"; +static char __pyx_k__tri[] = "tri"; +static char __pyx_k__Lock[] = "Lock"; +static char __pyx_k__axis[] = "axis"; +static char __pyx_k__base[] = "base"; +static char __pyx_k__data[] = "data"; +static char __pyx_k__edge[] = "edge"; +static char __pyx_k__fill[] = "fill"; +static char __pyx_k__info[] = "info"; +static char __pyx_k__ndim[] = "ndim"; +static char __pyx_k__next[] = "next"; +static char __pyx_k__prod[] = "prod"; +static char __pyx_k__self[] = "self"; +static char __pyx_k__descr[] = "descr"; +static char __pyx_k__dtype[] = "dtype"; +static char __pyx_k__empty[] = "empty"; +static char __pyx_k__finfo[] = "finfo"; +static char __pyx_k__names[] = "names"; +static char __pyx_k__numpy[] = "numpy"; +static char __pyx_k__point[] = "point"; +static char __pyx_k__range[] = "range"; +static char __pyx_k__shape[] = "shape"; +static char __pyx_k__zeros[] = "zeros"; +static char __pyx_k__astype[] = "astype"; +static char __pyx_k__double[] = "double"; +static char __pyx_k__fields[] = "fields"; +static char __pyx_k__format[] = "format"; +static char __pyx_k__normal[] = "normal"; +static char __pyx_k__object[] = "object"; +static char __pyx_k__offset[] = "offset"; +static char __pyx_k__points[] = "points"; +static char __pyx_k__resize[] = "resize"; +static char __pyx_k__vertex[] = "vertex"; +static char __pyx_k__xrange[] = "xrange"; +static char __pyx_k____all__[] = "__all__"; +static char __pyx_k__acquire[] = "acquire"; +static char __pyx_k__npoints[] = "npoints"; +static char __pyx_k__release[] = "release"; +static char __pyx_k__reshape[] = "reshape"; +static char __pyx_k__strides[] = "strides"; +static char __pyx_k__tsearch[] = "tsearch"; +static char __pyx_k__vertex2[] = "vertex2"; +static char __pyx_k__Delaunay[] = "Delaunay"; +static char __pyx_k____init__[] = "__init__"; +static char __pyx_k____main__[] = "__main__"; +static char __pyx_k__facet_id[] = "facet_id"; +static char __pyx_k__itemsize[] = "itemsize"; +static char __pyx_k__last_low[] = "last_low"; +static char __pyx_k__nsimplex[] = "nsimplex"; +static char __pyx_k__property[] = "property"; +static char __pyx_k__readonly[] = "readonly"; +static char __pyx_k__triangle[] = "triangle"; +static char __pyx_k__type_num[] = "type_num"; +static char __pyx_k__vertices[] = "vertices"; +static char __pyx_k__NOerrexit[] = "NOerrexit"; +static char __pyx_k__SCALElast[] = "SCALElast"; +static char __pyx_k__byteorder[] = "byteorder"; +static char __pyx_k__equations[] = "equations"; +static char __pyx_k__last_high[] = "last_high"; +static char __pyx_k__max_bound[] = "max_bound"; +static char __pyx_k__min_bound[] = "min_bound"; +static char __pyx_k__neighbors[] = "neighbors"; +static char __pyx_k__numpoints[] = "numpoints"; +static char __pyx_k__threading[] = "threading"; +static char __pyx_k__transform[] = "transform"; +static char __pyx_k__ValueError[] = "ValueError"; +static char __pyx_k___transform[] = "_transform"; +static char __pyx_k__asanyarray[] = "asanyarray"; +static char __pyx_k__bruteforce[] = "bruteforce"; +static char __pyx_k__facet_list[] = "facet_list"; +static char __pyx_k__simplicial[] = "simplicial"; +static char __pyx_k__start_edge[] = "start_edge"; +static char __pyx_k__suboffsets[] = "suboffsets"; +static char __pyx_k___qhull_lock[] = "_qhull_lock"; +static char __pyx_k__convex_hull[] = "convex_hull"; +static char __pyx_k__lift_points[] = "lift_points"; +static char __pyx_k__RuntimeError[] = "RuntimeError"; +static char __pyx_k__find_simplex[] = "find_simplex"; +static char __pyx_k__last_newhigh[] = "last_newhigh"; +static char __pyx_k__upperdelaunay[] = "upperdelaunay"; +static char __pyx_k__plane_distance[] = "plane_distance"; +static char __pyx_k__start_triangle[] = "start_triangle"; +static char __pyx_k__paraboloid_scale[] = "paraboloid_scale"; +static char __pyx_k__paraboloid_shift[] = "paraboloid_shift"; +static char __pyx_k__ascontiguousarray[] = "ascontiguousarray"; +static char __pyx_k__vertex_to_simplex[] = "vertex_to_simplex"; +static char __pyx_k___vertex_to_simplex[] = "_vertex_to_simplex"; +static char __pyx_k___construct_delaunay[] = "_construct_delaunay"; +static PyObject *__pyx_kp_s_10; +static PyObject *__pyx_kp_s_11; +static PyObject *__pyx_kp_u_12; +static PyObject *__pyx_kp_u_13; +static PyObject *__pyx_kp_u_14; +static PyObject *__pyx_kp_u_15; +static PyObject *__pyx_kp_u_16; +static PyObject *__pyx_kp_u_17; +static PyObject *__pyx_kp_s_19; +static PyObject *__pyx_kp_s_2; +static PyObject *__pyx_kp_s_3; +static PyObject *__pyx_kp_s_4; +static PyObject *__pyx_n_s_5; +static PyObject *__pyx_kp_s_6; +static PyObject *__pyx_kp_s_7; +static PyObject *__pyx_n_s_8; +static PyObject *__pyx_n_s__Delaunay; +static PyObject *__pyx_n_s__Lock; +static PyObject *__pyx_n_s__NOerrexit; +static PyObject *__pyx_n_s__RuntimeError; +static PyObject *__pyx_n_s__SCALElast; +static PyObject *__pyx_n_s__ValueError; +static PyObject *__pyx_n_s____all__; +static PyObject *__pyx_n_s____init__; +static PyObject *__pyx_n_s____main__; +static PyObject *__pyx_n_s___construct_delaunay; +static PyObject *__pyx_n_s___qhull_lock; +static PyObject *__pyx_n_s___transform; +static PyObject *__pyx_n_s___vertex_to_simplex; +static PyObject *__pyx_n_s__acquire; +static PyObject *__pyx_n_s__asanyarray; +static PyObject *__pyx_n_s__ascontiguousarray; +static PyObject *__pyx_n_s__astype; +static PyObject *__pyx_n_s__axis; +static PyObject *__pyx_n_s__base; +static PyObject *__pyx_n_s__bruteforce; +static PyObject *__pyx_n_s__buf; +static PyObject *__pyx_n_s__byteorder; +static PyObject *__pyx_n_s__convex_hull; +static PyObject *__pyx_n_s__data; +static PyObject *__pyx_n_s__descr; +static PyObject *__pyx_n_s__double; +static PyObject *__pyx_n_s__dtype; +static PyObject *__pyx_n_s__e; +static PyObject *__pyx_n_s__edge; +static PyObject *__pyx_n_s__empty; +static PyObject *__pyx_n_s__eps; +static PyObject *__pyx_n_s__equations; +static PyObject *__pyx_n_s__facet_id; +static PyObject *__pyx_n_s__facet_list; +static PyObject *__pyx_n_s__fields; +static PyObject *__pyx_n_s__fill; +static PyObject *__pyx_n_s__find_simplex; +static PyObject *__pyx_n_s__finfo; +static PyObject *__pyx_n_s__format; +static PyObject *__pyx_n_s__id; +static PyObject *__pyx_n_s__info; +static PyObject *__pyx_n_s__int; +static PyObject *__pyx_n_s__itemsize; +static PyObject *__pyx_n_s__last_high; +static PyObject *__pyx_n_s__last_low; +static PyObject *__pyx_n_s__last_newhigh; +static PyObject *__pyx_n_s__lift_points; +static PyObject *__pyx_n_s__max; +static PyObject *__pyx_n_s__max_bound; +static PyObject *__pyx_n_s__min; +static PyObject *__pyx_n_s__min_bound; +static PyObject *__pyx_n_s__names; +static PyObject *__pyx_n_s__nan; +static PyObject *__pyx_n_s__ndim; +static PyObject *__pyx_n_s__neighbors; +static PyObject *__pyx_n_s__next; +static PyObject *__pyx_n_s__normal; +static PyObject *__pyx_n_s__np; +static PyObject *__pyx_n_s__npoints; +static PyObject *__pyx_n_s__nsimplex; +static PyObject *__pyx_n_s__numpoints; +static PyObject *__pyx_n_s__numpy; +static PyObject *__pyx_n_s__obj; +static PyObject *__pyx_n_s__object; +static PyObject *__pyx_n_s__offset; +static PyObject *__pyx_n_s__p; +static PyObject *__pyx_n_s__paraboloid_scale; +static PyObject *__pyx_n_s__paraboloid_shift; +static PyObject *__pyx_n_s__plane_distance; +static PyObject *__pyx_n_s__point; +static PyObject *__pyx_n_s__points; +static PyObject *__pyx_n_s__prod; +static PyObject *__pyx_n_s__property; +static PyObject *__pyx_n_s__range; +static PyObject *__pyx_n_s__readonly; +static PyObject *__pyx_n_s__release; +static PyObject *__pyx_n_s__reshape; +static PyObject *__pyx_n_s__resize; +static PyObject *__pyx_n_s__self; +static PyObject *__pyx_n_s__shape; +static PyObject *__pyx_n_s__simplicial; +static PyObject *__pyx_n_s__start_edge; +static PyObject *__pyx_n_s__start_triangle; +static PyObject *__pyx_n_s__strides; +static PyObject *__pyx_n_s__suboffsets; +static PyObject *__pyx_n_s__sum; +static PyObject *__pyx_n_s__threading; +static PyObject *__pyx_n_s__transform; +static PyObject *__pyx_n_s__tri; +static PyObject *__pyx_n_s__triangle; +static PyObject *__pyx_n_s__tsearch; +static PyObject *__pyx_n_s__type_num; +static PyObject *__pyx_n_s__upperdelaunay; +static PyObject *__pyx_n_s__vertex; +static PyObject *__pyx_n_s__vertex2; +static PyObject *__pyx_n_s__vertex_to_simplex; +static PyObject *__pyx_n_s__vertices; +static PyObject *__pyx_n_s__x; +static PyObject *__pyx_n_s__xi; +static PyObject *__pyx_n_s__xrange; +static PyObject *__pyx_n_s__zeros; +static PyObject *__pyx_int_0; +static PyObject *__pyx_int_1; +static PyObject *__pyx_int_2; +static PyObject *__pyx_int_neg_1; +static PyObject *__pyx_int_10; +static PyObject *__pyx_int_15; +static PyObject *__pyx_k_9; + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull__construct_delaunay(PyObject *__pyx_self, PyObject *__pyx_v_points); +static char __pyx_doc_5scipy_7spatial_5qhull__construct_delaunay[] = "\n Perform Delaunay triangulation of the given set of points.\n\n "; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull__construct_delaunay(PyObject *__pyx_self, PyObject *__pyx_v_points) { + char *__pyx_v_options; + int __pyx_v_curlong; + int __pyx_v_totlong; + int __pyx_v_dim; + int __pyx_v_numpoints; + int __pyx_v_exitcode; + PyObject *__pyx_v_paraboloid_scale; + PyObject *__pyx_v_paraboloid_shift; + PyObject *__pyx_v_vertices; + PyObject *__pyx_v_neighbors; + PyObject *__pyx_v_equations; + Py_buffer __pyx_bstruct_points; + Py_ssize_t __pyx_bstride_0_points = 0; + Py_ssize_t __pyx_bstride_1_points = 0; + Py_ssize_t __pyx_bshape_0_points = 0; + Py_ssize_t __pyx_bshape_1_points = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyArrayObject *__pyx_t_4 = NULL; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_t_9; + boolT __pyx_t_10; + realT __pyx_t_11; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + int __pyx_t_14; + int __pyx_t_15; + __Pyx_RefNannySetupContext("_construct_delaunay"); + __pyx_self = __pyx_self; + __Pyx_INCREF((PyObject *)__pyx_v_points); + __pyx_v_paraboloid_scale = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_paraboloid_shift = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_vertices = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_neighbors = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_equations = Py_None; __Pyx_INCREF(Py_None); + __pyx_bstruct_points.buf = NULL; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_points), __pyx_ptype_5numpy_ndarray, 1, "points", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_points, (PyObject*)__pyx_v_points, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_bstride_0_points = __pyx_bstruct_points.strides[0]; __pyx_bstride_1_points = __pyx_bstruct_points.strides[1]; + __pyx_bshape_0_points = __pyx_bstruct_points.shape[0]; __pyx_bshape_1_points = __pyx_bstruct_points.shape[1]; + + + __pyx_v_options = __pyx_k_1; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__ascontiguousarray); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __pyx_t_3 = PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = __pyx_t_3; + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __pyx_t_5 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_points, (PyObject*)__pyx_t_4, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_5 < 0)) { + PyErr_Fetch(&__pyx_t_6, &__pyx_t_7, &__pyx_t_8); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_points, (PyObject*)__pyx_v_points, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_6); Py_XDECREF(__pyx_t_7); Py_XDECREF(__pyx_t_8); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_6, __pyx_t_7, __pyx_t_8); + } + } + __pyx_bstride_0_points = __pyx_bstruct_points.strides[0]; __pyx_bstride_1_points = __pyx_bstruct_points.strides[1]; + __pyx_bshape_0_points = __pyx_bstruct_points.shape[0]; __pyx_bshape_1_points = __pyx_bstruct_points.shape[1]; + if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_v_points); + __pyx_v_points = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_v_numpoints = (((PyArrayObject *)__pyx_v_points)->dimensions[0]); + + + __pyx_v_dim = (((PyArrayObject *)__pyx_v_points)->dimensions[1]); + + + __pyx_t_9 = (__pyx_v_numpoints <= 0); + if (__pyx_t_9) { + + + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 155; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_2)); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_kp_s_2)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_2)); + __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 155; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_1, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 155; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L5; + } + __pyx_L5:; + + + __pyx_t_9 = (__pyx_v_dim < 2); + if (__pyx_t_9) { + + + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_3)); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_kp_s_3)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_3)); + __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s___qhull_lock); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__acquire); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + + { + + + qh_qh.NOerrexit = 1; + + + __pyx_v_exitcode = qh_new_qhull(__pyx_v_dim, __pyx_v_numpoints, ((realT *)((PyArrayObject *)__pyx_v_points)->data), 0, __pyx_v_options, NULL, stderr); + + + { + + + __pyx_t_9 = (__pyx_v_exitcode != 0); + if (__pyx_t_9) { + + + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_4)); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_kp_s_4)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_4)); + __pyx_t_1 = PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_1, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L11;} + goto __pyx_L13; + } + __pyx_L13:; + + + qh_triangulate(); + + + __pyx_t_10 = qh_qh.SCALElast; + if (__pyx_t_10) { + + + __pyx_t_11 = (qh_qh.last_high - qh_qh.last_low); + if (unlikely(__pyx_t_11 == 0)) { + PyErr_Format(PyExc_ZeroDivisionError, "float division"); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L11;} + } + __pyx_t_1 = PyFloat_FromDouble((qh_qh.last_newhigh / __pyx_t_11)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_v_paraboloid_scale); + __pyx_v_paraboloid_scale = __pyx_t_1; + __pyx_t_1 = 0; + + + __pyx_t_1 = PyFloat_FromDouble((-qh_qh.last_low)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyNumber_Multiply(__pyx_t_1, __pyx_v_paraboloid_scale); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_paraboloid_shift); + __pyx_v_paraboloid_shift = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L14; + } + { + + + __pyx_t_3 = PyFloat_FromDouble(1.0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_v_paraboloid_scale); + __pyx_v_paraboloid_scale = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyFloat_FromDouble(0.0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_v_paraboloid_shift); + __pyx_v_paraboloid_shift = __pyx_t_3; + __pyx_t_3 = 0; + } + __pyx_L14:; + + + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyInt_FromLong(__pyx_v_dim); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyInt_FromLong(__pyx_v_numpoints); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_12 = PyTuple_New(2); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_12); + PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_12, 1, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_1 = 0; + __pyx_t_2 = 0; + __pyx_t_2 = PyObject_Call(__pyx_t_3, __pyx_t_12, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + if (PyTuple_CheckExact(__pyx_t_2) && likely(PyTuple_GET_SIZE(__pyx_t_2) == 3)) { + PyObject* tuple = __pyx_t_2; + __pyx_t_12 = PyTuple_GET_ITEM(tuple, 0); __Pyx_INCREF(__pyx_t_12); + __pyx_t_3 = PyTuple_GET_ITEM(tuple, 1); __Pyx_INCREF(__pyx_t_3); + __pyx_t_1 = PyTuple_GET_ITEM(tuple, 2); __Pyx_INCREF(__pyx_t_1); + + + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_vertices); + __pyx_v_vertices = __pyx_t_12; + __pyx_t_12 = 0; + __Pyx_DECREF(__pyx_v_neighbors); + __pyx_v_neighbors = __pyx_t_3; + __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_equations); + __pyx_v_equations = __pyx_t_1; + __pyx_t_1 = 0; + } else { + __pyx_t_13 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_13); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_12 = __Pyx_UnpackItem(__pyx_t_13, 0); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_3 = __Pyx_UnpackItem(__pyx_t_13, 1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_UnpackItem(__pyx_t_13, 2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_1); + if (__Pyx_EndUnpack(__pyx_t_13) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_DECREF(__pyx_v_vertices); + __pyx_v_vertices = __pyx_t_12; + __pyx_t_12 = 0; + __Pyx_DECREF(__pyx_v_neighbors); + __pyx_v_neighbors = __pyx_t_3; + __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_equations); + __pyx_v_equations = __pyx_t_1; + __pyx_t_1 = 0; + } + + + __Pyx_XDECREF(__pyx_r); + + + __pyx_t_2 = PyTuple_New(5); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 182; __pyx_clineno = __LINE__; goto __pyx_L11;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_vertices); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_vertices); + __Pyx_GIVEREF(__pyx_v_vertices); + __Pyx_INCREF(__pyx_v_neighbors); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_neighbors); + __Pyx_GIVEREF(__pyx_v_neighbors); + __Pyx_INCREF(__pyx_v_equations); + PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_v_equations); + __Pyx_GIVEREF(__pyx_v_equations); + __Pyx_INCREF(__pyx_v_paraboloid_scale); + PyTuple_SET_ITEM(__pyx_t_2, 3, __pyx_v_paraboloid_scale); + __Pyx_GIVEREF(__pyx_v_paraboloid_scale); + __Pyx_INCREF(__pyx_v_paraboloid_shift); + PyTuple_SET_ITEM(__pyx_t_2, 4, __pyx_v_paraboloid_shift); + __Pyx_GIVEREF(__pyx_v_paraboloid_shift); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L10; + } + { + int __pyx_why; + PyObject *__pyx_exc_type, *__pyx_exc_value, *__pyx_exc_tb; + int __pyx_exc_lineno; + __pyx_exc_type = 0; __pyx_exc_value = 0; __pyx_exc_tb = 0; __pyx_exc_lineno = 0; + __pyx_why = 0; goto __pyx_L12; + __pyx_L10: __pyx_exc_type = 0; __pyx_exc_value = 0; __pyx_exc_tb = 0; __pyx_exc_lineno = 0; + __pyx_why = 3; goto __pyx_L12; + __pyx_L11: { + __pyx_why = 4; + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_ErrFetch(&__pyx_exc_type, &__pyx_exc_value, &__pyx_exc_tb); + __pyx_exc_lineno = __pyx_lineno; + goto __pyx_L12; + } + __pyx_L12:; + + + qh_freeqhull(0); + + + qh_memfreeshort((&__pyx_v_curlong), (&__pyx_v_totlong)); + + + __pyx_t_9 = (__pyx_v_curlong != 0); + if (!__pyx_t_9) { + __pyx_t_14 = (__pyx_v_totlong != 0); + __pyx_t_15 = __pyx_t_14; + } else { + __pyx_t_15 = __pyx_t_9; + } + if (__pyx_t_15) { + + + __pyx_t_2 = PyInt_FromLong(__pyx_v_totlong); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L15_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyInt_FromLong(__pyx_v_curlong); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L15_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L15_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_2 = 0; + __pyx_t_1 = 0; + __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_6), __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L15_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L15_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L15_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_1, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L15_error;} + goto __pyx_L16; + } + __pyx_L16:; + goto __pyx_L17; + __pyx_L15_error:; + if (__pyx_why == 4) { + Py_XDECREF(__pyx_exc_type); + Py_XDECREF(__pyx_exc_value); + Py_XDECREF(__pyx_exc_tb); + } + goto __pyx_L8; + __pyx_L17:; + switch (__pyx_why) { + case 3: goto __pyx_L7; + case 4: { + __Pyx_ErrRestore(__pyx_exc_type, __pyx_exc_value, __pyx_exc_tb); + __pyx_lineno = __pyx_exc_lineno; + __pyx_exc_type = 0; + __pyx_exc_value = 0; + __pyx_exc_tb = 0; + goto __pyx_L8; + } + } + } + } + { + int __pyx_why; + PyObject *__pyx_exc_type, *__pyx_exc_value, *__pyx_exc_tb; + int __pyx_exc_lineno; + __pyx_exc_type = 0; __pyx_exc_value = 0; __pyx_exc_tb = 0; __pyx_exc_lineno = 0; + __pyx_why = 0; goto __pyx_L9; + __pyx_L7: __pyx_exc_type = 0; __pyx_exc_value = 0; __pyx_exc_tb = 0; __pyx_exc_lineno = 0; + __pyx_why = 3; goto __pyx_L9; + __pyx_L8: { + __pyx_why = 4; + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_ErrFetch(&__pyx_exc_type, &__pyx_exc_value, &__pyx_exc_tb); + __pyx_exc_lineno = __pyx_lineno; + goto __pyx_L9; + } + __pyx_L9:; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s___qhull_lock); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L18_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__release); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L18_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L18_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L19; + __pyx_L18_error:; + if (__pyx_why == 4) { + Py_XDECREF(__pyx_exc_type); + Py_XDECREF(__pyx_exc_value); + Py_XDECREF(__pyx_exc_tb); + } + goto __pyx_L1_error; + __pyx_L19:; + switch (__pyx_why) { + case 3: goto __pyx_L0; + case 4: { + __Pyx_ErrRestore(__pyx_exc_type, __pyx_exc_value, __pyx_exc_tb); + __pyx_lineno = __pyx_exc_lineno; + __pyx_exc_type = 0; + __pyx_exc_value = 0; + __pyx_exc_tb = 0; + goto __pyx_L1_error; + } + } + } + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_13); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("scipy.spatial.qhull._construct_delaunay"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __pyx_L2:; + __Pyx_DECREF(__pyx_v_paraboloid_scale); + __Pyx_DECREF(__pyx_v_paraboloid_shift); + __Pyx_DECREF(__pyx_v_vertices); + __Pyx_DECREF(__pyx_v_neighbors); + __Pyx_DECREF(__pyx_v_equations); + __Pyx_DECREF((PyObject *)__pyx_v_points); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull__qhull_get_facet_array(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static char __pyx_doc_5scipy_7spatial_5qhull__qhull_get_facet_array[] = "\n Return array of simplical facets currently in Qhull.\n\n Returns\n -------\n vertices : array of int, shape (nfacets, ndim+1)\n Indices of coordinates of vertices forming the simplical facets\n neighbors : array of int, shape (nfacets, ndim)\n Indices of neighboring facets. The kth neighbor is opposite\n the kth vertex, and the first neighbor is the horizon facet\n for the first vertex.\n\n Facets extending to infinity are denoted with index -1.\n\n "; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull__qhull_get_facet_array(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + int __pyx_v_ndim; + int __pyx_v_numpoints; + facetT *__pyx_v_facet; + facetT *__pyx_v_neighbor; + vertexT *__pyx_v_vertex; + int __pyx_v_i; + int __pyx_v_j; + int __pyx_v_point; + PyArrayObject *__pyx_v_vertices; + PyArrayObject *__pyx_v_neighbors; + PyArrayObject *__pyx_v_equations; + PyArrayObject *__pyx_v_id_map; + Py_buffer __pyx_bstruct_neighbors; + Py_ssize_t __pyx_bstride_0_neighbors = 0; + Py_ssize_t __pyx_bstride_1_neighbors = 0; + Py_ssize_t __pyx_bshape_0_neighbors = 0; + Py_ssize_t __pyx_bshape_1_neighbors = 0; + Py_buffer __pyx_bstruct_id_map; + Py_ssize_t __pyx_bstride_0_id_map = 0; + Py_ssize_t __pyx_bshape_0_id_map = 0; + Py_buffer __pyx_bstruct_vertices; + Py_ssize_t __pyx_bstride_0_vertices = 0; + Py_ssize_t __pyx_bstride_1_vertices = 0; + Py_ssize_t __pyx_bshape_0_vertices = 0; + Py_ssize_t __pyx_bshape_1_vertices = 0; + Py_buffer __pyx_bstruct_equations; + Py_ssize_t __pyx_bstride_0_equations = 0; + Py_ssize_t __pyx_bstride_1_equations = 0; + Py_ssize_t __pyx_bshape_0_equations = 0; + Py_ssize_t __pyx_bshape_1_equations = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + int __pyx_t_11; + int __pyx_t_12; + unsigned int __pyx_t_13; + PyArrayObject *__pyx_t_14 = NULL; + PyArrayObject *__pyx_t_15 = NULL; + PyArrayObject *__pyx_t_16 = NULL; + flagT __pyx_t_17; + long __pyx_t_18; + int __pyx_t_19; + int __pyx_t_20; + int __pyx_t_21; + unsigned int __pyx_t_22; + int __pyx_t_23; + int __pyx_t_24; + int __pyx_t_25; + int __pyx_t_26; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__ndim,&__pyx_n_s__numpoints,0}; + __Pyx_RefNannySetupContext("_qhull_get_facet_array"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__ndim); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__numpoints); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_qhull_get_facet_array", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_qhull_get_facet_array") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_ndim = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_ndim == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_numpoints = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_numpoints == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_ndim = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_ndim == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_numpoints = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_numpoints == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_qhull_get_facet_array", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("scipy.spatial.qhull._qhull_get_facet_array"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_v_vertices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_neighbors = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_equations = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_id_map = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_bstruct_vertices.buf = NULL; + __pyx_bstruct_neighbors.buf = NULL; + __pyx_bstruct_equations.buf = NULL; + __pyx_bstruct_id_map.buf = NULL; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyLong_FromUnsignedLong(qh_qh.facet_id); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__int); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, __pyx_t_1, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id_map); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_id_map, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_id_map, (PyObject*)__pyx_v_id_map, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_8, __pyx_t_9, __pyx_t_10); + } + } + __pyx_bstride_0_id_map = __pyx_bstruct_id_map.strides[0]; + __pyx_bshape_0_id_map = __pyx_bstruct_id_map.shape[0]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_6 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_id_map)); + __pyx_v_id_map = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + + __pyx_t_5 = PyObject_GetAttr(((PyObject *)__pyx_v_id_map), __pyx_n_s__fill); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_int_neg_1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_int_neg_1); + __Pyx_GIVEREF(__pyx_int_neg_1); + __pyx_t_1 = PyObject_Call(__pyx_t_5, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_v_facet = qh_qh.facet_list; + + + __pyx_v_j = 0; + + + while (1) { + if ((__pyx_v_facet != 0)) { + __pyx_t_11 = (__pyx_v_facet->next != 0); + } else { + __pyx_t_11 = (__pyx_v_facet != 0); + } + if (!__pyx_t_11) break; + + + if (__pyx_v_facet->simplicial) { + __pyx_t_11 = (!__pyx_v_facet->upperdelaunay); + __pyx_t_12 = __pyx_t_11; + } else { + __pyx_t_12 = __pyx_v_facet->simplicial; + } + if (__pyx_t_12) { + + + __pyx_t_13 = __pyx_v_facet->id; + __pyx_t_7 = -1; + if (unlikely(__pyx_t_13 >= __pyx_bshape_0_id_map)) __pyx_t_7 = 0; + if (unlikely(__pyx_t_7 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_7); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 228; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_bstruct_id_map.buf, __pyx_t_13, __pyx_bstride_0_id_map) = __pyx_v_j; + + + __pyx_v_j += 1; + goto __pyx_L8; + } + __pyx_L8:; + + + __pyx_v_facet = __pyx_v_facet->next; + } + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__zeros); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = PyInt_FromLong((__pyx_v_ndim + 1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_1 = 0; + __pyx_t_5 = 0; + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_2)); + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__int); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_3, __pyx_t_5, ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; + if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_14 = ((PyArrayObject *)__pyx_t_4); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_t_14, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_10, &__pyx_t_9, &__pyx_t_8); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_v_vertices, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_8); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_10, __pyx_t_9, __pyx_t_8); + } + } + __pyx_bstride_0_vertices = __pyx_bstruct_vertices.strides[0]; __pyx_bstride_1_vertices = __pyx_bstruct_vertices.strides[1]; + __pyx_bshape_0_vertices = __pyx_bstruct_vertices.shape[0]; __pyx_bshape_1_vertices = __pyx_bstruct_vertices.shape[1]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_14 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_vertices)); + __pyx_v_vertices = ((PyArrayObject *)__pyx_t_4); + __pyx_t_4 = 0; + + + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyInt_FromLong((__pyx_v_ndim + 1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_4 = 0; + __pyx_t_5 = 0; + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__int); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__dtype), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyEval_CallObjectWithKeywords(__pyx_t_2, __pyx_t_5, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_15 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_neighbors); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_neighbors, (PyObject*)__pyx_t_15, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_neighbors, (PyObject*)__pyx_v_neighbors, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_8, __pyx_t_9, __pyx_t_10); + } + } + __pyx_bstride_0_neighbors = __pyx_bstruct_neighbors.strides[0]; __pyx_bstride_1_neighbors = __pyx_bstruct_neighbors.strides[1]; + __pyx_bshape_0_neighbors = __pyx_bstruct_neighbors.shape[0]; __pyx_bshape_1_neighbors = __pyx_bstruct_neighbors.shape[1]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_15 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_neighbors)); + __pyx_v_neighbors = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__zeros); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = PyInt_FromLong((__pyx_v_ndim + 2)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_1 = 0; + __pyx_t_5 = 0; + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_2)); + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_3, __pyx_t_5, ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; + if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_16 = ((PyArrayObject *)__pyx_t_4); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_equations); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_equations, (PyObject*)__pyx_t_16, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_10, &__pyx_t_9, &__pyx_t_8); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_equations, (PyObject*)__pyx_v_equations, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_8); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_10, __pyx_t_9, __pyx_t_8); + } + } + __pyx_bstride_0_equations = __pyx_bstruct_equations.strides[0]; __pyx_bstride_1_equations = __pyx_bstruct_equations.strides[1]; + __pyx_bshape_0_equations = __pyx_bstruct_equations.shape[0]; __pyx_bshape_1_equations = __pyx_bstruct_equations.shape[1]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_16 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_equations)); + __pyx_v_equations = ((PyArrayObject *)__pyx_t_4); + __pyx_t_4 = 0; + + + __pyx_v_facet = qh_qh.facet_list; + + + __pyx_v_j = 0; + + + while (1) { + if ((__pyx_v_facet != 0)) { + __pyx_t_12 = (__pyx_v_facet->next != 0); + } else { + __pyx_t_12 = (__pyx_v_facet != 0); + } + if (!__pyx_t_12) break; + + + __pyx_t_12 = (!__pyx_v_facet->simplicial); + if (__pyx_t_12) { + + + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 242; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_7)); + PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_kp_s_7)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_7)); + __pyx_t_2 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 242; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_2, 0, 0); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 242; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L11; + } + __pyx_L11:; + + + __pyx_t_17 = __pyx_v_facet->upperdelaunay; + if (__pyx_t_17) { + + + __pyx_v_facet = __pyx_v_facet->next; + + + goto __pyx_L9_continue; + goto __pyx_L12; + } + __pyx_L12:; + + + __pyx_t_18 = (__pyx_v_ndim + 1); + for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_18; __pyx_t_7+=1) { + __pyx_v_i = __pyx_t_7; + + + __pyx_v_vertex = ((vertexT *)(__pyx_v_facet->vertices->e[__pyx_v_i]).p); + + + __pyx_v_point = qh_pointid(__pyx_v_vertex->point); + + + __pyx_t_19 = __pyx_v_j; + __pyx_t_20 = __pyx_v_i; + __pyx_t_21 = -1; + if (__pyx_t_19 < 0) { + __pyx_t_19 += __pyx_bshape_0_vertices; + if (unlikely(__pyx_t_19 < 0)) __pyx_t_21 = 0; + } else if (unlikely(__pyx_t_19 >= __pyx_bshape_0_vertices)) __pyx_t_21 = 0; + if (__pyx_t_20 < 0) { + __pyx_t_20 += __pyx_bshape_1_vertices; + if (unlikely(__pyx_t_20 < 0)) __pyx_t_21 = 1; + } else if (unlikely(__pyx_t_20 >= __pyx_bshape_1_vertices)) __pyx_t_21 = 1; + if (unlikely(__pyx_t_21 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_21); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_19, __pyx_bstride_0_vertices, __pyx_t_20, __pyx_bstride_1_vertices) = __pyx_v_point; + } + + + __pyx_t_18 = (__pyx_v_ndim + 1); + for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_18; __pyx_t_7+=1) { + __pyx_v_i = __pyx_t_7; + + + __pyx_v_neighbor = ((facetT *)(__pyx_v_facet->neighbors->e[__pyx_v_i]).p); + + + __pyx_t_22 = __pyx_v_neighbor->id; + __pyx_t_21 = -1; + if (unlikely(__pyx_t_22 >= __pyx_bshape_0_id_map)) __pyx_t_21 = 0; + if (unlikely(__pyx_t_21 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_21); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_21 = __pyx_v_j; + __pyx_t_23 = __pyx_v_i; + __pyx_t_24 = -1; + if (__pyx_t_21 < 0) { + __pyx_t_21 += __pyx_bshape_0_neighbors; + if (unlikely(__pyx_t_21 < 0)) __pyx_t_24 = 0; + } else if (unlikely(__pyx_t_21 >= __pyx_bshape_0_neighbors)) __pyx_t_24 = 0; + if (__pyx_t_23 < 0) { + __pyx_t_23 += __pyx_bshape_1_neighbors; + if (unlikely(__pyx_t_23 < 0)) __pyx_t_24 = 1; + } else if (unlikely(__pyx_t_23 >= __pyx_bshape_1_neighbors)) __pyx_t_24 = 1; + if (unlikely(__pyx_t_24 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_24); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_neighbors.buf, __pyx_t_21, __pyx_bstride_0_neighbors, __pyx_t_23, __pyx_bstride_1_neighbors) = (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_bstruct_id_map.buf, __pyx_t_22, __pyx_bstride_0_id_map)); + } + + + __pyx_t_18 = (__pyx_v_ndim + 1); + for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_18; __pyx_t_7+=1) { + __pyx_v_i = __pyx_t_7; + + + __pyx_t_24 = __pyx_v_j; + __pyx_t_25 = __pyx_v_i; + __pyx_t_26 = -1; + if (__pyx_t_24 < 0) { + __pyx_t_24 += __pyx_bshape_0_equations; + if (unlikely(__pyx_t_24 < 0)) __pyx_t_26 = 0; + } else if (unlikely(__pyx_t_24 >= __pyx_bshape_0_equations)) __pyx_t_26 = 0; + if (__pyx_t_25 < 0) { + __pyx_t_25 += __pyx_bshape_1_equations; + if (unlikely(__pyx_t_25 < 0)) __pyx_t_26 = 1; + } else if (unlikely(__pyx_t_25 >= __pyx_bshape_1_equations)) __pyx_t_26 = 1; + if (unlikely(__pyx_t_26 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_26); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_equations.buf, __pyx_t_24, __pyx_bstride_0_equations, __pyx_t_25, __pyx_bstride_1_equations) = (__pyx_v_facet->normal[__pyx_v_i]); + } + + + __pyx_t_7 = __pyx_v_j; + __pyx_t_18 = (__pyx_v_ndim + 1); + __pyx_t_26 = -1; + if (__pyx_t_7 < 0) { + __pyx_t_7 += __pyx_bshape_0_equations; + if (unlikely(__pyx_t_7 < 0)) __pyx_t_26 = 0; + } else if (unlikely(__pyx_t_7 >= __pyx_bshape_0_equations)) __pyx_t_26 = 0; + if (__pyx_t_18 < 0) { + __pyx_t_18 += __pyx_bshape_1_equations; + if (unlikely(__pyx_t_18 < 0)) __pyx_t_26 = 1; + } else if (unlikely(__pyx_t_18 >= __pyx_bshape_1_equations)) __pyx_t_26 = 1; + if (unlikely(__pyx_t_26 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_26); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 262; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_equations.buf, __pyx_t_7, __pyx_bstride_0_equations, __pyx_t_18, __pyx_bstride_1_equations) = __pyx_v_facet->offset; + + + __pyx_v_j += 1; + + + __pyx_v_facet = __pyx_v_facet->next; + __pyx_L9_continue:; + } + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 267; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(((PyObject *)__pyx_v_vertices)); + PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_vertices)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_vertices)); + __Pyx_INCREF(((PyObject *)__pyx_v_neighbors)); + PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_v_neighbors)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_neighbors)); + __Pyx_INCREF(((PyObject *)__pyx_v_equations)); + PyTuple_SET_ITEM(__pyx_t_2, 2, ((PyObject *)__pyx_v_equations)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_equations)); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_neighbors); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id_map); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_equations); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("scipy.spatial.qhull._qhull_get_facet_array"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_neighbors); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_id_map); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_equations); + __pyx_L2:; + __Pyx_DECREF((PyObject *)__pyx_v_vertices); + __Pyx_DECREF((PyObject *)__pyx_v_neighbors); + __Pyx_DECREF((PyObject *)__pyx_v_equations); + __Pyx_DECREF((PyObject *)__pyx_v_id_map); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull__get_barycentric_transforms(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static char __pyx_doc_5scipy_7spatial_5qhull__get_barycentric_transforms[] = "\n Compute barycentric affine coordinate transformations for given\n simplices.\n\n Returns\n -------\n Tinvs : array, shape (nsimplex, ndim+1, ndim)\n Barycentric transforms for each simplex.\n\n Tinvs[i,:ndim,:ndim] contains inverse of the matrix ``T``,\n and Tinvs[i,ndim,:] contains the vector ``r_n`` (see below).\n\n Notes\n -----\n Barycentric transform from ``x`` to ``c`` is defined by::\n\n T c = x - r_n\n\n where the ``r_1, ..., r_n`` are the vertices of the simplex.\n The matrix ``T`` is defined by the condition::\n\n T e_j = r_j - r_n\n\n where ``e_j`` is the unit axis vector, e.g, ``e_2 = [0,1,0,0,...]``\n This implies that ``T_ij = (r_j - r_n)_i``.\n\n For the barycentric transforms, we need to compute the inverse\n matrix ``T^-1`` and store the vectors ``r_n`` for each vertex.\n These are stacked into the `Tinvs` returned.\n\n "; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull__get_barycentric_transforms(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyArrayObject *__pyx_v_points = 0; + PyArrayObject *__pyx_v_vertices = 0; + PyArrayObject *__pyx_v_T; + PyArrayObject *__pyx_v_Tinvs; + int __pyx_v_ivertex; + int __pyx_v_i; + int __pyx_v_j; + int __pyx_v_n; + int __pyx_v_nrhs; + int __pyx_v_lda; + int __pyx_v_ldb; + int __pyx_v_info; + int __pyx_v_ipiv[(NPY_MAXDIMS + 1)]; + int __pyx_v_ndim; + int __pyx_v_nvertex; + double __pyx_v_nan; + double __pyx_v_x1; + double __pyx_v_x2; + double __pyx_v_x3; + double __pyx_v_y1; + double __pyx_v_y2; + double __pyx_v_y3; + double __pyx_v_det; + Py_buffer __pyx_bstruct_Tinvs; + Py_ssize_t __pyx_bstride_0_Tinvs = 0; + Py_ssize_t __pyx_bstride_1_Tinvs = 0; + Py_ssize_t __pyx_bstride_2_Tinvs = 0; + Py_ssize_t __pyx_bshape_0_Tinvs = 0; + Py_ssize_t __pyx_bshape_1_Tinvs = 0; + Py_ssize_t __pyx_bshape_2_Tinvs = 0; + Py_buffer __pyx_bstruct_T; + Py_ssize_t __pyx_bstride_0_T = 0; + Py_ssize_t __pyx_bstride_1_T = 0; + Py_ssize_t __pyx_bshape_0_T = 0; + Py_ssize_t __pyx_bshape_1_T = 0; + Py_buffer __pyx_bstruct_vertices; + Py_ssize_t __pyx_bstride_0_vertices = 0; + Py_ssize_t __pyx_bstride_1_vertices = 0; + Py_ssize_t __pyx_bshape_0_vertices = 0; + Py_ssize_t __pyx_bshape_1_vertices = 0; + Py_buffer __pyx_bstruct_points; + Py_ssize_t __pyx_bstride_0_points = 0; + Py_ssize_t __pyx_bstride_1_points = 0; + Py_ssize_t __pyx_bshape_0_points = 0; + Py_ssize_t __pyx_bshape_1_points = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + double __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyArrayObject *__pyx_t_7 = NULL; + int __pyx_t_8; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyArrayObject *__pyx_t_12 = NULL; + int __pyx_t_13; + int __pyx_t_14; + int __pyx_t_15; + long __pyx_t_16; + __pyx_t_5numpy_int_t __pyx_t_17; + long __pyx_t_18; + int __pyx_t_19; + long __pyx_t_20; + __pyx_t_5numpy_int_t __pyx_t_21; + long __pyx_t_22; + int __pyx_t_23; + long __pyx_t_24; + __pyx_t_5numpy_int_t __pyx_t_25; + long __pyx_t_26; + int __pyx_t_27; + long __pyx_t_28; + __pyx_t_5numpy_int_t __pyx_t_29; + long __pyx_t_30; + int __pyx_t_31; + long __pyx_t_32; + __pyx_t_5numpy_int_t __pyx_t_33; + long __pyx_t_34; + int __pyx_t_35; + long __pyx_t_36; + __pyx_t_5numpy_int_t __pyx_t_37; + long __pyx_t_38; + int __pyx_t_39; + long __pyx_t_40; + long __pyx_t_41; + int __pyx_t_42; + long __pyx_t_43; + long __pyx_t_44; + int __pyx_t_45; + long __pyx_t_46; + long __pyx_t_47; + int __pyx_t_48; + long __pyx_t_49; + long __pyx_t_50; + int __pyx_t_51; + long __pyx_t_52; + long __pyx_t_53; + int __pyx_t_54; + long __pyx_t_55; + long __pyx_t_56; + int __pyx_t_57; + int __pyx_t_58; + int __pyx_t_59; + int __pyx_t_60; + __pyx_t_5numpy_int_t __pyx_t_61; + int __pyx_t_62; + int __pyx_t_63; + int __pyx_t_64; + int __pyx_t_65; + int __pyx_t_66; + int __pyx_t_67; + int __pyx_t_68; + int __pyx_t_69; + __pyx_t_5numpy_int_t __pyx_t_70; + int __pyx_t_71; + int __pyx_t_72; + int __pyx_t_73; + int __pyx_t_74; + int __pyx_t_75; + int __pyx_t_76; + int __pyx_t_77; + long __pyx_t_78; + int __pyx_t_79; + int __pyx_t_80; + int __pyx_t_81; + int __pyx_t_82; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__points,&__pyx_n_s__vertices,0}; + __Pyx_RefNannySetupContext("_get_barycentric_transforms"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__points); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__vertices); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_get_barycentric_transforms", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_get_barycentric_transforms") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_points = ((PyArrayObject *)values[0]); + __pyx_v_vertices = ((PyArrayObject *)values[1]); + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_points = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 0)); + __pyx_v_vertices = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 1)); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_get_barycentric_transforms", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("scipy.spatial.qhull._get_barycentric_transforms"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF((PyObject *)__pyx_v_points); + __Pyx_INCREF((PyObject *)__pyx_v_vertices); + __pyx_v_T = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_Tinvs = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_bstruct_T.buf = NULL; + __pyx_bstruct_Tinvs.buf = NULL; + __pyx_bstruct_points.buf = NULL; + __pyx_bstruct_vertices.buf = NULL; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_points), __pyx_ptype_5numpy_ndarray, 1, "points", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_vertices), __pyx_ptype_5numpy_ndarray, 1, "vertices", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_points, (PyObject*)__pyx_v_points, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_bstride_0_points = __pyx_bstruct_points.strides[0]; __pyx_bstride_1_points = __pyx_bstruct_points.strides[1]; + __pyx_bshape_0_points = __pyx_bstruct_points.shape[0]; __pyx_bshape_1_points = __pyx_bstruct_points.shape[1]; + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_v_vertices, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_bstride_0_vertices = __pyx_bstruct_vertices.strides[0]; __pyx_bstride_1_vertices = __pyx_bstruct_vertices.strides[1]; + __pyx_bshape_0_vertices = __pyx_bstruct_vertices.shape[0]; __pyx_bshape_1_vertices = __pyx_bstruct_vertices.shape[1]; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__nan); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_nan = __pyx_t_3; + + + __pyx_v_ndim = (__pyx_v_points->dimensions[1]); + + + __pyx_v_nvertex = (__pyx_v_vertices->dimensions[0]); + + + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyInt_FromLong(__pyx_v_ndim); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyInt_FromLong(__pyx_v_ndim); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_2 = 0; + __pyx_t_4 = 0; + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_5)); + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_6 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_1, __pyx_t_4, ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0; + if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_7 = ((PyArrayObject *)__pyx_t_6); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_T); + __pyx_t_8 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_T, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_8 < 0)) { + PyErr_Fetch(&__pyx_t_9, &__pyx_t_10, &__pyx_t_11); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_T, (PyObject*)__pyx_v_T, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_9, __pyx_t_10, __pyx_t_11); + } + } + __pyx_bstride_0_T = __pyx_bstruct_T.strides[0]; __pyx_bstride_1_T = __pyx_bstruct_T.strides[1]; + __pyx_bshape_0_T = __pyx_bstruct_T.shape[0]; __pyx_bshape_1_T = __pyx_bstruct_T.shape[1]; + if (unlikely(__pyx_t_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_7 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_T)); + __pyx_v_T = ((PyArrayObject *)__pyx_t_6); + __pyx_t_6 = 0; + + + __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__zeros); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyInt_FromLong(__pyx_v_nvertex); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = PyInt_FromLong((__pyx_v_ndim + 1)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyInt_FromLong(__pyx_v_ndim); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_6 = 0; + __pyx_t_4 = 0; + __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_2)); + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_5, __pyx_t_1, ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; + if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_12 = ((PyArrayObject *)__pyx_t_6); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_Tinvs); + __pyx_t_8 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_Tinvs, (PyObject*)__pyx_t_12, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack); + if (unlikely(__pyx_t_8 < 0)) { + PyErr_Fetch(&__pyx_t_11, &__pyx_t_10, &__pyx_t_9); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_Tinvs, (PyObject*)__pyx_v_Tinvs, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 3, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_9); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_11, __pyx_t_10, __pyx_t_9); + } + } + __pyx_bstride_0_Tinvs = __pyx_bstruct_Tinvs.strides[0]; __pyx_bstride_1_Tinvs = __pyx_bstruct_Tinvs.strides[1]; __pyx_bstride_2_Tinvs = __pyx_bstruct_Tinvs.strides[2]; + __pyx_bshape_0_Tinvs = __pyx_bstruct_Tinvs.shape[0]; __pyx_bshape_1_Tinvs = __pyx_bstruct_Tinvs.shape[1]; __pyx_bshape_2_Tinvs = __pyx_bstruct_Tinvs.shape[2]; + if (unlikely(__pyx_t_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_12 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_Tinvs)); + __pyx_v_Tinvs = ((PyArrayObject *)__pyx_t_6); + __pyx_t_6 = 0; + + + __pyx_t_8 = __pyx_v_nvertex; + for (__pyx_t_13 = 0; __pyx_t_13 < __pyx_t_8; __pyx_t_13+=1) { + __pyx_v_ivertex = __pyx_t_13; + + + __pyx_t_14 = (__pyx_v_ndim == 2); + if (__pyx_t_14) { + + + __pyx_t_15 = __pyx_v_ivertex; + __pyx_t_16 = 0; + if (__pyx_t_15 < 0) __pyx_t_15 += __pyx_bshape_0_vertices; + if (__pyx_t_16 < 0) __pyx_t_16 += __pyx_bshape_1_vertices; + __pyx_t_17 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_15, __pyx_bstride_0_vertices, __pyx_t_16, __pyx_bstride_1_vertices)); + __pyx_t_18 = 0; + if (__pyx_t_17 < 0) __pyx_t_17 += __pyx_bshape_0_points; + if (__pyx_t_18 < 0) __pyx_t_18 += __pyx_bshape_1_points; + __pyx_v_x1 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_points.buf, __pyx_t_17, __pyx_bstride_0_points, __pyx_t_18, __pyx_bstride_1_points)); + + + __pyx_t_19 = __pyx_v_ivertex; + __pyx_t_20 = 1; + if (__pyx_t_19 < 0) __pyx_t_19 += __pyx_bshape_0_vertices; + if (__pyx_t_20 < 0) __pyx_t_20 += __pyx_bshape_1_vertices; + __pyx_t_21 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_19, __pyx_bstride_0_vertices, __pyx_t_20, __pyx_bstride_1_vertices)); + __pyx_t_22 = 0; + if (__pyx_t_21 < 0) __pyx_t_21 += __pyx_bshape_0_points; + if (__pyx_t_22 < 0) __pyx_t_22 += __pyx_bshape_1_points; + __pyx_v_x2 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_points.buf, __pyx_t_21, __pyx_bstride_0_points, __pyx_t_22, __pyx_bstride_1_points)); + + + __pyx_t_23 = __pyx_v_ivertex; + __pyx_t_24 = 2; + if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_bshape_0_vertices; + if (__pyx_t_24 < 0) __pyx_t_24 += __pyx_bshape_1_vertices; + __pyx_t_25 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_23, __pyx_bstride_0_vertices, __pyx_t_24, __pyx_bstride_1_vertices)); + __pyx_t_26 = 0; + if (__pyx_t_25 < 0) __pyx_t_25 += __pyx_bshape_0_points; + if (__pyx_t_26 < 0) __pyx_t_26 += __pyx_bshape_1_points; + __pyx_v_x3 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_points.buf, __pyx_t_25, __pyx_bstride_0_points, __pyx_t_26, __pyx_bstride_1_points)); + + + __pyx_t_27 = __pyx_v_ivertex; + __pyx_t_28 = 0; + if (__pyx_t_27 < 0) __pyx_t_27 += __pyx_bshape_0_vertices; + if (__pyx_t_28 < 0) __pyx_t_28 += __pyx_bshape_1_vertices; + __pyx_t_29 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_27, __pyx_bstride_0_vertices, __pyx_t_28, __pyx_bstride_1_vertices)); + __pyx_t_30 = 1; + if (__pyx_t_29 < 0) __pyx_t_29 += __pyx_bshape_0_points; + if (__pyx_t_30 < 0) __pyx_t_30 += __pyx_bshape_1_points; + __pyx_v_y1 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_points.buf, __pyx_t_29, __pyx_bstride_0_points, __pyx_t_30, __pyx_bstride_1_points)); + + + __pyx_t_31 = __pyx_v_ivertex; + __pyx_t_32 = 1; + if (__pyx_t_31 < 0) __pyx_t_31 += __pyx_bshape_0_vertices; + if (__pyx_t_32 < 0) __pyx_t_32 += __pyx_bshape_1_vertices; + __pyx_t_33 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_31, __pyx_bstride_0_vertices, __pyx_t_32, __pyx_bstride_1_vertices)); + __pyx_t_34 = 1; + if (__pyx_t_33 < 0) __pyx_t_33 += __pyx_bshape_0_points; + if (__pyx_t_34 < 0) __pyx_t_34 += __pyx_bshape_1_points; + __pyx_v_y2 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_points.buf, __pyx_t_33, __pyx_bstride_0_points, __pyx_t_34, __pyx_bstride_1_points)); + + + __pyx_t_35 = __pyx_v_ivertex; + __pyx_t_36 = 2; + if (__pyx_t_35 < 0) __pyx_t_35 += __pyx_bshape_0_vertices; + if (__pyx_t_36 < 0) __pyx_t_36 += __pyx_bshape_1_vertices; + __pyx_t_37 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_35, __pyx_bstride_0_vertices, __pyx_t_36, __pyx_bstride_1_vertices)); + __pyx_t_38 = 1; + if (__pyx_t_37 < 0) __pyx_t_37 += __pyx_bshape_0_points; + if (__pyx_t_38 < 0) __pyx_t_38 += __pyx_bshape_1_points; + __pyx_v_y3 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_points.buf, __pyx_t_37, __pyx_bstride_0_points, __pyx_t_38, __pyx_bstride_1_points)); + + + __pyx_v_x1 -= __pyx_v_x3; + + + __pyx_v_x2 -= __pyx_v_x3; + + + __pyx_v_y1 -= __pyx_v_y3; + + + __pyx_v_y2 -= __pyx_v_y3; + + + __pyx_v_det = ((__pyx_v_x1 * __pyx_v_y2) - (__pyx_v_x2 * __pyx_v_y1)); + + + __pyx_t_14 = (__pyx_v_det == 0); + if (__pyx_t_14) { + + + __pyx_v_info = 1; + goto __pyx_L9; + } + { + + + __pyx_v_info = 0; + + + if (unlikely(__pyx_v_det == 0)) { + PyErr_Format(PyExc_ZeroDivisionError, "float division"); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 356; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_39 = __pyx_v_ivertex; + __pyx_t_40 = 0; + __pyx_t_41 = 0; + if (__pyx_t_39 < 0) __pyx_t_39 += __pyx_bshape_0_Tinvs; + if (__pyx_t_40 < 0) __pyx_t_40 += __pyx_bshape_1_Tinvs; + if (__pyx_t_41 < 0) __pyx_t_41 += __pyx_bshape_2_Tinvs; + *__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_39, __pyx_bstride_0_Tinvs, __pyx_t_40, __pyx_bstride_1_Tinvs, __pyx_t_41, __pyx_bstride_2_Tinvs) = (__pyx_v_y2 / __pyx_v_det); + + + __pyx_t_3 = (-__pyx_v_x2); + if (unlikely(__pyx_v_det == 0)) { + PyErr_Format(PyExc_ZeroDivisionError, "float division"); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 357; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_42 = __pyx_v_ivertex; + __pyx_t_43 = 0; + __pyx_t_44 = 1; + if (__pyx_t_42 < 0) __pyx_t_42 += __pyx_bshape_0_Tinvs; + if (__pyx_t_43 < 0) __pyx_t_43 += __pyx_bshape_1_Tinvs; + if (__pyx_t_44 < 0) __pyx_t_44 += __pyx_bshape_2_Tinvs; + *__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_42, __pyx_bstride_0_Tinvs, __pyx_t_43, __pyx_bstride_1_Tinvs, __pyx_t_44, __pyx_bstride_2_Tinvs) = (__pyx_t_3 / __pyx_v_det); + + + __pyx_t_3 = (-__pyx_v_y1); + if (unlikely(__pyx_v_det == 0)) { + PyErr_Format(PyExc_ZeroDivisionError, "float division"); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 358; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_45 = __pyx_v_ivertex; + __pyx_t_46 = 1; + __pyx_t_47 = 0; + if (__pyx_t_45 < 0) __pyx_t_45 += __pyx_bshape_0_Tinvs; + if (__pyx_t_46 < 0) __pyx_t_46 += __pyx_bshape_1_Tinvs; + if (__pyx_t_47 < 0) __pyx_t_47 += __pyx_bshape_2_Tinvs; + *__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_45, __pyx_bstride_0_Tinvs, __pyx_t_46, __pyx_bstride_1_Tinvs, __pyx_t_47, __pyx_bstride_2_Tinvs) = (__pyx_t_3 / __pyx_v_det); + + + if (unlikely(__pyx_v_det == 0)) { + PyErr_Format(PyExc_ZeroDivisionError, "float division"); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_48 = __pyx_v_ivertex; + __pyx_t_49 = 1; + __pyx_t_50 = 1; + if (__pyx_t_48 < 0) __pyx_t_48 += __pyx_bshape_0_Tinvs; + if (__pyx_t_49 < 0) __pyx_t_49 += __pyx_bshape_1_Tinvs; + if (__pyx_t_50 < 0) __pyx_t_50 += __pyx_bshape_2_Tinvs; + *__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_48, __pyx_bstride_0_Tinvs, __pyx_t_49, __pyx_bstride_1_Tinvs, __pyx_t_50, __pyx_bstride_2_Tinvs) = (__pyx_v_x1 / __pyx_v_det); + + + __pyx_t_51 = __pyx_v_ivertex; + __pyx_t_52 = 2; + __pyx_t_53 = 0; + if (__pyx_t_51 < 0) __pyx_t_51 += __pyx_bshape_0_Tinvs; + if (__pyx_t_52 < 0) __pyx_t_52 += __pyx_bshape_1_Tinvs; + if (__pyx_t_53 < 0) __pyx_t_53 += __pyx_bshape_2_Tinvs; + *__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_51, __pyx_bstride_0_Tinvs, __pyx_t_52, __pyx_bstride_1_Tinvs, __pyx_t_53, __pyx_bstride_2_Tinvs) = __pyx_v_x3; + + + __pyx_t_54 = __pyx_v_ivertex; + __pyx_t_55 = 2; + __pyx_t_56 = 1; + if (__pyx_t_54 < 0) __pyx_t_54 += __pyx_bshape_0_Tinvs; + if (__pyx_t_55 < 0) __pyx_t_55 += __pyx_bshape_1_Tinvs; + if (__pyx_t_56 < 0) __pyx_t_56 += __pyx_bshape_2_Tinvs; + *__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_54, __pyx_bstride_0_Tinvs, __pyx_t_55, __pyx_bstride_1_Tinvs, __pyx_t_56, __pyx_bstride_2_Tinvs) = __pyx_v_y3; + } + __pyx_L9:; + goto __pyx_L8; + } + { + + + __pyx_t_57 = __pyx_v_ndim; + for (__pyx_t_58 = 0; __pyx_t_58 < __pyx_t_57; __pyx_t_58+=1) { + __pyx_v_i = __pyx_t_58; + + + __pyx_t_59 = __pyx_v_ivertex; + __pyx_t_60 = __pyx_v_ndim; + if (__pyx_t_59 < 0) __pyx_t_59 += __pyx_bshape_0_vertices; + if (__pyx_t_60 < 0) __pyx_t_60 += __pyx_bshape_1_vertices; + __pyx_t_61 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_59, __pyx_bstride_0_vertices, __pyx_t_60, __pyx_bstride_1_vertices)); + __pyx_t_62 = __pyx_v_i; + if (__pyx_t_61 < 0) __pyx_t_61 += __pyx_bshape_0_points; + if (__pyx_t_62 < 0) __pyx_t_62 += __pyx_bshape_1_points; + __pyx_t_63 = __pyx_v_ivertex; + __pyx_t_64 = __pyx_v_ndim; + __pyx_t_65 = __pyx_v_i; + if (__pyx_t_63 < 0) __pyx_t_63 += __pyx_bshape_0_Tinvs; + if (__pyx_t_64 < 0) __pyx_t_64 += __pyx_bshape_1_Tinvs; + if (__pyx_t_65 < 0) __pyx_t_65 += __pyx_bshape_2_Tinvs; + *__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_63, __pyx_bstride_0_Tinvs, __pyx_t_64, __pyx_bstride_1_Tinvs, __pyx_t_65, __pyx_bstride_2_Tinvs) = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_points.buf, __pyx_t_61, __pyx_bstride_0_points, __pyx_t_62, __pyx_bstride_1_points)); + + + __pyx_t_66 = __pyx_v_ndim; + for (__pyx_t_67 = 0; __pyx_t_67 < __pyx_t_66; __pyx_t_67+=1) { + __pyx_v_j = __pyx_t_67; + + + __pyx_t_68 = __pyx_v_ivertex; + __pyx_t_69 = __pyx_v_j; + if (__pyx_t_68 < 0) __pyx_t_68 += __pyx_bshape_0_vertices; + if (__pyx_t_69 < 0) __pyx_t_69 += __pyx_bshape_1_vertices; + __pyx_t_70 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_68, __pyx_bstride_0_vertices, __pyx_t_69, __pyx_bstride_1_vertices)); + __pyx_t_71 = __pyx_v_i; + if (__pyx_t_70 < 0) __pyx_t_70 += __pyx_bshape_0_points; + if (__pyx_t_71 < 0) __pyx_t_71 += __pyx_bshape_1_points; + + + __pyx_t_72 = __pyx_v_ivertex; + __pyx_t_73 = __pyx_v_ndim; + __pyx_t_74 = __pyx_v_i; + if (__pyx_t_72 < 0) __pyx_t_72 += __pyx_bshape_0_Tinvs; + if (__pyx_t_73 < 0) __pyx_t_73 += __pyx_bshape_1_Tinvs; + if (__pyx_t_74 < 0) __pyx_t_74 += __pyx_bshape_2_Tinvs; + + + __pyx_t_75 = __pyx_v_i; + __pyx_t_76 = __pyx_v_j; + if (__pyx_t_75 < 0) __pyx_t_75 += __pyx_bshape_0_T; + if (__pyx_t_76 < 0) __pyx_t_76 += __pyx_bshape_1_T; + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_T.buf, __pyx_t_75, __pyx_bstride_0_T, __pyx_t_76, __pyx_bstride_1_T) = ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_points.buf, __pyx_t_70, __pyx_bstride_0_points, __pyx_t_71, __pyx_bstride_1_points)) - (*__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_72, __pyx_bstride_0_Tinvs, __pyx_t_73, __pyx_bstride_1_Tinvs, __pyx_t_74, __pyx_bstride_2_Tinvs))); + } + + + __pyx_t_66 = __pyx_v_ivertex; + __pyx_t_67 = __pyx_v_i; + __pyx_t_77 = __pyx_v_i; + if (__pyx_t_66 < 0) __pyx_t_66 += __pyx_bshape_0_Tinvs; + if (__pyx_t_67 < 0) __pyx_t_67 += __pyx_bshape_1_Tinvs; + if (__pyx_t_77 < 0) __pyx_t_77 += __pyx_bshape_2_Tinvs; + *__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_66, __pyx_bstride_0_Tinvs, __pyx_t_67, __pyx_bstride_1_Tinvs, __pyx_t_77, __pyx_bstride_2_Tinvs) = 1; + } + + + __pyx_v_n = __pyx_v_ndim; + + + __pyx_v_nrhs = __pyx_v_ndim; + + + __pyx_v_lda = __pyx_v_ndim; + + + __pyx_v_ldb = __pyx_v_ndim; + + + qh_dgesv((&__pyx_v_n), (&__pyx_v_nrhs), ((double *)__pyx_v_T->data), (&__pyx_v_lda), __pyx_v_ipiv, (((double *)__pyx_v_Tinvs->data) + ((__pyx_v_ndim * (__pyx_v_ndim + 1)) * __pyx_v_ivertex)), (&__pyx_v_ldb), (&__pyx_v_info)); + } + __pyx_L8:; + + + __pyx_t_14 = (__pyx_v_info != 0); + if (__pyx_t_14) { + + + __pyx_t_78 = (__pyx_v_ndim + 1); + for (__pyx_t_57 = 0; __pyx_t_57 < __pyx_t_78; __pyx_t_57+=1) { + __pyx_v_i = __pyx_t_57; + + + __pyx_t_58 = __pyx_v_ndim; + for (__pyx_t_79 = 0; __pyx_t_79 < __pyx_t_58; __pyx_t_79+=1) { + __pyx_v_j = __pyx_t_79; + + + __pyx_t_80 = __pyx_v_ivertex; + __pyx_t_81 = __pyx_v_i; + __pyx_t_82 = __pyx_v_j; + if (__pyx_t_80 < 0) __pyx_t_80 += __pyx_bshape_0_Tinvs; + if (__pyx_t_81 < 0) __pyx_t_81 += __pyx_bshape_1_Tinvs; + if (__pyx_t_82 < 0) __pyx_t_82 += __pyx_bshape_2_Tinvs; + *__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_Tinvs.buf, __pyx_t_80, __pyx_bstride_0_Tinvs, __pyx_t_81, __pyx_bstride_1_Tinvs, __pyx_t_82, __pyx_bstride_2_Tinvs) = __pyx_v_nan; + } + } + goto __pyx_L14; + } + __pyx_L14:; + } + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_Tinvs)); + __pyx_r = ((PyObject *)__pyx_v_Tinvs); + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_Tinvs); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_T); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("scipy.spatial.qhull._get_barycentric_transforms"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_Tinvs); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_T); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __pyx_L2:; + __Pyx_DECREF((PyObject *)__pyx_v_T); + __Pyx_DECREF((PyObject *)__pyx_v_Tinvs); + __Pyx_DECREF((PyObject *)__pyx_v_points); + __Pyx_DECREF((PyObject *)__pyx_v_vertices); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static int __pyx_f_5scipy_7spatial_5qhull__barycentric_inside(int __pyx_v_ndim, double *__pyx_v_transform, double *__pyx_v_x, double *__pyx_v_c, double __pyx_v_eps) { + int __pyx_v_i; + int __pyx_v_j; + int __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + double __pyx_t_5; + int __pyx_t_6; + int __pyx_t_7; + + + (__pyx_v_c[__pyx_v_ndim]) = 1.0; + + + __pyx_t_1 = __pyx_v_ndim; + for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) { + __pyx_v_i = __pyx_t_2; + + + (__pyx_v_c[__pyx_v_i]) = 0; + + + __pyx_t_3 = __pyx_v_ndim; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_j = __pyx_t_4; + + + (__pyx_v_c[__pyx_v_i]) += ((__pyx_v_transform[((__pyx_v_ndim * __pyx_v_i) + __pyx_v_j)]) * ((__pyx_v_x[__pyx_v_j]) - (__pyx_v_transform[((__pyx_v_ndim * __pyx_v_ndim) + __pyx_v_j)]))); + } + + + (__pyx_v_c[__pyx_v_ndim]) -= (__pyx_v_c[__pyx_v_i]); + + + __pyx_t_5 = (__pyx_v_c[__pyx_v_i]); + __pyx_t_6 = ((-__pyx_v_eps) <= __pyx_t_5); + if (__pyx_t_6) { + __pyx_t_6 = (__pyx_t_5 <= (1 + __pyx_v_eps)); + } + __pyx_t_7 = (!__pyx_t_6); + if (__pyx_t_7) { + + + __pyx_r = 0; + goto __pyx_L0; + goto __pyx_L7; + } + __pyx_L7:; + } + + + __pyx_t_5 = (__pyx_v_c[__pyx_v_ndim]); + __pyx_t_7 = ((-__pyx_v_eps) <= __pyx_t_5); + if (__pyx_t_7) { + __pyx_t_7 = (__pyx_t_5 <= (1 + __pyx_v_eps)); + } + __pyx_t_6 = (!__pyx_t_7); + if (__pyx_t_6) { + + + __pyx_r = 0; + goto __pyx_L0; + goto __pyx_L8; + } + __pyx_L8:; + + + __pyx_r = 1; + goto __pyx_L0; + + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + + + +static void __pyx_f_5scipy_7spatial_5qhull__barycentric_coordinate_single(int __pyx_v_ndim, double *__pyx_v_transform, double *__pyx_v_x, double *__pyx_v_c, int __pyx_v_i) { + int __pyx_v_j; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + + + __pyx_t_1 = (__pyx_v_i == __pyx_v_ndim); + if (__pyx_t_1) { + + + (__pyx_v_c[__pyx_v_ndim]) = 1.0; + + + __pyx_t_2 = __pyx_v_ndim; + for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { + __pyx_v_j = __pyx_t_3; + + + (__pyx_v_c[__pyx_v_ndim]) -= (__pyx_v_c[__pyx_v_j]); + } + goto __pyx_L3; + } + { + + + (__pyx_v_c[__pyx_v_i]) = 0; + + + __pyx_t_2 = __pyx_v_ndim; + for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { + __pyx_v_j = __pyx_t_3; + + + (__pyx_v_c[__pyx_v_i]) += ((__pyx_v_transform[((__pyx_v_ndim * __pyx_v_i) + __pyx_v_j)]) * ((__pyx_v_x[__pyx_v_j]) - (__pyx_v_transform[((__pyx_v_ndim * __pyx_v_ndim) + __pyx_v_j)]))); + } + } + __pyx_L3:; + +} + + + +static void __pyx_f_5scipy_7spatial_5qhull__barycentric_coordinates(int __pyx_v_ndim, double *__pyx_v_transform, double *__pyx_v_x, double *__pyx_v_c) { + int __pyx_v_i; + int __pyx_v_j; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + + + (__pyx_v_c[__pyx_v_ndim]) = 1.0; + + + __pyx_t_1 = __pyx_v_ndim; + for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) { + __pyx_v_i = __pyx_t_2; + + + (__pyx_v_c[__pyx_v_i]) = 0; + + + __pyx_t_3 = __pyx_v_ndim; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_j = __pyx_t_4; + + + (__pyx_v_c[__pyx_v_i]) += ((__pyx_v_transform[((__pyx_v_ndim * __pyx_v_i) + __pyx_v_j)]) * ((__pyx_v_x[__pyx_v_j]) - (__pyx_v_transform[((__pyx_v_ndim * __pyx_v_ndim) + __pyx_v_j)]))); + } + + + (__pyx_v_c[__pyx_v_ndim]) -= (__pyx_v_c[__pyx_v_i]); + } + +} + + + +static void __pyx_f_5scipy_7spatial_5qhull__lift_point(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, double *__pyx_v_x, double *__pyx_v_z) { + int __pyx_v_i; + int __pyx_t_1; + int __pyx_t_2; + + + (__pyx_v_z[__pyx_v_d->ndim]) = 0; + + + __pyx_t_1 = __pyx_v_d->ndim; + for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) { + __pyx_v_i = __pyx_t_2; + + + (__pyx_v_z[__pyx_v_i]) = (__pyx_v_x[__pyx_v_i]); + + + (__pyx_v_z[__pyx_v_d->ndim]) += pow((__pyx_v_x[__pyx_v_i]), 2); + } + + + (__pyx_v_z[__pyx_v_d->ndim]) *= __pyx_v_d->paraboloid_scale; + + + (__pyx_v_z[__pyx_v_d->ndim]) += __pyx_v_d->paraboloid_shift; + +} + + + +static double __pyx_f_5scipy_7spatial_5qhull__distplane(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, int __pyx_v_isimplex, double *__pyx_v_point) { + double __pyx_v_dist; + int __pyx_v_k; + double __pyx_r; + long __pyx_t_1; + int __pyx_t_2; + + + __pyx_v_dist = (__pyx_v_d->equations[(((__pyx_v_isimplex * (__pyx_v_d->ndim + 2)) + __pyx_v_d->ndim) + 1)]); + + + __pyx_t_1 = (__pyx_v_d->ndim + 1); + for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) { + __pyx_v_k = __pyx_t_2; + + + __pyx_v_dist += ((__pyx_v_d->equations[((__pyx_v_isimplex * (__pyx_v_d->ndim + 2)) + __pyx_v_k)]) * (__pyx_v_point[__pyx_v_k])); + } + + + __pyx_r = __pyx_v_dist; + goto __pyx_L0; + + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + + + +static void __pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_init(__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *__pyx_v_it, __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, int __pyx_v_vertex) { + int __pyx_v_k; + int __pyx_v_ivertex; + int __pyx_v_start; + int __pyx_t_1; + int __pyx_t_2; + + + __pyx_v_start = 0; + + + __pyx_v_it->info = __pyx_v_d; + + + __pyx_v_it->vertex = __pyx_v_vertex; + + + __pyx_v_it->triangle = (__pyx_v_d->vertex_to_simplex[__pyx_v_vertex]); + + + __pyx_v_it->start_triangle = __pyx_v_it->triangle; + + + __pyx_t_1 = (__pyx_v_it->triangle != -1); + if (__pyx_t_1) { + + + for (__pyx_t_2 = 0; __pyx_t_2 < 3; __pyx_t_2+=1) { + __pyx_v_k = __pyx_t_2; + + + __pyx_v_ivertex = (__pyx_v_it->info->vertices[((__pyx_v_it->triangle * 3) + __pyx_v_k)]); + + + __pyx_t_1 = (__pyx_v_ivertex != __pyx_v_vertex); + if (__pyx_t_1) { + + + __pyx_v_it->vertex2 = __pyx_v_ivertex; + + + __pyx_v_it->edge = __pyx_v_k; + + + __pyx_v_it->start_edge = __pyx_v_k; + + + goto __pyx_L5_break; + goto __pyx_L6; + } + __pyx_L6:; + } + __pyx_L5_break:; + goto __pyx_L3; + } + { + + + __pyx_v_it->start_edge = -1; + + + __pyx_v_it->edge = -1; + } + __pyx_L3:; + +} + + + +static void __pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_next(__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *__pyx_v_it) { + int __pyx_v_itri; + int __pyx_v_k; + int __pyx_v_ivertex; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + + + __pyx_v_itri = (__pyx_v_it->info->neighbors[((__pyx_v_it->triangle * 3) + __pyx_v_it->edge)]); + + + __pyx_t_1 = (__pyx_v_itri == -1); + if (__pyx_t_1) { + + + __pyx_t_1 = (__pyx_v_it->start_edge == -1); + if (__pyx_t_1) { + + + __pyx_v_it->edge = -1; + + + goto __pyx_L0; + goto __pyx_L4; + } + __pyx_L4:; + + + for (__pyx_t_2 = 0; __pyx_t_2 < 3; __pyx_t_2+=1) { + __pyx_v_k = __pyx_t_2; + + + __pyx_v_ivertex = (__pyx_v_it->info->vertices[((__pyx_v_it->triangle * 3) + __pyx_v_k)]); + + + __pyx_t_1 = (__pyx_v_ivertex != __pyx_v_it->vertex); + if (__pyx_t_1) { + __pyx_t_3 = (__pyx_v_k != __pyx_v_it->start_edge); + __pyx_t_4 = __pyx_t_3; + } else { + __pyx_t_4 = __pyx_t_1; + } + if (__pyx_t_4) { + + + __pyx_v_it->edge = __pyx_v_k; + + + __pyx_v_it->vertex2 = __pyx_v_ivertex; + + + goto __pyx_L6_break; + goto __pyx_L7; + } + __pyx_L7:; + } + __pyx_L6_break:; + + + __pyx_v_it->start_edge = -1; + + + goto __pyx_L0; + goto __pyx_L3; + } + __pyx_L3:; + + + for (__pyx_t_2 = 0; __pyx_t_2 < 3; __pyx_t_2+=1) { + __pyx_v_k = __pyx_t_2; + + + __pyx_v_ivertex = (__pyx_v_it->info->vertices[((__pyx_v_itri * 3) + __pyx_v_k)]); + + + __pyx_t_4 = ((__pyx_v_it->info->neighbors[((__pyx_v_itri * 3) + __pyx_v_k)]) != __pyx_v_it->triangle); + if (__pyx_t_4) { + + + __pyx_t_1 = (__pyx_v_ivertex != __pyx_v_it->vertex); + __pyx_t_3 = __pyx_t_1; + } else { + __pyx_t_3 = __pyx_t_4; + } + if (__pyx_t_3) { + + + __pyx_v_it->edge = __pyx_v_k; + + + __pyx_v_it->vertex2 = __pyx_v_ivertex; + + + goto __pyx_L9_break; + goto __pyx_L10; + } + __pyx_L10:; + } + __pyx_L9_break:; + + + __pyx_v_it->triangle = __pyx_v_itri; + + + __pyx_t_3 = (__pyx_v_it->triangle == __pyx_v_it->start_triangle); + if (__pyx_t_3) { + + + __pyx_v_it->edge = -1; + + + goto __pyx_L0; + goto __pyx_L11; + } + __pyx_L11:; + + __pyx_L0:; +} + + + +static int __pyx_f_5scipy_7spatial_5qhull__is_point_fully_outside(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, double *__pyx_v_x, double __pyx_v_eps) { + int __pyx_v_i; + int __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + + + __pyx_t_1 = __pyx_v_d->ndim; + for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) { + __pyx_v_i = __pyx_t_2; + + + __pyx_t_3 = ((__pyx_v_x[__pyx_v_i]) < ((__pyx_v_d->min_bound[__pyx_v_i]) - __pyx_v_eps)); + if (!__pyx_t_3) { + __pyx_t_4 = ((__pyx_v_x[__pyx_v_i]) > ((__pyx_v_d->max_bound[__pyx_v_i]) + __pyx_v_eps)); + __pyx_t_5 = __pyx_t_4; + } else { + __pyx_t_5 = __pyx_t_3; + } + if (__pyx_t_5) { + + + __pyx_r = 1; + goto __pyx_L0; + goto __pyx_L5; + } + __pyx_L5:; + } + + + __pyx_r = 0; + goto __pyx_L0; + + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + + + +static int __pyx_f_5scipy_7spatial_5qhull__find_simplex_bruteforce(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, double *__pyx_v_c, double *__pyx_v_x, double __pyx_v_eps) { + int __pyx_v_inside; + int __pyx_v_isimplex; + int __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + + + __pyx_t_1 = __pyx_f_5scipy_7spatial_5qhull__is_point_fully_outside(__pyx_v_d, __pyx_v_x, __pyx_v_eps); + if (__pyx_t_1) { + + + __pyx_r = -1; + goto __pyx_L0; + goto __pyx_L3; + } + __pyx_L3:; + + + __pyx_t_1 = __pyx_v_d->nsimplex; + for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) { + __pyx_v_isimplex = __pyx_t_2; + + + __pyx_v_inside = __pyx_f_5scipy_7spatial_5qhull__barycentric_inside(__pyx_v_d->ndim, (__pyx_v_d->transform + ((__pyx_v_isimplex * __pyx_v_d->ndim) * (__pyx_v_d->ndim + 1))), __pyx_v_x, __pyx_v_c, __pyx_v_eps); + + + __pyx_t_3 = __pyx_v_inside; + if (__pyx_t_3) { + + + __pyx_r = __pyx_v_isimplex; + goto __pyx_L0; + goto __pyx_L6; + } + __pyx_L6:; + } + + + __pyx_r = -1; + goto __pyx_L0; + + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + + + +static int __pyx_f_5scipy_7spatial_5qhull__find_simplex_directed(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, double *__pyx_v_c, double *__pyx_v_x, int *__pyx_v_start, double __pyx_v_eps) { + int __pyx_v_k; + int __pyx_v_m; + int __pyx_v_ndim; + int __pyx_v_inside; + int __pyx_v_isimplex; + double *__pyx_v_transform; + double __pyx_v_v; + int __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + long __pyx_t_4; + int __pyx_t_5; + + + __pyx_v_ndim = __pyx_v_d->ndim; + + + __pyx_v_isimplex = (__pyx_v_start[0]); + + + __pyx_t_1 = (__pyx_v_isimplex < 0); + if (!__pyx_t_1) { + __pyx_t_2 = (__pyx_v_isimplex >= __pyx_v_d->nsimplex); + __pyx_t_3 = __pyx_t_2; + } else { + __pyx_t_3 = __pyx_t_1; + } + if (__pyx_t_3) { + + + __pyx_v_isimplex = 0; + goto __pyx_L3; + } + __pyx_L3:; + + + while (1) { + __pyx_t_3 = (__pyx_v_isimplex != -1); + if (!__pyx_t_3) break; + + + __pyx_v_transform = (__pyx_v_d->transform + ((__pyx_v_isimplex * __pyx_v_ndim) * (__pyx_v_ndim + 1))); + + + __pyx_v_inside = 1; + + + __pyx_t_4 = (__pyx_v_ndim + 1); + for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { + __pyx_v_k = __pyx_t_5; + + + __pyx_f_5scipy_7spatial_5qhull__barycentric_coordinate_single(__pyx_v_ndim, __pyx_v_transform, __pyx_v_x, __pyx_v_c, __pyx_v_k); + + + __pyx_t_3 = ((__pyx_v_c[__pyx_v_k]) < (-__pyx_v_eps)); + if (__pyx_t_3) { + + + __pyx_v_m = (__pyx_v_d->neighbors[(((__pyx_v_ndim + 1) * __pyx_v_isimplex) + __pyx_v_k)]); + + + __pyx_t_3 = (__pyx_v_m == -1); + if (__pyx_t_3) { + + + (__pyx_v_start[0]) = __pyx_v_isimplex; + + + __pyx_r = -1; + goto __pyx_L0; + goto __pyx_L9; + } + __pyx_L9:; + + + __pyx_v_v = (__pyx_v_d->transform[((__pyx_v_m * __pyx_v_ndim) * (__pyx_v_ndim + 1))]); + + + __pyx_t_3 = (__pyx_v_v != __pyx_v_v); + if (__pyx_t_3) { + + + goto __pyx_L6_continue; + goto __pyx_L10; + } + { + + + __pyx_v_isimplex = __pyx_v_m; + + + __pyx_v_inside = -1; + + + goto __pyx_L7_break; + } + __pyx_L10:; + goto __pyx_L8; + } + + + __pyx_t_3 = ((__pyx_v_c[__pyx_v_k]) > (1 + __pyx_v_eps)); + if (__pyx_t_3) { + + + __pyx_v_inside = 0; + goto __pyx_L8; + } + __pyx_L8:; + __pyx_L6_continue:; + } + __pyx_L7_break:; + + + switch (__pyx_v_inside) { + case -1: + + + goto __pyx_L4_continue; + break; + + + case 1: + + + goto __pyx_L5_break; + break; + default: + + + __pyx_v_isimplex = __pyx_f_5scipy_7spatial_5qhull__find_simplex_bruteforce(__pyx_v_d, __pyx_v_c, __pyx_v_x, __pyx_v_eps); + + + goto __pyx_L5_break; + break; + } + __pyx_L4_continue:; + } + __pyx_L5_break:; + + + (__pyx_v_start[0]) = __pyx_v_isimplex; + + + __pyx_r = __pyx_v_isimplex; + goto __pyx_L0; + + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + + + +static int __pyx_f_5scipy_7spatial_5qhull__find_simplex(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, double *__pyx_v_c, double *__pyx_v_x, int *__pyx_v_start, double __pyx_v_eps) { + int __pyx_v_isimplex; + int __pyx_v_k; + int __pyx_v_ineigh; + int __pyx_v_ndim; + double __pyx_v_z[(NPY_MAXDIMS + 1)]; + double __pyx_v_best_dist; + double __pyx_v_dist; + int __pyx_v_changed; + int __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + long __pyx_t_5; + + + __pyx_t_1 = __pyx_f_5scipy_7spatial_5qhull__is_point_fully_outside(__pyx_v_d, __pyx_v_x, __pyx_v_eps); + if (__pyx_t_1) { + + + __pyx_r = -1; + goto __pyx_L0; + goto __pyx_L3; + } + __pyx_L3:; + + + __pyx_t_2 = (__pyx_v_d->nsimplex <= 0); + if (__pyx_t_2) { + + + __pyx_r = -1; + goto __pyx_L0; + goto __pyx_L4; + } + __pyx_L4:; + + + __pyx_v_ndim = __pyx_v_d->ndim; + + + __pyx_v_isimplex = (__pyx_v_start[0]); + + + __pyx_t_2 = (__pyx_v_isimplex < 0); + if (!__pyx_t_2) { + __pyx_t_3 = (__pyx_v_isimplex >= __pyx_v_d->nsimplex); + __pyx_t_4 = __pyx_t_3; + } else { + __pyx_t_4 = __pyx_t_2; + } + if (__pyx_t_4) { + + + __pyx_v_isimplex = 0; + goto __pyx_L5; + } + __pyx_L5:; + + + __pyx_f_5scipy_7spatial_5qhull__lift_point(__pyx_v_d, __pyx_v_x, __pyx_v_z); + + + __pyx_v_best_dist = __pyx_f_5scipy_7spatial_5qhull__distplane(__pyx_v_d, __pyx_v_isimplex, __pyx_v_z); + + + __pyx_v_changed = 1; + + + while (1) { + __pyx_t_1 = __pyx_v_changed; + if (!__pyx_t_1) break; + + + __pyx_t_4 = (__pyx_v_best_dist > 0); + if (__pyx_t_4) { + + + goto __pyx_L7_break; + goto __pyx_L8; + } + __pyx_L8:; + + + __pyx_v_changed = 0; + + + __pyx_t_5 = (__pyx_v_ndim + 1); + for (__pyx_t_1 = 0; __pyx_t_1 < __pyx_t_5; __pyx_t_1+=1) { + __pyx_v_k = __pyx_t_1; + + + __pyx_v_ineigh = (__pyx_v_d->neighbors[(((__pyx_v_ndim + 1) * __pyx_v_isimplex) + __pyx_v_k)]); + + + __pyx_t_4 = (__pyx_v_ineigh == -1); + if (__pyx_t_4) { + + + goto __pyx_L9_continue; + goto __pyx_L11; + } + __pyx_L11:; + + + __pyx_v_dist = __pyx_f_5scipy_7spatial_5qhull__distplane(__pyx_v_d, __pyx_v_ineigh, __pyx_v_z); + + + __pyx_t_4 = (__pyx_v_dist > __pyx_v_best_dist); + if (__pyx_t_4) { + + + __pyx_v_isimplex = __pyx_v_ineigh; + + + __pyx_v_best_dist = __pyx_v_dist; + + + __pyx_v_changed = 1; + goto __pyx_L12; + } + __pyx_L12:; + __pyx_L9_continue:; + } + } + __pyx_L7_break:; + + + (__pyx_v_start[0]) = __pyx_v_isimplex; + + + __pyx_r = __pyx_f_5scipy_7spatial_5qhull__find_simplex_directed(__pyx_v_d, __pyx_v_c, __pyx_v_x, __pyx_v_start, __pyx_v_eps); + goto __pyx_L0; + + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static PyMethodDef __pyx_mdef_5scipy_7spatial_5qhull_8Delaunay___init__ = {__Pyx_NAMESTR("__init__"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull_8Delaunay___init__, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)}; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_points = 0; + PyObject *__pyx_v_vertices; + PyObject *__pyx_v_neighbors; + PyObject *__pyx_v_equations; + PyObject *__pyx_v_paraboloid_scale; + PyObject *__pyx_v_paraboloid_shift; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__points,0}; + __Pyx_RefNannySetupContext("__init__"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__points); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 863; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 863; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_points = values[1]; + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_points = PyTuple_GET_ITEM(__pyx_args, 1); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 863; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.__init__"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_v_vertices = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_neighbors = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_equations = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_paraboloid_scale = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_paraboloid_shift = Py_None; __Pyx_INCREF(Py_None); + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s___construct_delaunay); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 865; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 865; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 865; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyTuple_CheckExact(__pyx_t_3) && likely(PyTuple_GET_SIZE(__pyx_t_3) == 5)) { + PyObject* tuple = __pyx_t_3; + __pyx_t_2 = PyTuple_GET_ITEM(tuple, 0); __Pyx_INCREF(__pyx_t_2); + __pyx_t_1 = PyTuple_GET_ITEM(tuple, 1); __Pyx_INCREF(__pyx_t_1); + __pyx_t_4 = PyTuple_GET_ITEM(tuple, 2); __Pyx_INCREF(__pyx_t_4); + __pyx_t_5 = PyTuple_GET_ITEM(tuple, 3); __Pyx_INCREF(__pyx_t_5); + __pyx_t_6 = PyTuple_GET_ITEM(tuple, 4); __Pyx_INCREF(__pyx_t_6); + + + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_vertices); + __pyx_v_vertices = __pyx_t_2; + __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_neighbors); + __pyx_v_neighbors = __pyx_t_1; + __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_equations); + __pyx_v_equations = __pyx_t_4; + __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_v_paraboloid_scale); + __pyx_v_paraboloid_scale = __pyx_t_5; + __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_v_paraboloid_shift); + __pyx_v_paraboloid_shift = __pyx_t_6; + __pyx_t_6 = 0; + } else { + __pyx_t_7 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 864; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_2 = __Pyx_UnpackItem(__pyx_t_7, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 864; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_UnpackItem(__pyx_t_7, 1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 864; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = __Pyx_UnpackItem(__pyx_t_7, 2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 864; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_UnpackItem(__pyx_t_7, 3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 864; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = __Pyx_UnpackItem(__pyx_t_7, 4); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 864; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + if (__Pyx_EndUnpack(__pyx_t_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 864; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_v_vertices); + __pyx_v_vertices = __pyx_t_2; + __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_neighbors); + __pyx_v_neighbors = __pyx_t_1; + __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_equations); + __pyx_v_equations = __pyx_t_4; + __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_v_paraboloid_scale); + __pyx_v_paraboloid_scale = __pyx_t_5; + __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_v_paraboloid_shift); + __pyx_v_paraboloid_shift = __pyx_t_6; + __pyx_t_6 = 0; + } + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_points, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 867; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_3, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_6) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 867; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__ndim, __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 867; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + + __pyx_t_6 = PyObject_GetAttr(__pyx_v_points, __pyx_n_s__shape); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 868; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_6, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 868; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__npoints, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 868; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_vertices, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_3, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_6) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__nsimplex, __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 869; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__points, __pyx_v_points) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 870; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__vertices, __pyx_v_vertices) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 871; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__neighbors, __pyx_v_neighbors) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 872; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__equations, __pyx_v_equations) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 873; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__paraboloid_scale, __pyx_v_paraboloid_scale) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 874; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__paraboloid_shift, __pyx_v_paraboloid_shift) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 875; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + __pyx_t_6 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__points); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 876; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__min); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 876; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 876; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_6)); + if (PyDict_SetItem(__pyx_t_6, ((PyObject *)__pyx_n_s__axis), __pyx_int_0) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 876; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 876; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__min_bound, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 876; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + + __pyx_t_5 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__points); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 877; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__max); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 877; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 877; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_5)); + if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__axis), __pyx_int_0) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 877; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyEval_CallObjectWithKeywords(__pyx_t_6, ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 877; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__max_bound, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 877; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s___transform, Py_None) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 878; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s___vertex_to_simplex, Py_None) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 879; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.__init__"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF(__pyx_v_vertices); + __Pyx_DECREF(__pyx_v_neighbors); + __Pyx_DECREF(__pyx_v_equations); + __Pyx_DECREF(__pyx_v_paraboloid_scale); + __Pyx_DECREF(__pyx_v_paraboloid_shift); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_transform(PyObject *__pyx_self, PyObject *__pyx_v_self); +static char __pyx_doc_5scipy_7spatial_5qhull_8Delaunay_transform[] = "\n Affine transform from ``x`` to the barycentric coordinates ``c``.\n\n :type: ndarray of double, shape (nsimplex, ndim+1, ndim)\n\n This is defined by::\n\n T c = x - r\n\n At vertex ``j``, ``c_j = 1`` and the other coordinates zero.\n\n For simplex ``i``, ``transform[i,:ndim,:ndim]`` contains\n inverse of the matrix ``T``, and ``transform[i,ndim,:]``\n contains the vector ``r``.\n\n "; +static PyMethodDef __pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_transform = {__Pyx_NAMESTR("transform"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_transform, METH_O, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull_8Delaunay_transform)}; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_transform(PyObject *__pyx_self, PyObject *__pyx_v_self) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + __Pyx_RefNannySetupContext("transform"); + __pyx_self = __pyx_self; + __Pyx_INCREF(__pyx_v_self); + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___transform); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 899; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__pyx_t_1 == Py_None); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_2) { + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s_8); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 900; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__points); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 900; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + + + __pyx_t_4 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__vertices); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 901; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 900; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_3 = 0; + __pyx_t_4 = 0; + __pyx_t_4 = PyObject_Call(__pyx_t_1, __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 900; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s___transform, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 900; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + goto __pyx_L5; + } + __pyx_L5:; + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___transform); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 902; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.transform"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF(__pyx_v_self); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_vertex_to_simplex(PyObject *__pyx_self, PyObject *__pyx_v_self); +static char __pyx_doc_5scipy_7spatial_5qhull_8Delaunay_vertex_to_simplex[] = "\n Lookup array, from a vertex, to some simplex which it is a part of.\n\n :type: ndarray of int, shape (npoints,)\n "; +static PyMethodDef __pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_vertex_to_simplex = {__Pyx_NAMESTR("vertex_to_simplex"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_vertex_to_simplex, METH_O, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull_8Delaunay_vertex_to_simplex)}; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_vertex_to_simplex(PyObject *__pyx_self, PyObject *__pyx_v_self) { + int __pyx_v_isimplex; + int __pyx_v_k; + int __pyx_v_ivertex; + int __pyx_v_nsimplex; + int __pyx_v_ndim; + PyArrayObject *__pyx_v_vertices; + PyArrayObject *__pyx_v_arr; + Py_buffer __pyx_bstruct_arr; + Py_ssize_t __pyx_bstride_0_arr = 0; + Py_ssize_t __pyx_bshape_0_arr = 0; + Py_buffer __pyx_bstruct_vertices; + Py_ssize_t __pyx_bstride_0_vertices = 0; + Py_ssize_t __pyx_bstride_1_vertices = 0; + Py_ssize_t __pyx_bshape_0_vertices = 0; + Py_ssize_t __pyx_bshape_1_vertices = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyArrayObject *__pyx_t_11 = NULL; + int __pyx_t_12; + long __pyx_t_13; + int __pyx_t_14; + int __pyx_t_15; + int __pyx_t_16; + int __pyx_t_17; + int __pyx_t_18; + int __pyx_t_19; + __Pyx_RefNannySetupContext("vertex_to_simplex"); + __pyx_self = __pyx_self; + __Pyx_INCREF(__pyx_v_self); + __pyx_v_vertices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_arr = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_bstruct_vertices.buf = NULL; + __pyx_bstruct_arr.buf = NULL; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___vertex_to_simplex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 915; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = (__pyx_t_1 == Py_None); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_2) { + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__npoints); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_4)); + if (PyDict_SetItem(__pyx_t_4, ((PyObject *)__pyx_n_s__dtype), ((PyObject *)((PyObject*)&PyInt_Type))) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_3, __pyx_t_1, ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s___vertex_to_simplex, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 916; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + + __pyx_t_5 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___vertex_to_simplex); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 917; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__fill); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 917; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 917; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_int_neg_1); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_int_neg_1); + __Pyx_GIVEREF(__pyx_int_neg_1); + __pyx_t_1 = PyObject_Call(__pyx_t_4, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 917; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___vertex_to_simplex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_arr); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_v_arr, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_8, __pyx_t_9, __pyx_t_10); + } + } + __pyx_bstride_0_arr = __pyx_bstruct_arr.strides[0]; + __pyx_bshape_0_arr = __pyx_bstruct_arr.shape[0]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 919; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_6 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_arr)); + __pyx_v_arr = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__vertices); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_11 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_10, &__pyx_t_9, &__pyx_t_8); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_v_vertices, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_8); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_10, __pyx_t_9, __pyx_t_8); + } + } + __pyx_bstride_0_vertices = __pyx_bstruct_vertices.strides[0]; __pyx_bstride_1_vertices = __pyx_bstruct_vertices.strides[1]; + __pyx_bshape_0_vertices = __pyx_bstruct_vertices.shape[0]; __pyx_bshape_1_vertices = __pyx_bstruct_vertices.shape[1]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 920; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_11 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_vertices)); + __pyx_v_vertices = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__nsimplex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 922; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 922; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_nsimplex = __pyx_t_7; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__ndim); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 923; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 923; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_ndim = __pyx_t_7; + + + __pyx_t_7 = __pyx_v_nsimplex; + for (__pyx_t_12 = 0; __pyx_t_12 < __pyx_t_7; __pyx_t_12+=1) { + __pyx_v_isimplex = __pyx_t_12; + + + __pyx_t_13 = (__pyx_v_ndim + 1); + for (__pyx_t_14 = 0; __pyx_t_14 < __pyx_t_13; __pyx_t_14+=1) { + __pyx_v_k = __pyx_t_14; + + + __pyx_t_15 = __pyx_v_isimplex; + __pyx_t_16 = __pyx_v_k; + __pyx_t_17 = -1; + if (__pyx_t_15 < 0) { + __pyx_t_15 += __pyx_bshape_0_vertices; + if (unlikely(__pyx_t_15 < 0)) __pyx_t_17 = 0; + } else if (unlikely(__pyx_t_15 >= __pyx_bshape_0_vertices)) __pyx_t_17 = 0; + if (__pyx_t_16 < 0) { + __pyx_t_16 += __pyx_bshape_1_vertices; + if (unlikely(__pyx_t_16 < 0)) __pyx_t_17 = 1; + } else if (unlikely(__pyx_t_16 >= __pyx_bshape_1_vertices)) __pyx_t_17 = 1; + if (unlikely(__pyx_t_17 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_17); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 927; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_v_ivertex = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_15, __pyx_bstride_0_vertices, __pyx_t_16, __pyx_bstride_1_vertices)); + + + __pyx_t_17 = __pyx_v_ivertex; + __pyx_t_18 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_bshape_0_arr; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_18 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_bshape_0_arr)) __pyx_t_18 = 0; + if (unlikely(__pyx_t_18 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_18); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 928; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_2 = ((*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_bstruct_arr.buf, __pyx_t_17, __pyx_bstride_0_arr)) == -1); + if (__pyx_t_2) { + + + __pyx_t_18 = __pyx_v_ivertex; + __pyx_t_19 = -1; + if (__pyx_t_18 < 0) { + __pyx_t_18 += __pyx_bshape_0_arr; + if (unlikely(__pyx_t_18 < 0)) __pyx_t_19 = 0; + } else if (unlikely(__pyx_t_18 >= __pyx_bshape_0_arr)) __pyx_t_19 = 0; + if (unlikely(__pyx_t_19 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_19); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 929; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_bstruct_arr.buf, __pyx_t_18, __pyx_bstride_0_arr) = __pyx_v_isimplex; + goto __pyx_L10; + } + __pyx_L10:; + } + } + goto __pyx_L5; + } + __pyx_L5:; + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___vertex_to_simplex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_arr); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.vertex_to_simplex"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_arr); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __pyx_L2:; + __Pyx_DECREF((PyObject *)__pyx_v_vertices); + __Pyx_DECREF((PyObject *)__pyx_v_arr); + __Pyx_DECREF(__pyx_v_self); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_convex_hull(PyObject *__pyx_self, PyObject *__pyx_v_self); +static char __pyx_doc_5scipy_7spatial_5qhull_8Delaunay_convex_hull[] = "\n Vertices of facets forming the convex hull of the point set.\n\n :type: ndarray of int, shape (nfaces, ndim)\n\n The array contains the indices of the points\n belonging to the (N-1)-dimensional facets that form the convex\n hull of the triangulation.\n\n "; +static PyMethodDef __pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_convex_hull = {__Pyx_NAMESTR("convex_hull"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_convex_hull, METH_O, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull_8Delaunay_convex_hull)}; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_convex_hull(PyObject *__pyx_self, PyObject *__pyx_v_self) { + int __pyx_v_isimplex; + int __pyx_v_k; + int __pyx_v_j; + int __pyx_v_ndim; + int __pyx_v_nsimplex; + int __pyx_v_m; + int __pyx_v_msize; + PyArrayObject *__pyx_v_arr; + PyArrayObject *__pyx_v_neighbors; + PyArrayObject *__pyx_v_vertices; + PyObject *__pyx_v_out; + Py_buffer __pyx_bstruct_neighbors; + Py_ssize_t __pyx_bstride_0_neighbors = 0; + Py_ssize_t __pyx_bstride_1_neighbors = 0; + Py_ssize_t __pyx_bshape_0_neighbors = 0; + Py_ssize_t __pyx_bshape_1_neighbors = 0; + Py_buffer __pyx_bstruct_arr; + Py_ssize_t __pyx_bstride_0_arr = 0; + Py_ssize_t __pyx_bstride_1_arr = 0; + Py_ssize_t __pyx_bshape_0_arr = 0; + Py_ssize_t __pyx_bshape_1_arr = 0; + Py_buffer __pyx_bstruct_vertices; + Py_ssize_t __pyx_bstride_0_vertices = 0; + Py_ssize_t __pyx_bstride_1_vertices = 0; + Py_ssize_t __pyx_bshape_0_vertices = 0; + Py_ssize_t __pyx_bshape_1_vertices = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyArrayObject *__pyx_t_2 = NULL; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyArrayObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyArrayObject *__pyx_t_11 = NULL; + int __pyx_t_12; + long __pyx_t_13; + int __pyx_t_14; + int __pyx_t_15; + int __pyx_t_16; + int __pyx_t_17; + long __pyx_t_18; + int __pyx_t_19; + int __pyx_t_20; + int __pyx_t_21; + int __pyx_t_22; + int __pyx_t_23; + int __pyx_t_24; + int __pyx_t_25; + int __pyx_t_26; + long __pyx_t_27; + __Pyx_RefNannySetupContext("convex_hull"); + __pyx_self = __pyx_self; + __Pyx_INCREF(__pyx_v_self); + __pyx_v_arr = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_neighbors = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_vertices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_out = Py_None; __Pyx_INCREF(Py_None); + __pyx_bstruct_arr.buf = NULL; + __pyx_bstruct_neighbors.buf = NULL; + __pyx_bstruct_vertices.buf = NULL; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__neighbors); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 951; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 951; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_neighbors); + __pyx_t_3 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_neighbors, (PyObject*)__pyx_t_2, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_3 < 0)) { + PyErr_Fetch(&__pyx_t_4, &__pyx_t_5, &__pyx_t_6); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_neighbors, (PyObject*)__pyx_v_neighbors, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_4); Py_XDECREF(__pyx_t_5); Py_XDECREF(__pyx_t_6); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_4, __pyx_t_5, __pyx_t_6); + } + } + __pyx_bstride_0_neighbors = __pyx_bstruct_neighbors.strides[0]; __pyx_bstride_1_neighbors = __pyx_bstruct_neighbors.strides[1]; + __pyx_bshape_0_neighbors = __pyx_bstruct_neighbors.shape[0]; __pyx_bshape_1_neighbors = __pyx_bstruct_neighbors.shape[1]; + if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 951; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_2 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_neighbors)); + __pyx_v_neighbors = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__vertices); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 952; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 952; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_7 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __pyx_t_3 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_3 < 0)) { + PyErr_Fetch(&__pyx_t_6, &__pyx_t_5, &__pyx_t_4); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_v_vertices, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_6); Py_XDECREF(__pyx_t_5); Py_XDECREF(__pyx_t_4); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_6, __pyx_t_5, __pyx_t_4); + } + } + __pyx_bstride_0_vertices = __pyx_bstruct_vertices.strides[0]; __pyx_bstride_1_vertices = __pyx_bstruct_vertices.strides[1]; + __pyx_bshape_0_vertices = __pyx_bstruct_vertices.shape[0]; __pyx_bshape_1_vertices = __pyx_bstruct_vertices.shape[1]; + if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 952; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_7 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_vertices)); + __pyx_v_vertices = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__ndim); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 953; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 953; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_ndim = __pyx_t_3; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__nsimplex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 954; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 954; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_nsimplex = __pyx_t_3; + + + __pyx_v_msize = 10; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 957; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__empty); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 957; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(__pyx_v_msize); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 957; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_9 = PyInt_FromLong(__pyx_v_ndim); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 957; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_10 = PyTuple_New(2); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 957; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_9); + __Pyx_GIVEREF(__pyx_t_9); + __pyx_t_1 = 0; + __pyx_t_9 = 0; + __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 957; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_10); + __Pyx_GIVEREF(__pyx_t_10); + __pyx_t_10 = 0; + __pyx_t_10 = PyDict_New(); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 957; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_10)); + if (PyDict_SetItem(__pyx_t_10, ((PyObject *)__pyx_n_s__dtype), ((PyObject *)((PyObject*)&PyInt_Type))) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 957; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyEval_CallObjectWithKeywords(__pyx_t_8, __pyx_t_9, ((PyObject *)__pyx_t_10)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 957; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0; + __Pyx_DECREF(__pyx_v_out); + __pyx_v_out = __pyx_t_1; + __pyx_t_1 = 0; + + + if (!(likely(((__pyx_v_out) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_out, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 958; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_11 = ((PyArrayObject *)__pyx_v_out); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_arr); + __pyx_t_3 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_3 < 0)) { + PyErr_Fetch(&__pyx_t_4, &__pyx_t_5, &__pyx_t_6); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_v_arr, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_4); Py_XDECREF(__pyx_t_5); Py_XDECREF(__pyx_t_6); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_4, __pyx_t_5, __pyx_t_6); + } + } + __pyx_bstride_0_arr = __pyx_bstruct_arr.strides[0]; __pyx_bstride_1_arr = __pyx_bstruct_arr.strides[1]; + __pyx_bshape_0_arr = __pyx_bstruct_arr.shape[0]; __pyx_bshape_1_arr = __pyx_bstruct_arr.shape[1]; + if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 958; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_11 = 0; + __Pyx_INCREF(__pyx_v_out); + __Pyx_DECREF(((PyObject *)__pyx_v_arr)); + __pyx_v_arr = ((PyArrayObject *)__pyx_v_out); + + + __pyx_v_m = 0; + + + __pyx_t_3 = __pyx_v_nsimplex; + for (__pyx_t_12 = 0; __pyx_t_12 < __pyx_t_3; __pyx_t_12+=1) { + __pyx_v_isimplex = __pyx_t_12; + + + __pyx_t_13 = (__pyx_v_ndim + 1); + for (__pyx_t_14 = 0; __pyx_t_14 < __pyx_t_13; __pyx_t_14+=1) { + __pyx_v_k = __pyx_t_14; + + + __pyx_t_15 = __pyx_v_isimplex; + __pyx_t_16 = __pyx_v_k; + if (__pyx_t_15 < 0) __pyx_t_15 += __pyx_bshape_0_neighbors; + if (__pyx_t_16 < 0) __pyx_t_16 += __pyx_bshape_1_neighbors; + __pyx_t_17 = ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_neighbors.buf, __pyx_t_15, __pyx_bstride_0_neighbors, __pyx_t_16, __pyx_bstride_1_neighbors)) == -1); + if (__pyx_t_17) { + + + __pyx_t_18 = (__pyx_v_ndim + 1); + for (__pyx_t_19 = 0; __pyx_t_19 < __pyx_t_18; __pyx_t_19+=1) { + __pyx_v_j = __pyx_t_19; + + + __pyx_t_17 = (__pyx_v_j < __pyx_v_k); + if (__pyx_t_17) { + + + __pyx_t_20 = __pyx_v_isimplex; + __pyx_t_21 = __pyx_v_j; + if (__pyx_t_20 < 0) __pyx_t_20 += __pyx_bshape_0_vertices; + if (__pyx_t_21 < 0) __pyx_t_21 += __pyx_bshape_1_vertices; + __pyx_t_22 = __pyx_v_m; + __pyx_t_23 = __pyx_v_j; + if (__pyx_t_22 < 0) __pyx_t_22 += __pyx_bshape_0_arr; + if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_bshape_1_arr; + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_arr.buf, __pyx_t_22, __pyx_bstride_0_arr, __pyx_t_23, __pyx_bstride_1_arr) = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_20, __pyx_bstride_0_vertices, __pyx_t_21, __pyx_bstride_1_vertices)); + goto __pyx_L12; + } + + + __pyx_t_17 = (__pyx_v_j > __pyx_v_k); + if (__pyx_t_17) { + + + __pyx_t_24 = __pyx_v_isimplex; + __pyx_t_25 = __pyx_v_j; + if (__pyx_t_24 < 0) __pyx_t_24 += __pyx_bshape_0_vertices; + if (__pyx_t_25 < 0) __pyx_t_25 += __pyx_bshape_1_vertices; + __pyx_t_26 = __pyx_v_m; + __pyx_t_27 = (__pyx_v_j - 1); + if (__pyx_t_26 < 0) __pyx_t_26 += __pyx_bshape_0_arr; + if (__pyx_t_27 < 0) __pyx_t_27 += __pyx_bshape_1_arr; + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_arr.buf, __pyx_t_26, __pyx_bstride_0_arr, __pyx_t_27, __pyx_bstride_1_arr) = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_24, __pyx_bstride_0_vertices, __pyx_t_25, __pyx_bstride_1_vertices)); + goto __pyx_L12; + } + __pyx_L12:; + } + + + __pyx_v_m += 1; + + + __pyx_t_17 = (__pyx_v_m >= __pyx_v_msize); + if (__pyx_t_17) { + + + __pyx_t_11 = ((PyArrayObject *)Py_None); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_arr); + __pyx_t_19 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_19 < 0)) { + PyErr_Fetch(&__pyx_t_6, &__pyx_t_5, &__pyx_t_4); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_v_arr, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_6); Py_XDECREF(__pyx_t_5); Py_XDECREF(__pyx_t_4); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_6, __pyx_t_5, __pyx_t_4); + } + } + __pyx_bstride_0_arr = __pyx_bstruct_arr.strides[0]; __pyx_bstride_1_arr = __pyx_bstruct_arr.strides[1]; + __pyx_bshape_0_arr = __pyx_bstruct_arr.shape[0]; __pyx_bshape_1_arr = __pyx_bstruct_arr.shape[1]; + if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 972; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_11 = 0; + __Pyx_INCREF(Py_None); + __Pyx_DECREF(((PyObject *)__pyx_v_arr)); + __pyx_v_arr = ((PyArrayObject *)Py_None); + + + __pyx_v_msize = ((2 * __pyx_v_msize) + 1); + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_out, __pyx_n_s__resize); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 974; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_10 = PyInt_FromLong(__pyx_v_msize); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 974; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_9 = PyInt_FromLong(__pyx_v_ndim); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 974; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 974; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_10); + __Pyx_GIVEREF(__pyx_t_10); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_9); + __Pyx_GIVEREF(__pyx_t_9); + __pyx_t_10 = 0; + __pyx_t_9 = 0; + __pyx_t_9 = PyObject_Call(__pyx_t_1, __pyx_t_8, NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 974; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + + + if (!(likely(((__pyx_v_out) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_out, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 975; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_11 = ((PyArrayObject *)__pyx_v_out); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_arr); + __pyx_t_19 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_19 < 0)) { + PyErr_Fetch(&__pyx_t_4, &__pyx_t_5, &__pyx_t_6); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_v_arr, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_4); Py_XDECREF(__pyx_t_5); Py_XDECREF(__pyx_t_6); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_4, __pyx_t_5, __pyx_t_6); + } + } + __pyx_bstride_0_arr = __pyx_bstruct_arr.strides[0]; __pyx_bstride_1_arr = __pyx_bstruct_arr.strides[1]; + __pyx_bshape_0_arr = __pyx_bstruct_arr.shape[0]; __pyx_bshape_1_arr = __pyx_bstruct_arr.shape[1]; + if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 975; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_11 = 0; + __Pyx_INCREF(__pyx_v_out); + __Pyx_DECREF(((PyObject *)__pyx_v_arr)); + __pyx_v_arr = ((PyArrayObject *)__pyx_v_out); + goto __pyx_L13; + } + __pyx_L13:; + goto __pyx_L9; + } + __pyx_L9:; + } + } + + + __pyx_t_11 = ((PyArrayObject *)Py_None); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_arr); + __pyx_t_3 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_3 < 0)) { + PyErr_Fetch(&__pyx_t_6, &__pyx_t_5, &__pyx_t_4); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_arr, (PyObject*)__pyx_v_arr, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_6); Py_XDECREF(__pyx_t_5); Py_XDECREF(__pyx_t_4); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_6, __pyx_t_5, __pyx_t_4); + } + } + __pyx_bstride_0_arr = __pyx_bstruct_arr.strides[0]; __pyx_bstride_1_arr = __pyx_bstruct_arr.strides[1]; + __pyx_bshape_0_arr = __pyx_bstruct_arr.shape[0]; __pyx_bshape_1_arr = __pyx_bstruct_arr.shape[1]; + if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 977; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_11 = 0; + __Pyx_INCREF(Py_None); + __Pyx_DECREF(((PyObject *)__pyx_v_arr)); + __pyx_v_arr = ((PyArrayObject *)Py_None); + + + __pyx_t_9 = PyObject_GetAttr(__pyx_v_out, __pyx_n_s__resize); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 978; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = PyInt_FromLong(__pyx_v_m); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 978; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = PyInt_FromLong(__pyx_v_ndim); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 978; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_10 = PyTuple_New(2); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 978; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_8 = 0; + __pyx_t_1 = 0; + __pyx_t_1 = PyObject_Call(__pyx_t_9, __pyx_t_10, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 978; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_out); + __pyx_r = __pyx_v_out; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_neighbors); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_arr); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.convex_hull"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_neighbors); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_arr); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __pyx_L2:; + __Pyx_DECREF((PyObject *)__pyx_v_arr); + __Pyx_DECREF((PyObject *)__pyx_v_neighbors); + __Pyx_DECREF((PyObject *)__pyx_v_vertices); + __Pyx_DECREF(__pyx_v_out); + __Pyx_DECREF(__pyx_v_self); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_find_simplex(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static char __pyx_doc_5scipy_7spatial_5qhull_8Delaunay_find_simplex[] = "\n find_simplex(xi, bruteforce=False)\n\n Find the simplices containing the given points.\n\n Parameters\n ----------\n tri : DelaunayInfo\n Delaunay triangulation\n xi : ndarray of double, shape (..., ndim)\n Points to locate\n bruteforce : bool, optional\n Whether to only perform a brute-force search\n\n Returns\n -------\n i : ndarray of int, same shape as `xi`\n Indices of simplices containing each point.\n Points outside the triangulation get the value -1.\n\n Notes\n -----\n This uses an algorithm adapted from Qhull's qh_findbestfacet,\n which makes use of the connection between a convex hull and a\n Delaunay triangulation. After finding the simplex closest to\n the point in N+1 dimensions, the algorithm falls back to\n directed search in N dimensions.\n\n "; +static PyMethodDef __pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_find_simplex = {__Pyx_NAMESTR("find_simplex"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_find_simplex, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull_8Delaunay_find_simplex)}; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_find_simplex(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_xi = 0; + PyObject *__pyx_v_bruteforce = 0; + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_info; + int __pyx_v_isimplex; + double __pyx_v_c[NPY_MAXDIMS]; + double __pyx_v_eps; + int __pyx_v_start; + int __pyx_v_k; + PyArrayObject *__pyx_v_x; + PyArrayObject *__pyx_v_out_; + PyObject *__pyx_v_xi_shape; + PyObject *__pyx_v_out; + Py_buffer __pyx_bstruct_out_; + Py_ssize_t __pyx_bstride_0_out_ = 0; + Py_ssize_t __pyx_bshape_0_out_ = 0; + Py_buffer __pyx_bstruct_x; + Py_ssize_t __pyx_bstride_0_x = 0; + Py_ssize_t __pyx_bstride_1_x = 0; + Py_ssize_t __pyx_bshape_0_x = 0; + Py_ssize_t __pyx_bshape_1_x = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + double __pyx_t_11; + PyObject *__pyx_t_12 = NULL; + PyArrayObject *__pyx_t_13 = NULL; + npy_intp __pyx_t_14; + int __pyx_t_15; + int __pyx_t_16; + int __pyx_t_17; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__xi,&__pyx_n_s__bruteforce,0}; + __Pyx_RefNannySetupContext("find_simplex"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[3] = {0,0,0}; + values[2] = __pyx_k_9; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__xi); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("find_simplex", 0, 2, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__bruteforce); + if (unlikely(value)) { values[2] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "find_simplex") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_xi = values[1]; + __pyx_v_bruteforce = values[2]; + } else { + __pyx_v_bruteforce = __pyx_k_9; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 3: + __pyx_v_bruteforce = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: + __pyx_v_xi = PyTuple_GET_ITEM(__pyx_args, 1); + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; + } + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("find_simplex", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.find_simplex"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF(__pyx_v_xi); + __Pyx_INCREF(__pyx_v_bruteforce); + __pyx_v_x = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_out_ = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_xi_shape = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_out = Py_None; __Pyx_INCREF(Py_None); + __pyx_bstruct_x.buf = NULL; + __pyx_bstruct_out_.buf = NULL; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1020; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__asanyarray); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1020; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1020; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_xi); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_xi); + __Pyx_GIVEREF(__pyx_v_xi); + __pyx_t_3 = PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1020; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_xi); + __pyx_v_xi = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1022; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, -1, sizeof(long), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1022; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__ndim); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1022; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_t_3, Py_NE); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1022; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1022; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__pyx_t_4) { + + + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1023; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_10)); + PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_10)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_10)); + __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1023; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1023; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1025; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_v_xi_shape); + __pyx_v_xi_shape = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__reshape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__prod); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = PySequence_GetSlice(__pyx_t_2, 0, -1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = PyObject_Call(__pyx_t_1, __pyx_t_2, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_2, -1, sizeof(long), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_5 = 0; + __pyx_t_1 = 0; + __pyx_t_1 = PyObject_Call(__pyx_t_3, __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1026; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_xi); + __pyx_v_xi = __pyx_t_1; + __pyx_t_1 = 0; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__ascontiguousarray); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__astype); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = PyObject_Call(__pyx_t_2, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_x); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_x, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_x, (PyObject*)__pyx_v_x, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_8, __pyx_t_9, __pyx_t_10); + } + } + __pyx_bstride_0_x = __pyx_bstruct_x.strides[0]; __pyx_bstride_1_x = __pyx_bstruct_x.strides[1]; + __pyx_bshape_0_x = __pyx_bstruct_x.shape[0]; __pyx_bshape_1_x = __pyx_bstruct_x.shape[1]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1027; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_6 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_x)); + __pyx_v_x = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + + __pyx_v_start = 0; + + + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__finfo); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__eps); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyNumber_Multiply(__pyx_t_5, __pyx_int_10); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1031; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_eps = __pyx_t_11; + + + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__zeros); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_2, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_2)); + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_12 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__int); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_12) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __pyx_t_12 = PyEval_CallObjectWithKeywords(__pyx_t_5, __pyx_t_3, ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1032; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_out); + __pyx_v_out = __pyx_t_12; + __pyx_t_12 = 0; + + + if (!(likely(((__pyx_v_out) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_out, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1033; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_13 = ((PyArrayObject *)__pyx_v_out); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out_); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_out_, (PyObject*)__pyx_t_13, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_10, &__pyx_t_9, &__pyx_t_8); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out_, (PyObject*)__pyx_v_out_, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_8); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_10, __pyx_t_9, __pyx_t_8); + } + } + __pyx_bstride_0_out_ = __pyx_bstruct_out_.strides[0]; + __pyx_bshape_0_out_ = __pyx_bstruct_out_.shape[0]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1033; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_13 = 0; + __Pyx_INCREF(__pyx_v_out); + __Pyx_DECREF(((PyObject *)__pyx_v_out_)); + __pyx_v_out_ = ((PyArrayObject *)__pyx_v_out); + + + __pyx_v_info = __pyx_f_5scipy_7spatial_5qhull__get_delaunay_info(__pyx_v_self, 1, 0); + + + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_bruteforce); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1036; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__pyx_t_4) { + + + __pyx_t_14 = (__pyx_v_x->dimensions[0]); + for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_14; __pyx_t_7+=1) { + __pyx_v_k = __pyx_t_7; + + + __pyx_v_isimplex = __pyx_f_5scipy_7spatial_5qhull__find_simplex_bruteforce(__pyx_v_info, __pyx_v_c, (((double *)__pyx_v_x->data) + (__pyx_v_info->ndim * __pyx_v_k)), __pyx_v_eps); + + + __pyx_t_15 = __pyx_v_k; + __pyx_t_16 = -1; + if (__pyx_t_15 < 0) { + __pyx_t_15 += __pyx_bshape_0_out_; + if (unlikely(__pyx_t_15 < 0)) __pyx_t_16 = 0; + } else if (unlikely(__pyx_t_15 >= __pyx_bshape_0_out_)) __pyx_t_16 = 0; + if (unlikely(__pyx_t_16 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_16); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1042; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_bstruct_out_.buf, __pyx_t_15, __pyx_bstride_0_out_) = __pyx_v_isimplex; + } + goto __pyx_L7; + } + { + + + __pyx_t_14 = (__pyx_v_x->dimensions[0]); + for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_14; __pyx_t_7+=1) { + __pyx_v_k = __pyx_t_7; + + + __pyx_v_isimplex = __pyx_f_5scipy_7spatial_5qhull__find_simplex(__pyx_v_info, __pyx_v_c, (((double *)__pyx_v_x->data) + (__pyx_v_info->ndim * __pyx_v_k)), (&__pyx_v_start), __pyx_v_eps); + + + __pyx_t_16 = __pyx_v_k; + __pyx_t_17 = -1; + if (__pyx_t_16 < 0) { + __pyx_t_16 += __pyx_bshape_0_out_; + if (unlikely(__pyx_t_16 < 0)) __pyx_t_17 = 0; + } else if (unlikely(__pyx_t_16 >= __pyx_bshape_0_out_)) __pyx_t_17 = 0; + if (unlikely(__pyx_t_17 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_17); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1047; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_bstruct_out_.buf, __pyx_t_16, __pyx_bstride_0_out_) = __pyx_v_isimplex; + } + } + __pyx_L7:; + + + free(__pyx_v_info); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_12 = PyObject_GetAttr(__pyx_v_out, __pyx_n_s__reshape); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1051; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_2 = PySequence_GetSlice(__pyx_v_xi_shape, 0, -1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1051; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1051; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyObject_Call(__pyx_t_12, __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1051; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_12); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out_); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_x); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.find_simplex"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out_); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_x); + __pyx_L2:; + __Pyx_DECREF((PyObject *)__pyx_v_x); + __Pyx_DECREF((PyObject *)__pyx_v_out_); + __Pyx_DECREF(__pyx_v_xi_shape); + __Pyx_DECREF(__pyx_v_out); + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF(__pyx_v_xi); + __Pyx_DECREF(__pyx_v_bruteforce); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_plane_distance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static char __pyx_doc_5scipy_7spatial_5qhull_8Delaunay_plane_distance[] = "\n plane_distance(xi)\n\n Compute hyperplane distances to the point `xi` from all simplices.\n\n "; +static PyMethodDef __pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_plane_distance = {__Pyx_NAMESTR("plane_distance"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_plane_distance, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull_8Delaunay_plane_distance)}; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_plane_distance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_xi = 0; + PyArrayObject *__pyx_v_x; + PyArrayObject *__pyx_v_out_; + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_info; + double __pyx_v_z[(NPY_MAXDIMS + 1)]; + int __pyx_v_i; + int __pyx_v_j; + PyObject *__pyx_v_xi_shape; + PyObject *__pyx_v_out; + Py_buffer __pyx_bstruct_out_; + Py_ssize_t __pyx_bstride_0_out_ = 0; + Py_ssize_t __pyx_bstride_1_out_ = 0; + Py_ssize_t __pyx_bshape_0_out_ = 0; + Py_ssize_t __pyx_bshape_1_out_ = 0; + Py_buffer __pyx_bstruct_x; + Py_ssize_t __pyx_bstride_0_x = 0; + Py_ssize_t __pyx_bstride_1_x = 0; + Py_ssize_t __pyx_bshape_0_x = 0; + Py_ssize_t __pyx_bshape_1_x = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyArrayObject *__pyx_t_12 = NULL; + npy_intp __pyx_t_13; + int __pyx_t_14; + int __pyx_t_15; + int __pyx_t_16; + int __pyx_t_17; + int __pyx_t_18; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__xi,0}; + __Pyx_RefNannySetupContext("plane_distance"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__xi); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("plane_distance", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "plane_distance") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_xi = values[1]; + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_xi = PyTuple_GET_ITEM(__pyx_args, 1); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("plane_distance", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.plane_distance"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF(__pyx_v_xi); + __pyx_v_x = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_out_ = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_xi_shape = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_out = Py_None; __Pyx_INCREF(Py_None); + __pyx_bstruct_x.buf = NULL; + __pyx_bstruct_out_.buf = NULL; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1066; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_1, -1, sizeof(long), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1066; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__ndim); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1066; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyObject_RichCompare(__pyx_t_2, __pyx_t_1, Py_NE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1066; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1066; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_4) { + + + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1067; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_11)); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_kp_s_11)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_11)); + __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1067; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_1, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1067; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1070; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_v_xi_shape); + __pyx_v_xi_shape = __pyx_t_1; + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__reshape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__prod); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PySequence_GetSlice(__pyx_t_3, 0, -1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = PyObject_Call(__pyx_t_2, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_3, -1, sizeof(long), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_5 = 0; + __pyx_t_2 = 0; + __pyx_t_2 = PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1071; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_xi); + __pyx_v_xi = __pyx_t_2; + __pyx_t_2 = 0; + + + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__ascontiguousarray); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__astype); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = PyObject_Call(__pyx_t_3, __pyx_t_1, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_x); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_x, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_x, (PyObject*)__pyx_v_x, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_8, __pyx_t_9, __pyx_t_10); + } + } + __pyx_bstride_0_x = __pyx_bstruct_x.strides[0]; __pyx_bstride_1_x = __pyx_bstruct_x.strides[1]; + __pyx_bshape_0_x = __pyx_bstruct_x.shape[0]; __pyx_bshape_1_x = __pyx_bstruct_x.shape[1]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1072; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_6 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_x)); + __pyx_v_x = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + + __pyx_v_info = __pyx_f_5scipy_7spatial_5qhull__get_delaunay_info(__pyx_v_self, 0, 0); + + + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_PyInt_to_py_npy_intp((__pyx_v_x->dimensions[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyInt_FromLong(__pyx_v_info->nsimplex); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_5 = 0; + __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_2)); + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_11 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_11); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__dtype), __pyx_t_11) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; + __pyx_t_11 = PyEval_CallObjectWithKeywords(__pyx_t_1, __pyx_t_3, ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_11); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_out); + __pyx_v_out = __pyx_t_11; + __pyx_t_11 = 0; + + + if (!(likely(((__pyx_v_out) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_out, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1077; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_12 = ((PyArrayObject *)__pyx_v_out); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out_); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_out_, (PyObject*)__pyx_t_12, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_10, &__pyx_t_9, &__pyx_t_8); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out_, (PyObject*)__pyx_v_out_, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_8); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_10, __pyx_t_9, __pyx_t_8); + } + } + __pyx_bstride_0_out_ = __pyx_bstruct_out_.strides[0]; __pyx_bstride_1_out_ = __pyx_bstruct_out_.strides[1]; + __pyx_bshape_0_out_ = __pyx_bstruct_out_.shape[0]; __pyx_bshape_1_out_ = __pyx_bstruct_out_.shape[1]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1077; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_12 = 0; + __Pyx_INCREF(__pyx_v_out); + __Pyx_DECREF(((PyObject *)__pyx_v_out_)); + __pyx_v_out_ = ((PyArrayObject *)__pyx_v_out); + + + __pyx_t_13 = (__pyx_v_x->dimensions[0]); + for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_13; __pyx_t_7+=1) { + __pyx_v_i = __pyx_t_7; + + + __pyx_t_14 = __pyx_v_info->nsimplex; + for (__pyx_t_15 = 0; __pyx_t_15 < __pyx_t_14; __pyx_t_15+=1) { + __pyx_v_j = __pyx_t_15; + + + __pyx_f_5scipy_7spatial_5qhull__lift_point(__pyx_v_info, (((double *)__pyx_v_x->data) + (__pyx_v_info->ndim * __pyx_v_i)), __pyx_v_z); + + + __pyx_t_16 = __pyx_v_i; + __pyx_t_17 = __pyx_v_j; + __pyx_t_18 = -1; + if (__pyx_t_16 < 0) { + __pyx_t_16 += __pyx_bshape_0_out_; + if (unlikely(__pyx_t_16 < 0)) __pyx_t_18 = 0; + } else if (unlikely(__pyx_t_16 >= __pyx_bshape_0_out_)) __pyx_t_18 = 0; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_bshape_1_out_; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_18 = 1; + } else if (unlikely(__pyx_t_17 >= __pyx_bshape_1_out_)) __pyx_t_18 = 1; + if (unlikely(__pyx_t_18 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_18); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1082; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_out_.buf, __pyx_t_16, __pyx_bstride_0_out_, __pyx_t_17, __pyx_bstride_1_out_) = __pyx_f_5scipy_7spatial_5qhull__distplane(__pyx_v_info, __pyx_v_j, __pyx_v_z); + } + } + + + free(__pyx_v_info); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_11 = PyObject_GetAttr(__pyx_v_out, __pyx_n_s__reshape); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1086; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_11); + __pyx_t_2 = PySequence_GetSlice(__pyx_v_xi_shape, 0, -1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1086; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__nsimplex); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1086; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1086; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyNumber_Add(__pyx_t_2, __pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1086; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1086; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_11, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1086; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_11); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out_); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_x); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.plane_distance"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out_); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_x); + __pyx_L2:; + __Pyx_DECREF((PyObject *)__pyx_v_x); + __Pyx_DECREF((PyObject *)__pyx_v_out_); + __Pyx_DECREF(__pyx_v_xi_shape); + __Pyx_DECREF(__pyx_v_out); + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF(__pyx_v_xi); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_lift_points(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static char __pyx_doc_5scipy_7spatial_5qhull_8Delaunay_lift_points[] = "\n lift_points(tri, x)\n\n Lift points to the Qhull paraboloid.\n\n "; +static PyMethodDef __pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_lift_points = {__Pyx_NAMESTR("lift_points"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_lift_points, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull_8Delaunay_lift_points)}; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_8Delaunay_lift_points(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_tri = 0; + PyObject *__pyx_v_x = 0; + PyObject *__pyx_v_z; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__tri,&__pyx_n_s__x,0}; + __Pyx_RefNannySetupContext("lift_points"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__tri); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__x); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("lift_points", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1088; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "lift_points") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1088; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_tri = values[0]; + __pyx_v_x = values[1]; + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_tri = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_x = PyTuple_GET_ITEM(__pyx_args, 1); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("lift_points", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1088; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.lift_points"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_v_z = Py_None; __Pyx_INCREF(Py_None); + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetAttr(__pyx_v_x, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PySequence_GetSlice(__pyx_t_1, 0, -1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetAttr(__pyx_v_x, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = __Pyx_GetItemInt(__pyx_t_1, -1, sizeof(long), PyInt_FromLong); if (!__pyx_t_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyNumber_Add(__pyx_t_4, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyNumber_Add(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_1)); + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__dtype), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_2, __pyx_t_4, ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1095; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_z); + __pyx_v_z = __pyx_t_5; + __pyx_t_5 = 0; + + + __pyx_t_5 = PySlice_New(Py_None, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1096; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1096; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(Py_Ellipsis); + PyTuple_SET_ITEM(__pyx_t_1, 0, Py_Ellipsis); + __Pyx_GIVEREF(Py_Ellipsis); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + if (PyObject_SetItem(__pyx_v_z, __pyx_t_1, __pyx_v_x) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1096; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_t_1 = PyNumber_Power(__pyx_v_x, __pyx_int_2, Py_None); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1097; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__sum); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1097; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1097; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_1)); + if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__axis), __pyx_int_neg_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1097; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_5, ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1097; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1097; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(Py_Ellipsis); + PyTuple_SET_ITEM(__pyx_t_1, 0, Py_Ellipsis); + __Pyx_GIVEREF(Py_Ellipsis); + __Pyx_INCREF(__pyx_int_neg_1); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_neg_1); + __Pyx_GIVEREF(__pyx_int_neg_1); + if (PyObject_SetItem(__pyx_v_z, __pyx_t_1, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1097; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = PyObject_GetAttr(__pyx_v_tri, __pyx_n_s__paraboloid_scale); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(Py_Ellipsis); + PyTuple_SET_ITEM(__pyx_t_1, 0, Py_Ellipsis); + __Pyx_GIVEREF(Py_Ellipsis); + __Pyx_INCREF(__pyx_int_neg_1); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_neg_1); + __Pyx_GIVEREF(__pyx_int_neg_1); + __pyx_t_5 = PyObject_GetItem(__pyx_v_z, __pyx_t_1); if (!__pyx_t_5) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = PyNumber_InPlaceMultiply(__pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyObject_SetItem(__pyx_v_z, __pyx_t_1, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1098; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_tri, __pyx_n_s__paraboloid_shift); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(Py_Ellipsis); + PyTuple_SET_ITEM(__pyx_t_2, 0, Py_Ellipsis); + __Pyx_GIVEREF(Py_Ellipsis); + __Pyx_INCREF(__pyx_int_neg_1); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_neg_1); + __Pyx_GIVEREF(__pyx_int_neg_1); + __pyx_t_5 = PyObject_GetItem(__pyx_v_z, __pyx_t_2); if (!__pyx_t_5) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_t_5, __pyx_t_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyObject_SetItem(__pyx_v_z, __pyx_t_2, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1099; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_z); + __pyx_r = __pyx_v_z; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("scipy.spatial.qhull.Delaunay.lift_points"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF(__pyx_v_z); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_tsearch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static char __pyx_doc_5scipy_7spatial_5qhull_tsearch[] = "\n tsearch(tri, xi)\n\n Find simplices containing the given points. This function does the\n same thing as Delaunay.find_simplex.\n\n .. versionadded:: 0.9\n\n See Also\n --------\n Delaunay.find_simplex\n\n "; +static PyObject *__pyx_pf_5scipy_7spatial_5qhull_tsearch(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_tri = 0; + PyObject *__pyx_v_xi = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__tri,&__pyx_n_s__xi,0}; + __Pyx_RefNannySetupContext("tsearch"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__tri); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__xi); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("tsearch", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1103; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "tsearch") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1103; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_tri = values[0]; + __pyx_v_xi = values[1]; + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_tri = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_xi = PyTuple_GET_ITEM(__pyx_args, 1); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("tsearch", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1103; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("scipy.spatial.qhull.tsearch"); + return NULL; + __pyx_L4_argument_unpacking_done:; + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyObject_GetAttr(__pyx_v_tri, __pyx_n_s__find_simplex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1117; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1117; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_xi); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_xi); + __Pyx_GIVEREF(__pyx_v_xi); + __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1117; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("scipy.spatial.qhull.tsearch"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_f_5scipy_7spatial_5qhull__get_delaunay_info(PyObject *__pyx_v_obj, int __pyx_v_compute_transform, int __pyx_v_compute_vertex_to_simplex) { + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_info; + PyArrayObject *__pyx_v_transform; + PyArrayObject *__pyx_v_vertex_to_simplex; + PyArrayObject *__pyx_v_points = 0; + PyArrayObject *__pyx_v_vertices = 0; + PyArrayObject *__pyx_v_neighbors = 0; + PyArrayObject *__pyx_v_equations = 0; + PyArrayObject *__pyx_v_min_bound = 0; + PyArrayObject *__pyx_v_max_bound = 0; + Py_buffer __pyx_bstruct_neighbors; + Py_ssize_t __pyx_bstride_0_neighbors = 0; + Py_ssize_t __pyx_bstride_1_neighbors = 0; + Py_ssize_t __pyx_bshape_0_neighbors = 0; + Py_ssize_t __pyx_bshape_1_neighbors = 0; + Py_buffer __pyx_bstruct_transform; + Py_ssize_t __pyx_bstride_0_transform = 0; + Py_ssize_t __pyx_bstride_1_transform = 0; + Py_ssize_t __pyx_bstride_2_transform = 0; + Py_ssize_t __pyx_bshape_0_transform = 0; + Py_ssize_t __pyx_bshape_1_transform = 0; + Py_ssize_t __pyx_bshape_2_transform = 0; + Py_buffer __pyx_bstruct_vertices; + Py_ssize_t __pyx_bstride_0_vertices = 0; + Py_ssize_t __pyx_bstride_1_vertices = 0; + Py_ssize_t __pyx_bshape_0_vertices = 0; + Py_ssize_t __pyx_bshape_1_vertices = 0; + Py_buffer __pyx_bstruct_points; + Py_ssize_t __pyx_bstride_0_points = 0; + Py_ssize_t __pyx_bstride_1_points = 0; + Py_ssize_t __pyx_bshape_0_points = 0; + Py_ssize_t __pyx_bshape_1_points = 0; + Py_buffer __pyx_bstruct_vertex_to_simplex; + Py_ssize_t __pyx_bstride_0_vertex_to_simplex = 0; + Py_ssize_t __pyx_bshape_0_vertex_to_simplex = 0; + Py_buffer __pyx_bstruct_min_bound; + Py_ssize_t __pyx_bstride_0_min_bound = 0; + Py_ssize_t __pyx_bshape_0_min_bound = 0; + Py_buffer __pyx_bstruct_max_bound; + Py_ssize_t __pyx_bstride_0_max_bound = 0; + Py_ssize_t __pyx_bshape_0_max_bound = 0; + Py_buffer __pyx_bstruct_equations; + Py_ssize_t __pyx_bstride_0_equations = 0; + Py_ssize_t __pyx_bstride_1_equations = 0; + Py_ssize_t __pyx_bshape_0_equations = 0; + Py_ssize_t __pyx_bshape_1_equations = 0; + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_r; + PyObject *__pyx_t_1 = NULL; + PyArrayObject *__pyx_t_2 = NULL; + PyArrayObject *__pyx_t_3 = NULL; + PyArrayObject *__pyx_t_4 = NULL; + PyArrayObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + PyArrayObject *__pyx_t_7 = NULL; + double __pyx_t_8; + int __pyx_t_9; + PyArrayObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyArrayObject *__pyx_t_14 = NULL; + __Pyx_RefNannySetupContext("_get_delaunay_info"); + __Pyx_INCREF(__pyx_v_obj); + __pyx_v_transform = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_vertex_to_simplex = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_bstruct_transform.buf = NULL; + __pyx_bstruct_vertex_to_simplex.buf = NULL; + __pyx_bstruct_points.buf = NULL; + __pyx_bstruct_vertices.buf = NULL; + __pyx_bstruct_neighbors.buf = NULL; + __pyx_bstruct_equations.buf = NULL; + __pyx_bstruct_min_bound.buf = NULL; + __pyx_bstruct_max_bound.buf = NULL; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__points); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_points, (PyObject*)__pyx_t_2, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_points = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_points.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_points = __pyx_bstruct_points.strides[0]; __pyx_bstride_1_points = __pyx_bstruct_points.strides[1]; + __pyx_bshape_0_points = __pyx_bstruct_points.shape[0]; __pyx_bshape_1_points = __pyx_bstruct_points.shape[1]; + } + } + __pyx_t_2 = 0; + __pyx_v_points = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__vertices); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1131; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1131; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_t_3, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_vertices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_vertices.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1131; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_vertices = __pyx_bstruct_vertices.strides[0]; __pyx_bstride_1_vertices = __pyx_bstruct_vertices.strides[1]; + __pyx_bshape_0_vertices = __pyx_bstruct_vertices.shape[0]; __pyx_bshape_1_vertices = __pyx_bstruct_vertices.shape[1]; + } + } + __pyx_t_3 = 0; + __pyx_v_vertices = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__neighbors); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_neighbors, (PyObject*)__pyx_t_4, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_neighbors = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_neighbors.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_neighbors = __pyx_bstruct_neighbors.strides[0]; __pyx_bstride_1_neighbors = __pyx_bstruct_neighbors.strides[1]; + __pyx_bshape_0_neighbors = __pyx_bstruct_neighbors.shape[0]; __pyx_bshape_1_neighbors = __pyx_bstruct_neighbors.shape[1]; + } + } + __pyx_t_4 = 0; + __pyx_v_neighbors = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__equations); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1133; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1133; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_equations, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_equations = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_equations.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1133; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_equations = __pyx_bstruct_equations.strides[0]; __pyx_bstride_1_equations = __pyx_bstruct_equations.strides[1]; + __pyx_bshape_0_equations = __pyx_bstruct_equations.shape[0]; __pyx_bshape_1_equations = __pyx_bstruct_equations.shape[1]; + } + } + __pyx_t_5 = 0; + __pyx_v_equations = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__min_bound); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_min_bound, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_min_bound = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_min_bound.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_min_bound = __pyx_bstruct_min_bound.strides[0]; + __pyx_bshape_0_min_bound = __pyx_bstruct_min_bound.shape[0]; + } + } + __pyx_t_6 = 0; + __pyx_v_min_bound = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__max_bound); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_7 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_max_bound, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_max_bound = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_max_bound.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_max_bound = __pyx_bstruct_max_bound.strides[0]; + __pyx_bshape_0_max_bound = __pyx_bstruct_max_bound.shape[0]; + } + } + __pyx_t_7 = 0; + __pyx_v_max_bound = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_v_info = ((__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *)malloc((sizeof(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t)))); + + + __pyx_v_info->ndim = (__pyx_v_points->dimensions[1]); + + + __pyx_v_info->npoints = (__pyx_v_points->dimensions[0]); + + + __pyx_v_info->nsimplex = (__pyx_v_vertices->dimensions[0]); + + + __pyx_v_info->points = ((double *)__pyx_v_points->data); + + + __pyx_v_info->vertices = ((int *)__pyx_v_vertices->data); + + + __pyx_v_info->neighbors = ((int *)__pyx_v_neighbors->data); + + + __pyx_v_info->equations = ((double *)__pyx_v_equations->data); + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__paraboloid_scale); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_8 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_info->paraboloid_scale = __pyx_t_8; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__paraboloid_shift); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_8 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_info->paraboloid_shift = __pyx_t_8; + + + __pyx_t_9 = __pyx_v_compute_transform; + if (__pyx_t_9) { + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__transform); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_10 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_transform); + __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_transform, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack); + if (unlikely(__pyx_t_9 < 0)) { + PyErr_Fetch(&__pyx_t_11, &__pyx_t_12, &__pyx_t_13); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_transform, (PyObject*)__pyx_v_transform, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_13); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_11, __pyx_t_12, __pyx_t_13); + } + } + __pyx_bstride_0_transform = __pyx_bstruct_transform.strides[0]; __pyx_bstride_1_transform = __pyx_bstruct_transform.strides[1]; __pyx_bstride_2_transform = __pyx_bstruct_transform.strides[2]; + __pyx_bshape_0_transform = __pyx_bstruct_transform.shape[0]; __pyx_bshape_1_transform = __pyx_bstruct_transform.shape[1]; __pyx_bshape_2_transform = __pyx_bstruct_transform.shape[2]; + if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_10 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_transform)); + __pyx_v_transform = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_v_info->transform = ((double *)__pyx_v_transform->data); + goto __pyx_L3; + } + { + + + __pyx_v_info->transform = NULL; + } + __pyx_L3:; + + + __pyx_t_9 = __pyx_v_compute_vertex_to_simplex; + if (__pyx_t_9) { + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_obj, __pyx_n_s__vertex_to_simplex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1153; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1153; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_14 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertex_to_simplex); + __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_vertex_to_simplex, (PyObject*)__pyx_t_14, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack); + if (unlikely(__pyx_t_9 < 0)) { + PyErr_Fetch(&__pyx_t_13, &__pyx_t_12, &__pyx_t_11); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertex_to_simplex, (PyObject*)__pyx_v_vertex_to_simplex, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_13); Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_13, __pyx_t_12, __pyx_t_11); + } + } + __pyx_bstride_0_vertex_to_simplex = __pyx_bstruct_vertex_to_simplex.strides[0]; + __pyx_bshape_0_vertex_to_simplex = __pyx_bstruct_vertex_to_simplex.shape[0]; + if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1153; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_14 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_vertex_to_simplex)); + __pyx_v_vertex_to_simplex = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_v_info->vertex_to_simplex = ((int *)__pyx_v_vertex_to_simplex->data); + goto __pyx_L4; + } + { + + + __pyx_v_info->vertex_to_simplex = NULL; + } + __pyx_L4:; + + + __pyx_v_info->min_bound = ((double *)__pyx_v_min_bound->data); + + + __pyx_v_info->max_bound = ((double *)__pyx_v_max_bound->data); + + + __pyx_r = __pyx_v_info; + goto __pyx_L0; + + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_neighbors); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_transform); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertex_to_simplex); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_min_bound); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_max_bound); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_equations); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_WriteUnraisable("scipy.spatial.qhull._get_delaunay_info"); + __pyx_r = 0; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_neighbors); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_transform); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertex_to_simplex); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_min_bound); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_max_bound); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_equations); + __pyx_L2:; + __Pyx_DECREF((PyObject *)__pyx_v_transform); + __Pyx_DECREF((PyObject *)__pyx_v_vertex_to_simplex); + __Pyx_XDECREF((PyObject *)__pyx_v_points); + __Pyx_XDECREF((PyObject *)__pyx_v_vertices); + __Pyx_XDECREF((PyObject *)__pyx_v_neighbors); + __Pyx_XDECREF((PyObject *)__pyx_v_equations); + __Pyx_XDECREF((PyObject *)__pyx_v_min_bound); + __Pyx_XDECREF((PyObject *)__pyx_v_max_bound); + __Pyx_DECREF(__pyx_v_obj); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); +static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { + int __pyx_v_copy_shape; + int __pyx_v_i; + int __pyx_v_ndim; + int __pyx_v_endian_detector; + int __pyx_v_little_endian; + int __pyx_v_t; + char *__pyx_v_f; + PyArray_Descr *__pyx_v_descr = 0; + int __pyx_v_offset; + int __pyx_v_hasfields; + int __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + int __pyx_t_7; + int __pyx_t_8; + char *__pyx_t_9; + __Pyx_RefNannySetupContext("__getbuffer__"); + if (__pyx_v_info == NULL) return 0; + __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(__pyx_v_info->obj); + __Pyx_INCREF((PyObject *)__pyx_v_self); + + + __pyx_v_endian_detector = 1; + + + __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); + + + __pyx_v_ndim = PyArray_NDIM(((PyArrayObject *)__pyx_v_self)); + + + __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t))); + if (__pyx_t_1) { + + + __pyx_v_copy_shape = 1; + goto __pyx_L5; + } + { + + + __pyx_v_copy_shape = 0; + } + __pyx_L5:; + + + __pyx_t_1 = ((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS); + if (__pyx_t_1) { + + + __pyx_t_2 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_C_CONTIGUOUS)); + __pyx_t_3 = __pyx_t_2; + } else { + __pyx_t_3 = __pyx_t_1; + } + if (__pyx_t_3) { + + + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_12)); + PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_kp_u_12)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_12)); + __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_4, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + __pyx_t_3 = ((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS); + if (__pyx_t_3) { + + + __pyx_t_1 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_F_CONTIGUOUS)); + __pyx_t_2 = __pyx_t_1; + } else { + __pyx_t_2 = __pyx_t_3; + } + if (__pyx_t_2) { + + + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_13)); + PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_kp_u_13)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_13)); + __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L7; + } + __pyx_L7:; + + + __pyx_v_info->buf = PyArray_DATA(((PyArrayObject *)__pyx_v_self)); + + + __pyx_v_info->ndim = __pyx_v_ndim; + + + __pyx_t_6 = __pyx_v_copy_shape; + if (__pyx_t_6) { + + + __pyx_v_info->strides = ((Py_ssize_t *)malloc((((sizeof(Py_ssize_t)) * __pyx_v_ndim) * 2))); + + + __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim); + + + __pyx_t_6 = __pyx_v_ndim; + for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_6; __pyx_t_7+=1) { + __pyx_v_i = __pyx_t_7; + + + (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]); + + + (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]); + } + goto __pyx_L8; + } + { + + + __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(((PyArrayObject *)__pyx_v_self))); + + + __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(((PyArrayObject *)__pyx_v_self))); + } + __pyx_L8:; + + + __pyx_v_info->suboffsets = NULL; + + + __pyx_v_info->itemsize = PyArray_ITEMSIZE(((PyArrayObject *)__pyx_v_self)); + + + __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(((PyArrayObject *)__pyx_v_self))); + + + __pyx_v_f = NULL; + + + __Pyx_INCREF(((PyObject *)((PyArrayObject *)__pyx_v_self)->descr)); + __pyx_v_descr = ((PyArrayObject *)__pyx_v_self)->descr; + + + __pyx_v_hasfields = PyDataType_HASFIELDS(__pyx_v_descr); + + + __pyx_t_2 = (!__pyx_v_hasfields); + if (__pyx_t_2) { + __pyx_t_3 = (!__pyx_v_copy_shape); + __pyx_t_1 = __pyx_t_3; + } else { + __pyx_t_1 = __pyx_t_2; + } + if (__pyx_t_1) { + + + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); + __pyx_v_info->obj = Py_None; + goto __pyx_L11; + } + { + + + __Pyx_INCREF(__pyx_v_self); + __Pyx_GIVEREF(__pyx_v_self); + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); + __pyx_v_info->obj = __pyx_v_self; + } + __pyx_L11:; + + + __pyx_t_1 = (!__pyx_v_hasfields); + if (__pyx_t_1) { + + + __pyx_v_t = __pyx_v_descr->type_num; + + + __pyx_t_1 = (__pyx_v_descr->byteorder == '>'); + if (__pyx_t_1) { + __pyx_t_2 = __pyx_v_little_endian; + } else { + __pyx_t_2 = __pyx_t_1; + } + if (!__pyx_t_2) { + + + __pyx_t_1 = (__pyx_v_descr->byteorder == '<'); + if (__pyx_t_1) { + __pyx_t_3 = (!__pyx_v_little_endian); + __pyx_t_8 = __pyx_t_3; + } else { + __pyx_t_8 = __pyx_t_1; + } + __pyx_t_1 = __pyx_t_8; + } else { + __pyx_t_1 = __pyx_t_2; + } + if (__pyx_t_1) { + + + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_14)); + PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_kp_u_14)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_14)); + __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_4, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L13; + } + __pyx_L13:; + + + __pyx_t_1 = (__pyx_v_t == NPY_BYTE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__b; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_UBYTE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__B; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_SHORT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__h; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_USHORT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__H; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_INT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__i; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_UINT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__I; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_LONG); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__l; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_ULONG); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__L; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_LONGLONG); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__q; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_ULONGLONG); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__Q; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_FLOAT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__f; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_DOUBLE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__d; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_LONGDOUBLE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__g; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_CFLOAT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__Zf; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_CDOUBLE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__Zd; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_CLONGDOUBLE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__Zg; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_OBJECT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__O; + goto __pyx_L14; + } + { + + + __pyx_t_5 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_15), __pyx_t_5); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_L14:; + + + __pyx_v_info->format = __pyx_v_f; + + + __pyx_r = 0; + goto __pyx_L0; + goto __pyx_L12; + } + { + + + __pyx_v_info->format = ((char *)malloc(255)); + + + (__pyx_v_info->format[0]) = '^'; + + + __pyx_v_offset = 0; + + + __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_f = __pyx_t_9; + + + (__pyx_v_f[0]) = 0; + } + __pyx_L12:; + + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("numpy.ndarray.__getbuffer__"); + __pyx_r = -1; + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = NULL; + goto __pyx_L2; + __pyx_L0:; + if (__pyx_v_info->obj == Py_None) { + __Pyx_GOTREF(Py_None); + __Pyx_DECREF(Py_None); __pyx_v_info->obj = NULL; + } + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_descr); + __Pyx_DECREF((PyObject *)__pyx_v_self); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static void __pyx_pf_5numpy_7ndarray___releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); +static void __pyx_pf_5numpy_7ndarray___releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) { + int __pyx_t_1; + __Pyx_RefNannySetupContext("__releasebuffer__"); + __Pyx_INCREF((PyObject *)__pyx_v_self); + + + __pyx_t_1 = PyArray_HASFIELDS(((PyArrayObject *)__pyx_v_self)); + if (__pyx_t_1) { + + + free(__pyx_v_info->format); + goto __pyx_L5; + } + __pyx_L5:; + + + __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t))); + if (__pyx_t_1) { + + + free(__pyx_v_info->strides); + goto __pyx_L6; + } + __pyx_L6:; + + __Pyx_DECREF((PyObject *)__pyx_v_self); + __Pyx_RefNannyFinishContext(); +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew1"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 756; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew2"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew3"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew4"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew5"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx_v_descr, char *__pyx_v_f, char *__pyx_v_end, int *__pyx_v_offset) { + PyArray_Descr *__pyx_v_child; + int __pyx_v_endian_detector; + int __pyx_v_little_endian; + PyObject *__pyx_v_fields; + PyObject *__pyx_v_childname; + PyObject *__pyx_v_new_offset; + PyObject *__pyx_v_t; + char *__pyx_r; + Py_ssize_t __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + int __pyx_t_7; + int __pyx_t_8; + int __pyx_t_9; + char *__pyx_t_10; + __Pyx_RefNannySetupContext("_util_dtypestring"); + __Pyx_INCREF((PyObject *)__pyx_v_descr); + __pyx_v_child = ((PyArray_Descr *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_fields = ((PyObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_childname = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_new_offset = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_t = Py_None; __Pyx_INCREF(Py_None); + + + __pyx_v_endian_detector = 1; + + + __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); + + + if (likely(((PyObject *)__pyx_v_descr->names) != Py_None)) { + __pyx_t_1 = 0; __pyx_t_2 = ((PyObject *)__pyx_v_descr->names); __Pyx_INCREF(__pyx_t_2); + } else { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 781; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + for (;;) { + if (__pyx_t_1 >= PyTuple_GET_SIZE(__pyx_t_2)) break; + __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_1); __Pyx_INCREF(__pyx_t_3); __pyx_t_1++; + __Pyx_DECREF(__pyx_v_childname); + __pyx_v_childname = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(((PyObject *)__pyx_v_fields)); + __pyx_v_fields = ((PyObject *)__pyx_t_3); + __pyx_t_3 = 0; + + + if (likely(((PyObject *)__pyx_v_fields) != Py_None) && likely(PyTuple_GET_SIZE(((PyObject *)__pyx_v_fields)) == 2)) { + PyObject* tuple = ((PyObject *)__pyx_v_fields); + __pyx_t_3 = PyTuple_GET_ITEM(tuple, 0); __Pyx_INCREF(__pyx_t_3); + if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 783; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyTuple_GET_ITEM(tuple, 1); __Pyx_INCREF(__pyx_t_4); + __Pyx_DECREF(((PyObject *)__pyx_v_child)); + __pyx_v_child = ((PyArray_Descr *)__pyx_t_3); + __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_new_offset); + __pyx_v_new_offset = __pyx_t_4; + __pyx_t_4 = 0; + } else { + __Pyx_UnpackTupleError(((PyObject *)__pyx_v_fields), 2); + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 783; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + + + __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + + + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_16)); + PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_kp_u_16)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_16)); + __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L5; + } + __pyx_L5:; + + + __pyx_t_6 = (__pyx_v_child->byteorder == '>'); + if (__pyx_t_6) { + __pyx_t_7 = __pyx_v_little_endian; + } else { + __pyx_t_7 = __pyx_t_6; + } + if (!__pyx_t_7) { + + + __pyx_t_6 = (__pyx_v_child->byteorder == '<'); + if (__pyx_t_6) { + __pyx_t_8 = (!__pyx_v_little_endian); + __pyx_t_9 = __pyx_t_8; + } else { + __pyx_t_9 = __pyx_t_6; + } + __pyx_t_6 = __pyx_t_9; + } else { + __pyx_t_6 = __pyx_t_7; + } + if (__pyx_t_6) { + + + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_14)); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_kp_u_14)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_14)); + __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + while (1) { + __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (!__pyx_t_6) break; + + + (__pyx_v_f[0]) = 120; + + + __pyx_v_f += 1; + + + (__pyx_v_offset[0]) += 1; + } + + + (__pyx_v_offset[0]) += __pyx_v_child->elsize; + + + __pyx_t_6 = (!PyDataType_HASFIELDS(__pyx_v_child)); + if (__pyx_t_6) { + + + __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_v_t); + __pyx_v_t = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_6 = ((__pyx_v_end - __pyx_v_f) < 5); + if (__pyx_t_6) { + + + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 810; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_17)); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_kp_u_17)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_17)); + __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 810; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 810; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L10; + } + __pyx_L10:; + + + __pyx_t_5 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 813; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 813; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 813; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 98; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 814; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 814; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 814; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 66; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 104; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 816; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 816; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 816; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 72; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 105; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 73; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 108; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 76; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 821; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 821; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 821; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 113; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 81; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 102; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 100; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 103; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 90; + (__pyx_v_f[1]) = 102; + __pyx_v_f += 1; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 90; + (__pyx_v_f[1]) = 100; + __pyx_v_f += 1; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 90; + (__pyx_v_f[1]) = 103; + __pyx_v_f += 1; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 79; + goto __pyx_L11; + } + { + + + __pyx_t_3 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_15), __pyx_v_t); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_L11:; + + + __pyx_v_f += 1; + goto __pyx_L9; + } + { + + + __pyx_t_10 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_10 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_f = __pyx_t_10; + } + __pyx_L9:; + } + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_r = __pyx_v_f; + goto __pyx_L0; + + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("numpy._util_dtypestring"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF((PyObject *)__pyx_v_child); + __Pyx_DECREF(__pyx_v_fields); + __Pyx_DECREF(__pyx_v_childname); + __Pyx_DECREF(__pyx_v_new_offset); + __Pyx_DECREF(__pyx_v_t); + __Pyx_DECREF((PyObject *)__pyx_v_descr); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { + PyObject *__pyx_v_baseptr; + int __pyx_t_1; + __Pyx_RefNannySetupContext("set_array_base"); + __Pyx_INCREF((PyObject *)__pyx_v_arr); + __Pyx_INCREF(__pyx_v_base); + + + __pyx_t_1 = (__pyx_v_base == Py_None); + if (__pyx_t_1) { + + + __pyx_v_baseptr = NULL; + goto __pyx_L3; + } + { + + + Py_INCREF(__pyx_v_base); + + + __pyx_v_baseptr = ((PyObject *)__pyx_v_base); + } + __pyx_L3:; + + + Py_XDECREF(__pyx_v_arr->base); + + + __pyx_v_arr->base = __pyx_v_baseptr; + + __Pyx_DECREF((PyObject *)__pyx_v_arr); + __Pyx_DECREF(__pyx_v_base); + __Pyx_RefNannyFinishContext(); +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { + PyObject *__pyx_r = NULL; + int __pyx_t_1; + __Pyx_RefNannySetupContext("get_array_base"); + __Pyx_INCREF((PyObject *)__pyx_v_arr); + + + __pyx_t_1 = (__pyx_v_arr->base == NULL); + if (__pyx_t_1) { + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_None); + __pyx_r = Py_None; + goto __pyx_L0; + goto __pyx_L3; + } + { + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_arr->base)); + __pyx_r = ((PyObject *)__pyx_v_arr->base); + goto __pyx_L0; + } + __pyx_L3:; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + __pyx_L0:; + __Pyx_DECREF((PyObject *)__pyx_v_arr); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static struct PyMethodDef __pyx_methods[] = { + {__Pyx_NAMESTR("_construct_delaunay"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull__construct_delaunay, METH_O, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull__construct_delaunay)}, + {__Pyx_NAMESTR("_qhull_get_facet_array"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull__qhull_get_facet_array, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull__qhull_get_facet_array)}, + {__Pyx_NAMESTR("_get_barycentric_transforms"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull__get_barycentric_transforms, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull__get_barycentric_transforms)}, + {__Pyx_NAMESTR("tsearch"), (PyCFunction)__pyx_pf_5scipy_7spatial_5qhull_tsearch, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_5scipy_7spatial_5qhull_tsearch)}, + {0, 0, 0, 0} +}; + +static void __pyx_init_filenames(void); + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + __Pyx_NAMESTR("qhull"), + __Pyx_DOCSTR(__pyx_k_18), + -1, + __pyx_methods , + NULL, + NULL, + NULL, + NULL +}; +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_kp_s_10, __pyx_k_10, sizeof(__pyx_k_10), 0, 0, 1, 0}, + {&__pyx_kp_s_11, __pyx_k_11, sizeof(__pyx_k_11), 0, 0, 1, 0}, + {&__pyx_kp_u_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 1, 0, 0}, + {&__pyx_kp_u_13, __pyx_k_13, sizeof(__pyx_k_13), 0, 1, 0, 0}, + {&__pyx_kp_u_14, __pyx_k_14, sizeof(__pyx_k_14), 0, 1, 0, 0}, + {&__pyx_kp_u_15, __pyx_k_15, sizeof(__pyx_k_15), 0, 1, 0, 0}, + {&__pyx_kp_u_16, __pyx_k_16, sizeof(__pyx_k_16), 0, 1, 0, 0}, + {&__pyx_kp_u_17, __pyx_k_17, sizeof(__pyx_k_17), 0, 1, 0, 0}, + {&__pyx_kp_s_19, __pyx_k_19, sizeof(__pyx_k_19), 0, 0, 1, 0}, + {&__pyx_kp_s_2, __pyx_k_2, sizeof(__pyx_k_2), 0, 0, 1, 0}, + {&__pyx_kp_s_3, __pyx_k_3, sizeof(__pyx_k_3), 0, 0, 1, 0}, + {&__pyx_kp_s_4, __pyx_k_4, sizeof(__pyx_k_4), 0, 0, 1, 0}, + {&__pyx_n_s_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 0, 1, 1}, + {&__pyx_kp_s_6, __pyx_k_6, sizeof(__pyx_k_6), 0, 0, 1, 0}, + {&__pyx_kp_s_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 0, 1, 0}, + {&__pyx_n_s_8, __pyx_k_8, sizeof(__pyx_k_8), 0, 0, 1, 1}, + {&__pyx_n_s__Delaunay, __pyx_k__Delaunay, sizeof(__pyx_k__Delaunay), 0, 0, 1, 1}, + {&__pyx_n_s__Lock, __pyx_k__Lock, sizeof(__pyx_k__Lock), 0, 0, 1, 1}, + {&__pyx_n_s__NOerrexit, __pyx_k__NOerrexit, sizeof(__pyx_k__NOerrexit), 0, 0, 1, 1}, + {&__pyx_n_s__RuntimeError, __pyx_k__RuntimeError, sizeof(__pyx_k__RuntimeError), 0, 0, 1, 1}, + {&__pyx_n_s__SCALElast, __pyx_k__SCALElast, sizeof(__pyx_k__SCALElast), 0, 0, 1, 1}, + {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1}, + {&__pyx_n_s____all__, __pyx_k____all__, sizeof(__pyx_k____all__), 0, 0, 1, 1}, + {&__pyx_n_s____init__, __pyx_k____init__, sizeof(__pyx_k____init__), 0, 0, 1, 1}, + {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1}, + {&__pyx_n_s___construct_delaunay, __pyx_k___construct_delaunay, sizeof(__pyx_k___construct_delaunay), 0, 0, 1, 1}, + {&__pyx_n_s___qhull_lock, __pyx_k___qhull_lock, sizeof(__pyx_k___qhull_lock), 0, 0, 1, 1}, + {&__pyx_n_s___transform, __pyx_k___transform, sizeof(__pyx_k___transform), 0, 0, 1, 1}, + {&__pyx_n_s___vertex_to_simplex, __pyx_k___vertex_to_simplex, sizeof(__pyx_k___vertex_to_simplex), 0, 0, 1, 1}, + {&__pyx_n_s__acquire, __pyx_k__acquire, sizeof(__pyx_k__acquire), 0, 0, 1, 1}, + {&__pyx_n_s__asanyarray, __pyx_k__asanyarray, sizeof(__pyx_k__asanyarray), 0, 0, 1, 1}, + {&__pyx_n_s__ascontiguousarray, __pyx_k__ascontiguousarray, sizeof(__pyx_k__ascontiguousarray), 0, 0, 1, 1}, + {&__pyx_n_s__astype, __pyx_k__astype, sizeof(__pyx_k__astype), 0, 0, 1, 1}, + {&__pyx_n_s__axis, __pyx_k__axis, sizeof(__pyx_k__axis), 0, 0, 1, 1}, + {&__pyx_n_s__base, __pyx_k__base, sizeof(__pyx_k__base), 0, 0, 1, 1}, + {&__pyx_n_s__bruteforce, __pyx_k__bruteforce, sizeof(__pyx_k__bruteforce), 0, 0, 1, 1}, + {&__pyx_n_s__buf, __pyx_k__buf, sizeof(__pyx_k__buf), 0, 0, 1, 1}, + {&__pyx_n_s__byteorder, __pyx_k__byteorder, sizeof(__pyx_k__byteorder), 0, 0, 1, 1}, + {&__pyx_n_s__convex_hull, __pyx_k__convex_hull, sizeof(__pyx_k__convex_hull), 0, 0, 1, 1}, + {&__pyx_n_s__data, __pyx_k__data, sizeof(__pyx_k__data), 0, 0, 1, 1}, + {&__pyx_n_s__descr, __pyx_k__descr, sizeof(__pyx_k__descr), 0, 0, 1, 1}, + {&__pyx_n_s__double, __pyx_k__double, sizeof(__pyx_k__double), 0, 0, 1, 1}, + {&__pyx_n_s__dtype, __pyx_k__dtype, sizeof(__pyx_k__dtype), 0, 0, 1, 1}, + {&__pyx_n_s__e, __pyx_k__e, sizeof(__pyx_k__e), 0, 0, 1, 1}, + {&__pyx_n_s__edge, __pyx_k__edge, sizeof(__pyx_k__edge), 0, 0, 1, 1}, + {&__pyx_n_s__empty, __pyx_k__empty, sizeof(__pyx_k__empty), 0, 0, 1, 1}, + {&__pyx_n_s__eps, __pyx_k__eps, sizeof(__pyx_k__eps), 0, 0, 1, 1}, + {&__pyx_n_s__equations, __pyx_k__equations, sizeof(__pyx_k__equations), 0, 0, 1, 1}, + {&__pyx_n_s__facet_id, __pyx_k__facet_id, sizeof(__pyx_k__facet_id), 0, 0, 1, 1}, + {&__pyx_n_s__facet_list, __pyx_k__facet_list, sizeof(__pyx_k__facet_list), 0, 0, 1, 1}, + {&__pyx_n_s__fields, __pyx_k__fields, sizeof(__pyx_k__fields), 0, 0, 1, 1}, + {&__pyx_n_s__fill, __pyx_k__fill, sizeof(__pyx_k__fill), 0, 0, 1, 1}, + {&__pyx_n_s__find_simplex, __pyx_k__find_simplex, sizeof(__pyx_k__find_simplex), 0, 0, 1, 1}, + {&__pyx_n_s__finfo, __pyx_k__finfo, sizeof(__pyx_k__finfo), 0, 0, 1, 1}, + {&__pyx_n_s__format, __pyx_k__format, sizeof(__pyx_k__format), 0, 0, 1, 1}, + {&__pyx_n_s__id, __pyx_k__id, sizeof(__pyx_k__id), 0, 0, 1, 1}, + {&__pyx_n_s__info, __pyx_k__info, sizeof(__pyx_k__info), 0, 0, 1, 1}, + {&__pyx_n_s__int, __pyx_k__int, sizeof(__pyx_k__int), 0, 0, 1, 1}, + {&__pyx_n_s__itemsize, __pyx_k__itemsize, sizeof(__pyx_k__itemsize), 0, 0, 1, 1}, + {&__pyx_n_s__last_high, __pyx_k__last_high, sizeof(__pyx_k__last_high), 0, 0, 1, 1}, + {&__pyx_n_s__last_low, __pyx_k__last_low, sizeof(__pyx_k__last_low), 0, 0, 1, 1}, + {&__pyx_n_s__last_newhigh, __pyx_k__last_newhigh, sizeof(__pyx_k__last_newhigh), 0, 0, 1, 1}, + {&__pyx_n_s__lift_points, __pyx_k__lift_points, sizeof(__pyx_k__lift_points), 0, 0, 1, 1}, + {&__pyx_n_s__max, __pyx_k__max, sizeof(__pyx_k__max), 0, 0, 1, 1}, + {&__pyx_n_s__max_bound, __pyx_k__max_bound, sizeof(__pyx_k__max_bound), 0, 0, 1, 1}, + {&__pyx_n_s__min, __pyx_k__min, sizeof(__pyx_k__min), 0, 0, 1, 1}, + {&__pyx_n_s__min_bound, __pyx_k__min_bound, sizeof(__pyx_k__min_bound), 0, 0, 1, 1}, + {&__pyx_n_s__names, __pyx_k__names, sizeof(__pyx_k__names), 0, 0, 1, 1}, + {&__pyx_n_s__nan, __pyx_k__nan, sizeof(__pyx_k__nan), 0, 0, 1, 1}, + {&__pyx_n_s__ndim, __pyx_k__ndim, sizeof(__pyx_k__ndim), 0, 0, 1, 1}, + {&__pyx_n_s__neighbors, __pyx_k__neighbors, sizeof(__pyx_k__neighbors), 0, 0, 1, 1}, + {&__pyx_n_s__next, __pyx_k__next, sizeof(__pyx_k__next), 0, 0, 1, 1}, + {&__pyx_n_s__normal, __pyx_k__normal, sizeof(__pyx_k__normal), 0, 0, 1, 1}, + {&__pyx_n_s__np, __pyx_k__np, sizeof(__pyx_k__np), 0, 0, 1, 1}, + {&__pyx_n_s__npoints, __pyx_k__npoints, sizeof(__pyx_k__npoints), 0, 0, 1, 1}, + {&__pyx_n_s__nsimplex, __pyx_k__nsimplex, sizeof(__pyx_k__nsimplex), 0, 0, 1, 1}, + {&__pyx_n_s__numpoints, __pyx_k__numpoints, sizeof(__pyx_k__numpoints), 0, 0, 1, 1}, + {&__pyx_n_s__numpy, __pyx_k__numpy, sizeof(__pyx_k__numpy), 0, 0, 1, 1}, + {&__pyx_n_s__obj, __pyx_k__obj, sizeof(__pyx_k__obj), 0, 0, 1, 1}, + {&__pyx_n_s__object, __pyx_k__object, sizeof(__pyx_k__object), 0, 0, 1, 1}, + {&__pyx_n_s__offset, __pyx_k__offset, sizeof(__pyx_k__offset), 0, 0, 1, 1}, + {&__pyx_n_s__p, __pyx_k__p, sizeof(__pyx_k__p), 0, 0, 1, 1}, + {&__pyx_n_s__paraboloid_scale, __pyx_k__paraboloid_scale, sizeof(__pyx_k__paraboloid_scale), 0, 0, 1, 1}, + {&__pyx_n_s__paraboloid_shift, __pyx_k__paraboloid_shift, sizeof(__pyx_k__paraboloid_shift), 0, 0, 1, 1}, + {&__pyx_n_s__plane_distance, __pyx_k__plane_distance, sizeof(__pyx_k__plane_distance), 0, 0, 1, 1}, + {&__pyx_n_s__point, __pyx_k__point, sizeof(__pyx_k__point), 0, 0, 1, 1}, + {&__pyx_n_s__points, __pyx_k__points, sizeof(__pyx_k__points), 0, 0, 1, 1}, + {&__pyx_n_s__prod, __pyx_k__prod, sizeof(__pyx_k__prod), 0, 0, 1, 1}, + {&__pyx_n_s__property, __pyx_k__property, sizeof(__pyx_k__property), 0, 0, 1, 1}, + {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1}, + {&__pyx_n_s__readonly, __pyx_k__readonly, sizeof(__pyx_k__readonly), 0, 0, 1, 1}, + {&__pyx_n_s__release, __pyx_k__release, sizeof(__pyx_k__release), 0, 0, 1, 1}, + {&__pyx_n_s__reshape, __pyx_k__reshape, sizeof(__pyx_k__reshape), 0, 0, 1, 1}, + {&__pyx_n_s__resize, __pyx_k__resize, sizeof(__pyx_k__resize), 0, 0, 1, 1}, + {&__pyx_n_s__self, __pyx_k__self, sizeof(__pyx_k__self), 0, 0, 1, 1}, + {&__pyx_n_s__shape, __pyx_k__shape, sizeof(__pyx_k__shape), 0, 0, 1, 1}, + {&__pyx_n_s__simplicial, __pyx_k__simplicial, sizeof(__pyx_k__simplicial), 0, 0, 1, 1}, + {&__pyx_n_s__start_edge, __pyx_k__start_edge, sizeof(__pyx_k__start_edge), 0, 0, 1, 1}, + {&__pyx_n_s__start_triangle, __pyx_k__start_triangle, sizeof(__pyx_k__start_triangle), 0, 0, 1, 1}, + {&__pyx_n_s__strides, __pyx_k__strides, sizeof(__pyx_k__strides), 0, 0, 1, 1}, + {&__pyx_n_s__suboffsets, __pyx_k__suboffsets, sizeof(__pyx_k__suboffsets), 0, 0, 1, 1}, + {&__pyx_n_s__sum, __pyx_k__sum, sizeof(__pyx_k__sum), 0, 0, 1, 1}, + {&__pyx_n_s__threading, __pyx_k__threading, sizeof(__pyx_k__threading), 0, 0, 1, 1}, + {&__pyx_n_s__transform, __pyx_k__transform, sizeof(__pyx_k__transform), 0, 0, 1, 1}, + {&__pyx_n_s__tri, __pyx_k__tri, sizeof(__pyx_k__tri), 0, 0, 1, 1}, + {&__pyx_n_s__triangle, __pyx_k__triangle, sizeof(__pyx_k__triangle), 0, 0, 1, 1}, + {&__pyx_n_s__tsearch, __pyx_k__tsearch, sizeof(__pyx_k__tsearch), 0, 0, 1, 1}, + {&__pyx_n_s__type_num, __pyx_k__type_num, sizeof(__pyx_k__type_num), 0, 0, 1, 1}, + {&__pyx_n_s__upperdelaunay, __pyx_k__upperdelaunay, sizeof(__pyx_k__upperdelaunay), 0, 0, 1, 1}, + {&__pyx_n_s__vertex, __pyx_k__vertex, sizeof(__pyx_k__vertex), 0, 0, 1, 1}, + {&__pyx_n_s__vertex2, __pyx_k__vertex2, sizeof(__pyx_k__vertex2), 0, 0, 1, 1}, + {&__pyx_n_s__vertex_to_simplex, __pyx_k__vertex_to_simplex, sizeof(__pyx_k__vertex_to_simplex), 0, 0, 1, 1}, + {&__pyx_n_s__vertices, __pyx_k__vertices, sizeof(__pyx_k__vertices), 0, 0, 1, 1}, + {&__pyx_n_s__x, __pyx_k__x, sizeof(__pyx_k__x), 0, 0, 1, 1}, + {&__pyx_n_s__xi, __pyx_k__xi, sizeof(__pyx_k__xi), 0, 0, 1, 1}, + {&__pyx_n_s__xrange, __pyx_k__xrange, sizeof(__pyx_k__xrange), 0, 0, 1, 1}, + {&__pyx_n_s__zeros, __pyx_k__zeros, sizeof(__pyx_k__zeros), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_object = __Pyx_GetName(__pyx_b, __pyx_n_s__object); if (!__pyx_builtin_object) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 804; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_property = __Pyx_GetName(__pyx_b, __pyx_n_s__property); if (!__pyx_builtin_property) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 155; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #if PY_MAJOR_VERSION >= 3 + __pyx_builtin_xrange = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_xrange) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #else + __pyx_builtin_xrange = __Pyx_GetName(__pyx_b, __pyx_n_s__xrange); if (!__pyx_builtin_xrange) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #endif + __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + return 0; + __pyx_L1_error:; + return -1; +} + +static int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_2 = PyInt_FromLong(2); if (unlikely(!__pyx_int_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_10 = PyInt_FromLong(10); if (unlikely(!__pyx_int_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_15 = PyInt_FromLong(15); if (unlikely(!__pyx_int_15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + return 0; + __pyx_L1_error:; + return -1; +} + +#if PY_MAJOR_VERSION < 3 +PyMODINIT_FUNC initqhull(void); +PyMODINIT_FUNC initqhull(void) +#else +PyMODINIT_FUNC PyInit_qhull(void); +PyMODINIT_FUNC PyInit_qhull(void) +#endif +{ + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + #if CYTHON_REFNANNY + void* __pyx_refnanny = NULL; + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); + if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); + } + __pyx_refnanny = __Pyx_RefNanny->SetupContext("PyMODINIT_FUNC PyInit_qhull(void)", __LINE__, __FILE__); + #endif + __pyx_init_filenames(); + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #if PY_MAJOR_VERSION < 3 + __pyx_empty_bytes = PyString_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #else + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #endif + + + #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + #ifdef WITH_THREAD + PyEval_InitThreads(); + #endif + #endif + + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4(__Pyx_NAMESTR("qhull"), __pyx_methods, __Pyx_DOCSTR(__pyx_k_18), 0, PYTHON_API_VERSION); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (!__pyx_m) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + #if PY_MAJOR_VERSION < 3 + Py_INCREF(__pyx_m); + #endif + __pyx_b = PyImport_AddModule(__Pyx_NAMESTR(__Pyx_BUILTIN_MODULE_NAME)); + if (!__pyx_b) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + if (__Pyx_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + + if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__pyx_module_is_main_scipy__spatial__qhull) { + if (__Pyx_SetAttrString(__pyx_m, "__name__", __pyx_n_s____main__) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + } + + if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + if (__Pyx_ExportFunction("_get_delaunay_info", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__get_delaunay_info, "__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *(PyObject *, int, int)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_barycentric_inside", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__barycentric_inside, "int (int, double *, double *, double *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_barycentric_coordinate_single", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__barycentric_coordinate_single, "void (int, double *, double *, double *, int)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_barycentric_coordinates", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__barycentric_coordinates, "void (int, double *, double *, double *)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_lift_point", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__lift_point, "void (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_distplane", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__distplane, "double (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int, double *)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_is_point_fully_outside", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__is_point_fully_outside, "int (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_find_simplex_bruteforce", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__find_simplex_bruteforce, "int (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_find_simplex_directed", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__find_simplex_directed, "int (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, int *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_find_simplex", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__find_simplex, "int (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, int *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_RidgeIter2D_init", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_init, "void (__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *, __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ExportFunction("_RidgeIter2D_next", (void (*)(void))__pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_next, "void (__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 848; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + + + __pyx_t_1 = __Pyx_Import(((PyObject *)__pyx_n_s__threading), 0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__threading, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_t_1 = __Pyx_Import(((PyObject *)__pyx_n_s__numpy), 0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__np, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_t_1 = PyList_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_1)); + __Pyx_INCREF(((PyObject *)__pyx_n_s__Delaunay)); + PyList_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_n_s__Delaunay)); + __Pyx_GIVEREF(((PyObject *)__pyx_n_s__Delaunay)); + __Pyx_INCREF(((PyObject *)__pyx_n_s__tsearch)); + PyList_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_n_s__tsearch)); + __Pyx_GIVEREF(((PyObject *)__pyx_n_s__tsearch)); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s____all__, ((PyObject *)__pyx_t_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__threading); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__Lock); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s___qhull_lock, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 804; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_1)); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 804; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_builtin_object); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_builtin_object); + __Pyx_GIVEREF(__pyx_builtin_object); + if (PyDict_SetItemString(((PyObject *)__pyx_t_1), "__doc__", ((PyObject *)__pyx_kp_s_19)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 804; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = __Pyx_CreateClass(__pyx_t_2, ((PyObject *)__pyx_t_1), __pyx_n_s__Delaunay, "scipy.spatial.qhull"); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 804; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_5scipy_7spatial_5qhull_8Delaunay___init__, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 863; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyMethod_New(__pyx_t_2, 0, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 863; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s____init__, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 863; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = PyCFunction_New(&__pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_transform, 0); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyMethod_New(__pyx_t_4, 0, __pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s__transform, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = __Pyx_GetName(__pyx_t_3, __pyx_n_s__transform); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyObject_Call(__pyx_builtin_property, __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 881; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s__transform, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 882; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_vertex_to_simplex, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 905; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyMethod_New(__pyx_t_2, 0, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 905; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s__vertex_to_simplex, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 905; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = __Pyx_GetName(__pyx_t_3, __pyx_n_s__vertex_to_simplex); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 905; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 904; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = PyObject_Call(__pyx_builtin_property, __pyx_t_2, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 904; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s__vertex_to_simplex, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 905; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = PyCFunction_New(&__pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_convex_hull, 0); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 935; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyMethod_New(__pyx_t_4, 0, __pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 935; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s__convex_hull, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 935; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = __Pyx_GetName(__pyx_t_3, __pyx_n_s__convex_hull); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 935; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 933; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyObject_Call(__pyx_builtin_property, __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 933; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s__convex_hull, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 935; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_k_9 = __pyx_t_2; + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_find_simplex, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyMethod_New(__pyx_t_2, 0, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s__find_simplex, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 981; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = PyCFunction_New(&__pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_plane_distance, 0); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyMethod_New(__pyx_t_4, 0, __pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s__plane_distance, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_5scipy_7spatial_5qhull_8Delaunay_lift_points, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1088; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyMethod_New(__pyx_t_2, 0, __pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1088; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_3, __pyx_n_s__lift_points, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1088; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__Delaunay, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 804; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; + + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + if (__pyx_m) { + __Pyx_AddTraceback("init scipy.spatial.qhull"); + Py_DECREF(__pyx_m); __pyx_m = 0; + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init scipy.spatial.qhull"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if PY_MAJOR_VERSION < 3 + return; + #else + return __pyx_m; + #endif +} + +static const char *__pyx_filenames[] = { + "qhull.pyx", + "numpy.pxd", +}; + + + +static void __pyx_init_filenames(void) { + __pyx_f = __pyx_filenames; +} + +static CYTHON_INLINE int __Pyx_IsLittleEndian(void) { + unsigned int n = 1; + return *(unsigned char*)(&n) != 0; +} + +typedef struct { + __Pyx_StructField root; + __Pyx_BufFmt_StackElem* head; + size_t fmt_offset; + int new_count, enc_count; + int is_complex; + char enc_type; + char packmode; +} __Pyx_BufFmt_Context; + +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + __Pyx_TypeInfo* type) { + stack[0].field = &ctx->root; + stack[0].parent_offset = 0; + ctx->root.type = type; + ctx->root.name = "buffer dtype"; + ctx->root.offset = 0; + ctx->head = stack; + ctx->head->field = &ctx->root; + ctx->fmt_offset = 0; + ctx->head->parent_offset = 0; + ctx->packmode = '@'; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->is_complex = 0; + while (type->typegroup == 'S') { + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = 0; + type = type->fields->type; + } +} + +static int __Pyx_BufFmt_ParseNumber(const char** ts) { + int count; + const char* t = *ts; + if (*t < '0' || *t > '9') { + return -1; + } else { + count = *t++ - '0'; + while (*t >= '0' && *t < '9') { + count *= 10; + count += *t++ - '0'; + } + } + *ts = t; + return count; +} + +static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { + char msg[] = {ch, 0}; + PyErr_Format(PyExc_ValueError, "Unexpected format string character: '%s'", msg); +} + +static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { + switch (ch) { + case 'b': return "'char'"; + case 'B': return "'unsigned char'"; + case 'h': return "'short'"; + case 'H': return "'unsigned short'"; + case 'i': return "'int'"; + case 'I': return "'unsigned int'"; + case 'l': return "'long'"; + case 'L': return "'unsigned long'"; + case 'q': return "'long long'"; + case 'Q': return "'unsigned long long'"; + case 'f': return (is_complex ? "'complex float'" : "'float'"); + case 'd': return (is_complex ? "'complex double'" : "'double'"); + case 'g': return (is_complex ? "'complex long double'" : "'long double'"); + case 'T': return "a struct"; + case 'O': return "Python object"; + case 'P': return "a pointer"; + case 0: return "end"; + default: return "unparseable format string"; + } +} + +static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': return 1; + case 'h': case 'H': return 2; + case 'i': case 'I': case 'l': case 'L': return 4; + case 'q': case 'Q': return 8; + case 'f': return (is_complex ? 8 : 4); + case 'd': return (is_complex ? 16 : 8); + case 'g': { + PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); + return 0; + } + case 'O': case 'P': return sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} + +static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { + switch (ch) { + case 'c': case 'b': case 'B': return 1; + case 'h': case 'H': return sizeof(short); + case 'i': case 'I': return sizeof(int); + case 'l': case 'L': return sizeof(long); + #ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(PY_LONG_LONG); + #endif + case 'f': return sizeof(float) * (is_complex ? 2 : 1); + case 'd': return sizeof(double) * (is_complex ? 2 : 1); + case 'g': return sizeof(long double) * (is_complex ? 2 : 1); + case 'O': case 'P': return sizeof(void*); + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} + +typedef struct { char c; short x; } __Pyx_st_short; +typedef struct { char c; int x; } __Pyx_st_int; +typedef struct { char c; long x; } __Pyx_st_long; +typedef struct { char c; float x; } __Pyx_st_float; +typedef struct { char c; double x; } __Pyx_st_double; +typedef struct { char c; long double x; } __Pyx_st_longdouble; +typedef struct { char c; void *x; } __Pyx_st_void_p; +#ifdef HAVE_LONG_LONG +typedef struct { char c; PY_LONG_LONG x; } __Pyx_s_long_long; +#endif + +static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': return 1; + case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); +#ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(__Pyx_s_long_long) - sizeof(PY_LONG_LONG); +#endif + case 'f': return sizeof(__Pyx_st_float) - sizeof(float); + case 'd': return sizeof(__Pyx_st_double) - sizeof(double); + case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} + +static size_t __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { + switch (ch) { + case 'c': case 'b': case 'h': case 'i': case 'l': case 'q': return 'I'; + case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U'; + case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R'); + case 'O': return 'O'; + case 'P': return 'P'; + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} + +static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { + if (ctx->head == NULL || ctx->head->field == &ctx->root) { + const char* expected; + const char* quote; + if (ctx->head == NULL) { + expected = "end"; + quote = ""; + } else { + expected = ctx->head->field->type->name; + quote = "'"; + } + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected %s%s%s but got %s", + quote, expected, quote, + __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); + } else { + __Pyx_StructField* field = ctx->head->field; + __Pyx_StructField* parent = (ctx->head - 1)->field; + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", + field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), + parent->type->name, field->name); + } +} + +static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { + char group; + size_t size, offset; + if (ctx->enc_type == 0) return 0; + group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); + do { + __Pyx_StructField* field = ctx->head->field; + __Pyx_TypeInfo* type = field->type; + + if (ctx->packmode == '@' || ctx->packmode == '^') { + size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); + } else { + size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); + } + if (ctx->packmode == '@') { + int align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); + int align_mod_offset; + if (align_at == 0) return -1; + align_mod_offset = ctx->fmt_offset % align_at; + if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; + } + + if (type->size != size || type->typegroup != group) { + if (type->typegroup == 'C' && type->fields != NULL) { + + size_t parent_offset = ctx->head->parent_offset + field->offset; + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = parent_offset; + continue; + } + + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + + offset = ctx->head->parent_offset + field->offset; + if (ctx->fmt_offset != offset) { + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch; next field is at offset %"PY_FORMAT_SIZE_T"d " + "but %"PY_FORMAT_SIZE_T"d expected", ctx->fmt_offset, offset); + return -1; + } + + ctx->fmt_offset += size; + + --ctx->enc_count; + + + while (1) { + if (field == &ctx->root) { + ctx->head = NULL; + if (ctx->enc_count != 0) { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + break; + } + ctx->head->field = ++field; + if (field->type == NULL) { + --ctx->head; + field = ctx->head->field; + continue; + } else if (field->type->typegroup == 'S') { + size_t parent_offset = ctx->head->parent_offset + field->offset; + if (field->type->fields->type == NULL) continue; + field = field->type->fields; + ++ctx->head; + ctx->head->field = field; + ctx->head->parent_offset = parent_offset; + break; + } else { + break; + } + } + } while (ctx->enc_count); + ctx->enc_type = 0; + ctx->is_complex = 0; + return 0; +} + +static int __Pyx_BufFmt_FirstPack(__Pyx_BufFmt_Context* ctx) { + if (ctx->enc_type != 0 || ctx->packmode != '@') { + PyErr_SetString(PyExc_ValueError, "Buffer packing mode currently only allowed at beginning of format string (this is a defect)"); + return -1; + } + return 0; +} + +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { + int got_Z = 0; + while (1) { + switch(*ts) { + case 0: + if (ctx->enc_type != 0 && ctx->head == NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + if (ctx->head != NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + return ts; + case ' ': + case 10: + case 13: + ++ts; + break; + case '<': + if (!__Pyx_IsLittleEndian()) { + PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); + return NULL; + } + if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL; + ctx->packmode = '='; + ++ts; + break; + case '>': + case '!': + if (__Pyx_IsLittleEndian()) { + PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); + return NULL; + } + if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL; + ctx->packmode = '='; + ++ts; + break; + case '=': + case '@': + case '^': + if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL; + ctx->packmode = *ts++; + break; + case 'T': + { + int i; + const char* ts_after_sub; + int struct_count = ctx->new_count; + ctx->new_count = 1; + ++ts; + if (*ts != '{') { + PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); + return NULL; + } + ++ts; + ts_after_sub = ts; + for (i = 0; i != struct_count; ++i) { + ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); + if (!ts_after_sub) return NULL; + } + ts = ts_after_sub; + } + break; + case '}': + ++ts; + return ts; + case 'x': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->fmt_offset += ctx->new_count; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ++ts; + break; + case 'Z': + got_Z = 1; + ++ts; + if (*ts != 'f' && *ts != 'd' && *ts != 'g') { + __Pyx_BufFmt_RaiseUnexpectedChar('Z'); + return NULL; + } + case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': + case 'l': case 'L': case 'q': case 'Q': + case 'f': case 'd': case 'g': + case 'O': + if (ctx->enc_type == *ts && got_Z == ctx->is_complex) { + + ctx->enc_count += ctx->new_count; + } else { + + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_count = ctx->new_count; + ctx->enc_type = *ts; + ctx->is_complex = got_Z; + } + ++ts; + ctx->new_count = 1; + got_Z = 0; + break; + default: + { + ctx->new_count = __Pyx_BufFmt_ParseNumber(&ts); + if (ctx->new_count == -1) { + char msg[2] = { *ts, 0 }; + PyErr_Format(PyExc_ValueError, + "Does not understand character buffer dtype format string ('%s')", msg); + return NULL; + } + } + + } + } +} + +static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) { + buf->buf = NULL; + buf->obj = NULL; + buf->strides = __Pyx_zeros; + buf->shape = __Pyx_zeros; + buf->suboffsets = __Pyx_minusones; +} + +static int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) { + if (obj == Py_None) { + __Pyx_ZeroBuffer(buf); + return 0; + } + buf->buf = NULL; + if (__Pyx_GetBuffer(obj, buf, flags) == -1) goto fail; + if (buf->ndim != nd) { + PyErr_Format(PyExc_ValueError, + "Buffer has wrong number of dimensions (expected %d, got %d)", + nd, buf->ndim); + goto fail; + } + if (!cast) { + __Pyx_BufFmt_Context ctx; + __Pyx_BufFmt_Init(&ctx, stack, dtype); + if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; + } + if ((unsigned)buf->itemsize != dtype->size) { + PyErr_Format(PyExc_ValueError, + "Item size of buffer (%"PY_FORMAT_SIZE_T"d byte%s) does not match size of '%s' (%"PY_FORMAT_SIZE_T"d byte%s)", + buf->itemsize, (buf->itemsize > 1) ? "s" : "", + dtype->name, + dtype->size, (dtype->size > 1) ? "s" : ""); + goto fail; + } + if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; + return 0; +fail:; + __Pyx_ZeroBuffer(buf); + return -1; +} + +static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { + if (info->buf == NULL) return; + if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; + __Pyx_ReleaseBuffer(info); +} + +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + if (unlikely(!type)) { + PyErr_Format(PyExc_SystemError, "Missing type object"); + return 0; + } + if (likely(PyObject_TypeCheck(obj, type))) + return 1; + PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", + Py_TYPE(obj)->tp_name, type->tp_name); + return 0; +} + +static void __Pyx_RaiseBufferFallbackError(void) { + PyErr_Format(PyExc_ValueError, + "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!"); +} + + +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { + PyErr_Format(PyExc_ValueError, + #if PY_VERSION_HEX < 0x02050000 + "need more than %d value%s to unpack", (int)index, + #else + "need more than %zd value%s to unpack", index, + #endif + (index == 1) ? "" : "s"); +} + +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void) { + PyErr_SetString(PyExc_ValueError, "too many values to unpack"); +} + +static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) { + PyObject *item; + if (!(item = PyIter_Next(iter))) { + if (!PyErr_Occurred()) { + __Pyx_RaiseNeedMoreValuesError(index); + } + } + return item; +} + +static int __Pyx_EndUnpack(PyObject *iter) { + PyObject *item; + if ((item = PyIter_Next(iter))) { + Py_DECREF(item); + __Pyx_RaiseTooManyValuesError(); + return -1; + } + else if (!PyErr_Occurred()) + return 0; + else + return -1; +} + +static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyThreadState *tstate = PyThreadState_GET(); + + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} + +static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) { + PyThreadState *tstate = PyThreadState_GET(); + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} + + +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AS_STRING(kw_name)); + #endif +} + +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *number, *more_or_less; + + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + number = (num_expected == 1) ? "" : "s"; + PyErr_Format(PyExc_TypeError, + #if PY_VERSION_HEX < 0x02050000 + "%s() takes %s %d positional argument%s (%d given)", + #else + "%s() takes %s %zd positional argument%s (%zd given)", + #endif + func_name, more_or_less, num_expected, number, num_found); +} + +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + } else { + #if PY_MAJOR_VERSION < 3 + if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) { + #else + if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) { + #endif + goto invalid_keyword_type; + } else { + for (name = first_kw_arg; *name; name++) { + #if PY_MAJOR_VERSION >= 3 + if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && + PyUnicode_Compare(**name, key) == 0) break; + #else + if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && + _PyString_Eq(**name, key)) break; + #endif + } + if (*name) { + values[name-argnames] = value; + } else { + + for (name=argnames; name != first_kw_arg; name++) { + if (**name == key) goto arg_passed_twice; + #if PY_MAJOR_VERSION >= 3 + if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && + PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice; + #else + if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && + _PyString_Eq(**name, key)) goto arg_passed_twice; + #endif + } + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + } + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, **name); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%s() got an unexpected keyword argument '%s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} +static void __Pyx_RaiseBufferIndexError(int axis) { + PyErr_Format(PyExc_IndexError, + "Out of bounds on buffer access (axis %d)", axis); +} + + + +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); +} + +static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) { + if (t == Py_None) { + __Pyx_RaiseNoneNotIterableError(); + } else if (PyTuple_GET_SIZE(t) < index) { + __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t)); + } else { + __Pyx_RaiseTooManyValuesError(); + } +} + +static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, + const char *name, int exact) +{ + if (!type) { + PyErr_Format(PyExc_SystemError, "Missing type object"); + return 0; + } + if (none_allowed && obj == Py_None) return 1; + else if (exact) { + if (Py_TYPE(obj) == type) return 1; + } + else { + if (PyObject_TypeCheck(obj, type)) return 1; + } + PyErr_Format(PyExc_TypeError, + "Argument '%s' has incorrect type (expected %s, got %s)", + name, type->tp_name, Py_TYPE(obj)->tp_name); + return 0; +} + +#if PY_MAJOR_VERSION < 3 +static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { + #if PY_VERSION_HEX >= 0x02060000 + if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER) + return PyObject_GetBuffer(obj, view, flags); + #endif + if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pf_5numpy_7ndarray___getbuffer__(obj, view, flags); + else { + PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name); + return -1; + } +} + +static void __Pyx_ReleaseBuffer(Py_buffer *view) { + PyObject* obj = view->obj; + if (obj) { +if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pf_5numpy_7ndarray___releasebuffer__(obj, view); + Py_DECREF(obj); + view->obj = NULL; + } +} + +#endif + +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) { + PyObject *__import__ = 0; + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + __import__ = __Pyx_GetAttrString(__pyx_b, "__import__"); + if (!__import__) + goto bad; + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(__pyx_m); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + module = PyObject_CallFunctionObjArgs(__import__, + name, global_dict, empty_dict, list, NULL); +bad: + Py_XDECREF(empty_list); + Py_XDECREF(__import__); + Py_XDECREF(empty_dict); + return module; +} + +static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) { + PyObject *result; + result = PyObject_GetAttr(dict, name); + if (!result) + PyErr_SetObject(PyExc_NameError, name); + return result; +} + +static PyObject *__Pyx_CreateClass( + PyObject *bases, PyObject *dict, PyObject *name, const char *modname) +{ + PyObject *py_modname; + PyObject *result = 0; + + #if PY_MAJOR_VERSION < 3 + py_modname = PyString_FromString(modname); + #else + py_modname = PyUnicode_FromString(modname); + #endif + if (!py_modname) + goto bad; + if (PyDict_SetItemString(dict, "__module__", py_modname) < 0) + goto bad; + #if PY_MAJOR_VERSION < 3 + result = PyClass_New(bases, dict, name); + #else + result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL); + #endif +bad: + Py_XDECREF(py_modname); + return result; +} + +#if PY_MAJOR_VERSION < 3 +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { + Py_XINCREF(type); + Py_XINCREF(value); + Py_XINCREF(tb); + + if (tb == Py_None) { + Py_DECREF(tb); + tb = 0; + } + else if (tb != NULL && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + + if (value == NULL) { + value = Py_None; + Py_INCREF(value); + } + #if PY_VERSION_HEX < 0x02050000 + if (!PyClass_Check(type)) + #else + if (!PyType_Check(type)) + #endif + { + + if (value != Py_None) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + + Py_DECREF(value); + value = type; + #if PY_VERSION_HEX < 0x02050000 + if (PyInstance_Check(type)) { + type = (PyObject*) ((PyInstanceObject*)type)->in_class; + Py_INCREF(type); + } + else { + type = 0; + PyErr_SetString(PyExc_TypeError, + "raise: exception must be an old-style class or instance"); + goto raise_error; + } + #else + type = (PyObject*) Py_TYPE(type); + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + #endif + } + + __Pyx_ErrRestore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} + +#else + +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (!PyExceptionClass_Check(type)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + + PyErr_SetObject(type, value); + + if (tb) { + PyThreadState *tstate = PyThreadState_GET(); + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } + } + +bad: + return; +} +#endif + +static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_npy_intp(npy_intp val) { + const npy_intp neg_one = (npy_intp)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(npy_intp) < sizeof(long)) { + return PyInt_FromLong((long)val); + } else if (sizeof(npy_intp) == sizeof(long)) { + if (is_unsigned) + return PyLong_FromUnsignedLong((unsigned long)val); + else + return PyInt_FromLong((long)val); + } else { + if (is_unsigned) + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val); + else + return PyLong_FromLongLong((PY_LONG_LONG)val); + } +} + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return ::std::complex< float >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return x + y*(__pyx_t_float_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + __pyx_t_float_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +#if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eqf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sumf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_difff(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prodf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quotf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + float denom = b.real * b.real + b.imag * b.imag; + z.real = (a.real * b.real + a.imag * b.imag) / denom; + z.imag = (a.imag * b.real - a.real * b.imag) / denom; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_negf(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zerof(__pyx_t_float_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conjf(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + +#endif + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return ::std::complex< double >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return x + y*(__pyx_t_double_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + __pyx_t_double_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +#if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eq(__pyx_t_double_complex a, __pyx_t_double_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + double denom = b.real * b.real + b.imag * b.imag; + z.real = (a.real * b.real + a.imag * b.imag) / denom; + z.imag = (a.imag * b.real - a.real * b.imag) / denom; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero(__pyx_t_double_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + +#endif + +static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject* x) { + const unsigned char neg_one = (unsigned char)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(unsigned char) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(unsigned char)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to unsigned char" : + "value too large to convert to unsigned char"); + } + return (unsigned char)-1; + } + return (unsigned char)val; + } + return (unsigned char)__Pyx_PyInt_AsUnsignedLong(x); +} + +static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject* x) { + const unsigned short neg_one = (unsigned short)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(unsigned short) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(unsigned short)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to unsigned short" : + "value too large to convert to unsigned short"); + } + return (unsigned short)-1; + } + return (unsigned short)val; + } + return (unsigned short)__Pyx_PyInt_AsUnsignedLong(x); +} + +static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject* x) { + const unsigned int neg_one = (unsigned int)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(unsigned int) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(unsigned int)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to unsigned int" : + "value too large to convert to unsigned int"); + } + return (unsigned int)-1; + } + return (unsigned int)val; + } + return (unsigned int)__Pyx_PyInt_AsUnsignedLong(x); +} + +static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject* x) { + const char neg_one = (char)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(char) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(char)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to char" : + "value too large to convert to char"); + } + return (char)-1; + } + return (char)val; + } + return (char)__Pyx_PyInt_AsLong(x); +} + +static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject* x) { + const short neg_one = (short)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(short) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(short)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to short" : + "value too large to convert to short"); + } + return (short)-1; + } + return (short)val; + } + return (short)__Pyx_PyInt_AsLong(x); +} + +static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject* x) { + const int neg_one = (int)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(int) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(int)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to int" : + "value too large to convert to int"); + } + return (int)-1; + } + return (int)val; + } + return (int)__Pyx_PyInt_AsLong(x); +} + +static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject* x) { + const signed char neg_one = (signed char)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(signed char) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(signed char)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to signed char" : + "value too large to convert to signed char"); + } + return (signed char)-1; + } + return (signed char)val; + } + return (signed char)__Pyx_PyInt_AsSignedLong(x); +} + +static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject* x) { + const signed short neg_one = (signed short)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(signed short) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(signed short)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to signed short" : + "value too large to convert to signed short"); + } + return (signed short)-1; + } + return (signed short)val; + } + return (signed short)__Pyx_PyInt_AsSignedLong(x); +} + +static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject* x) { + const signed int neg_one = (signed int)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(signed int) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(signed int)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to signed int" : + "value too large to convert to signed int"); + } + return (signed int)-1; + } + return (signed int)val; + } + return (signed int)__Pyx_PyInt_AsSignedLong(x); +} + +static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) { + const unsigned long neg_one = (unsigned long)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to unsigned long"); + return (unsigned long)-1; + } + return (unsigned long)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to unsigned long"); + return (unsigned long)-1; + } + return PyLong_AsUnsignedLong(x); + } else { + return PyLong_AsLong(x); + } + } else { + unsigned long val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (unsigned long)-1; + val = __Pyx_PyInt_AsUnsignedLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject* x) { + const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to unsigned PY_LONG_LONG"); + return (unsigned PY_LONG_LONG)-1; + } + return (unsigned PY_LONG_LONG)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to unsigned PY_LONG_LONG"); + return (unsigned PY_LONG_LONG)-1; + } + return PyLong_AsUnsignedLongLong(x); + } else { + return PyLong_AsLongLong(x); + } + } else { + unsigned PY_LONG_LONG val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (unsigned PY_LONG_LONG)-1; + val = __Pyx_PyInt_AsUnsignedLongLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) { + const long neg_one = (long)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long)-1; + } + return (long)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long)-1; + } + return PyLong_AsUnsignedLong(x); + } else { + return PyLong_AsLong(x); + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (long)-1; + val = __Pyx_PyInt_AsLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) { + const PY_LONG_LONG neg_one = (PY_LONG_LONG)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to PY_LONG_LONG"); + return (PY_LONG_LONG)-1; + } + return (PY_LONG_LONG)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to PY_LONG_LONG"); + return (PY_LONG_LONG)-1; + } + return PyLong_AsUnsignedLongLong(x); + } else { + return PyLong_AsLongLong(x); + } + } else { + PY_LONG_LONG val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (PY_LONG_LONG)-1; + val = __Pyx_PyInt_AsLongLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) { + const signed long neg_one = (signed long)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to signed long"); + return (signed long)-1; + } + return (signed long)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to signed long"); + return (signed long)-1; + } + return PyLong_AsUnsignedLong(x); + } else { + return PyLong_AsLong(x); + } + } else { + signed long val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (signed long)-1; + val = __Pyx_PyInt_AsSignedLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject* x) { + const signed PY_LONG_LONG neg_one = (signed PY_LONG_LONG)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to signed PY_LONG_LONG"); + return (signed PY_LONG_LONG)-1; + } + return (signed PY_LONG_LONG)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to signed PY_LONG_LONG"); + return (signed PY_LONG_LONG)-1; + } + return PyLong_AsUnsignedLongLong(x); + } else { + return PyLong_AsLongLong(x); + } + } else { + signed PY_LONG_LONG val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (signed PY_LONG_LONG)-1; + val = __Pyx_PyInt_AsSignedLongLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static void __Pyx_WriteUnraisable(const char *name) { + PyObject *old_exc, *old_val, *old_tb; + PyObject *ctx; + __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); + #if PY_MAJOR_VERSION < 3 + ctx = PyString_FromString(name); + #else + ctx = PyUnicode_FromString(name); + #endif + __Pyx_ErrRestore(old_exc, old_val, old_tb); + if (!ctx) { + PyErr_WriteUnraisable(Py_None); + } else { + PyErr_WriteUnraisable(ctx); + Py_DECREF(ctx); + } +} + +static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig) { + PyObject *d = 0; + PyObject *cobj = 0; + union { + void (*fp)(void); + void *p; + } tmp; + + d = PyObject_GetAttrString(__pyx_m, (char *)"__pyx_capi__"); + if (!d) { + PyErr_Clear(); + d = PyDict_New(); + if (!d) + goto bad; + Py_INCREF(d); + if (PyModule_AddObject(__pyx_m, (char *)"__pyx_capi__", d) < 0) + goto bad; + } + tmp.fp = f; +#if PY_VERSION_HEX < 0x03010000 + cobj = PyCObject_FromVoidPtrAndDesc(tmp.p, (void *)sig, 0); +#else + cobj = PyCapsule_New(tmp.p, sig, 0); +#endif + if (!cobj) + goto bad; + if (PyDict_SetItemString(d, name, cobj) < 0) + goto bad; + Py_DECREF(cobj); + Py_DECREF(d); + return 0; +bad: + Py_XDECREF(cobj); + Py_XDECREF(d); + return -1; +} + +#ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, + long size, int strict) +{ + PyObject *py_module = 0; + PyObject *result = 0; + PyObject *py_name = 0; + char warning[200]; + + py_module = __Pyx_ImportModule(module_name); + if (!py_module) + goto bad; + #if PY_MAJOR_VERSION < 3 + py_name = PyString_FromString(class_name); + #else + py_name = PyUnicode_FromString(class_name); + #endif + if (!py_name) + goto bad; + result = PyObject_GetAttr(py_module, py_name); + Py_DECREF(py_name); + py_name = 0; + Py_DECREF(py_module); + py_module = 0; + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%s.%s is not a type object", + module_name, class_name); + goto bad; + } + if (!strict && ((PyTypeObject *)result)->tp_basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility", + module_name, class_name); + PyErr_WarnEx(NULL, warning, 0); + } + else if (((PyTypeObject *)result)->tp_basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%s.%s has the wrong size, try recompiling", + module_name, class_name); + goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(py_module); + Py_XDECREF(result); + return 0; +} +#endif + +#ifndef __PYX_HAVE_RT_ImportModule +#define __PYX_HAVE_RT_ImportModule +static PyObject *__Pyx_ImportModule(const char *name) { + PyObject *py_name = 0; + PyObject *py_module = 0; + + #if PY_MAJOR_VERSION < 3 + py_name = PyString_FromString(name); + #else + py_name = PyUnicode_FromString(name); + #endif + if (!py_name) + goto bad; + py_module = PyImport_Import(py_name); + Py_DECREF(py_name); + return py_module; +bad: + Py_XDECREF(py_name); + return 0; +} +#endif + +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" + +static void __Pyx_AddTraceback(const char *funcname) { + PyObject *py_srcfile = 0; + PyObject *py_funcname = 0; + PyObject *py_globals = 0; + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + + #if PY_MAJOR_VERSION < 3 + py_srcfile = PyString_FromString(__pyx_filename); + #else + py_srcfile = PyUnicode_FromString(__pyx_filename); + #endif + if (!py_srcfile) goto bad; + if (__pyx_clineno) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + #else + py_funcname = PyUnicode_FromString(funcname); + #endif + } + if (!py_funcname) goto bad; + py_globals = PyModule_GetDict(__pyx_m); + if (!py_globals) goto bad; + py_code = PyCode_New( + 0, + #if PY_MAJOR_VERSION >= 3 + 0, + #endif + 0, + 0, + 0, + __pyx_empty_bytes, + __pyx_empty_tuple, + __pyx_empty_tuple, + __pyx_empty_tuple, + __pyx_empty_tuple, + __pyx_empty_tuple, + py_srcfile, + py_funcname, + __pyx_lineno, + __pyx_empty_bytes + ); + if (!py_code) goto bad; + py_frame = PyFrame_New( + PyThreadState_GET(), + py_code, + py_globals, + 0 + ); + if (!py_frame) goto bad; + py_frame->f_lineno = __pyx_lineno; + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_srcfile); + Py_XDECREF(py_funcname); + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { + while (t->p) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + ++t; + } + return 0; +} + + + +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + if (x == Py_True) return 1; + else if ((x == Py_False) | (x == Py_None)) return 0; + else return PyObject_IsTrue(x); +} + +static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) { + PyNumberMethods *m; + const char *name = NULL; + PyObject *res = NULL; +#if PY_VERSION_HEX < 0x03000000 + if (PyInt_Check(x) || PyLong_Check(x)) +#else + if (PyLong_Check(x)) +#endif + return Py_INCREF(x), x; + m = Py_TYPE(x)->tp_as_number; +#if PY_VERSION_HEX < 0x03000000 + if (m && m->nb_int) { + name = "int"; + res = PyNumber_Int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = PyNumber_Long(x); + } +#else + if (m && m->nb_int) { + name = "int"; + res = PyNumber_Long(x); + } +#endif + if (res) { +#if PY_VERSION_HEX < 0x03000000 + if (!PyInt_Check(res) && !PyLong_Check(res)) { +#else + if (!PyLong_Check(res)) { +#endif + PyErr_Format(PyExc_TypeError, + "__%s__ returned non-%s (type %.200s)", + name, name, Py_TYPE(res)->tp_name); + Py_DECREF(res); + return NULL; + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} + +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject* x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} + +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { +#if PY_VERSION_HEX < 0x02050000 + if (ival <= LONG_MAX) + return PyInt_FromLong((long)ival); + else { + unsigned char *bytes = (unsigned char *) &ival; + int one = 1; int little = (int)*(unsigned char*)&one; + return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0); + } +#else + return PyInt_FromSize_t(ival); +#endif +} + +static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) { + unsigned PY_LONG_LONG val = __Pyx_PyInt_AsUnsignedLongLong(x); + if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) { + return (size_t)-1; + } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) { + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to size_t"); + return (size_t)-1; + } + return (size_t)val; +} + + +#endif From scipy-svn at scipy.org Tue Aug 31 17:57:20 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 16:57:20 -0500 (CDT) Subject: [Scipy-svn] r6655 - in trunk/scipy/interpolate: . tests Message-ID: <20100831215720.6682939CD13@scipy.org> Author: ptvirtan Date: 2010-08-31 16:57:20 -0500 (Tue, 31 Aug 2010) New Revision: 6655 Added: trunk/scipy/interpolate/generate_interpnd.py trunk/scipy/interpolate/interpnd.pyx trunk/scipy/interpolate/interpnd_info.py trunk/scipy/interpolate/tests/test_interpnd.py Modified: trunk/scipy/interpolate/SConscript trunk/scipy/interpolate/setup.py Log: interpolate: implement N-dimensional interpolation routines Implement the following N-dimensional interpolation routines: - Linear barycentric interpolation (N-d) - Clough-Tocher cubic interpolation (2-d only) These make use of the new Delaunay tesselation routines in scipy.spatial. Modified: trunk/scipy/interpolate/SConscript =================================================================== --- trunk/scipy/interpolate/SConscript 2010-08-31 21:56:34 UTC (rev 6654) +++ trunk/scipy/interpolate/SConscript 2010-08-31 21:57:20 UTC (rev 6655) @@ -44,3 +44,6 @@ # Build _interpolate env.NumpyPythonExtension('_interpolate', source = 'src/_interpolate.cpp', CXXFILESUFFIX = ".cpp") + +# Build interpnd +env.NumpyPythonExtension('interpnd', source = 'interpnd.c') Added: trunk/scipy/interpolate/generate_interpnd.py =================================================================== --- trunk/scipy/interpolate/generate_interpnd.py (rev 0) +++ trunk/scipy/interpolate/generate_interpnd.py 2010-08-31 21:57:20 UTC (rev 6655) @@ -0,0 +1,41 @@ +#!/usr/bin/env python +import tempfile +import subprocess +import os +import sys +import re +import shutil + +from mako.template import Template + +f = open('interpnd.pyx', 'r') +template = f.read() +f.close() + +tmp_dir = tempfile.mkdtemp() +try: + # Run templating engine + fn = os.path.join(tmp_dir, 'interpnd.pyx') + f = open(fn, 'w') + f.write(Template(template).render()) + f.close() + + # Run Cython + dst_fn = os.path.join(tmp_dir, 'interpnd.c') + ret = subprocess.call(['cython', '-I', '../..', '-o', dst_fn, fn]) + if ret != 0: + sys.exit(ret) + + # Strip comments + f = open(dst_fn, 'r') + text = f.read() + f.close() + + r = re.compile(r'/\*(.*?)\*/', re.S) + + text = r.sub('', text) + f = open('interpnd.c', 'w') + f.write(text) + f.close() +finally: + shutil.rmtree(tmp_dir) Property changes on: trunk/scipy/interpolate/generate_interpnd.py ___________________________________________________________________ Name: svn:executable + * Added: trunk/scipy/interpolate/interpnd.pyx =================================================================== --- trunk/scipy/interpolate/interpnd.pyx (rev 0) +++ trunk/scipy/interpolate/interpnd.pyx 2010-08-31 21:57:20 UTC (rev 6655) @@ -0,0 +1,883 @@ +""" +Simple N-D interpolation + +.. versionadded:: 0.9 + +""" +# +# Copyright (C) Pauli Virtanen, 2010. +# +# Distributed under the same BSD license as Scipy. +# + +# +# Note: this file should be run through the Mako template engine before +# feeding it to Cython. +# +# Run ``generate_qhull.py`` to regenerate the ``qhull.c`` file +# + +import numpy as np +cimport numpy as np + +import scipy.spatial.qhull as qhull +cimport scipy.spatial.qhull as qhull + +cimport cython + +import warnings + +#------------------------------------------------------------------------------ +# Numpy etc. +#------------------------------------------------------------------------------ + +cdef extern from "stdlib.h": + void *malloc(int size) nogil + void free(void *ptr) nogil + +cdef extern from "math.h": + double sqrt(double x) nogil + double fmax(double a, double b) nogil + double fabs(double a) nogil + +cdef extern from "numpy/ndarraytypes.h": + cdef enum: + NPY_MAXDIMS + + +#------------------------------------------------------------------------------ +# Interpolator base class +#------------------------------------------------------------------------------ + +class NDInterpolatorBase(object): + """ + Common routines for interpolators. + + .. versionadded:: 0.9 + + """ + + def __init__(self, points, values, fill_value=np.nan, ndim=None): + """ + Check shape of points and values arrays, and reshape values to + (npoints, nvalues). Ensure the `points` and values arrays are + C-contiguous, and of correct type. + """ + points = _ndim_coords_from_arrays(points) + + self._check_init_shape(points, values, ndim=ndim) + + points = np.ascontiguousarray(points.astype(np.double)) + values = np.ascontiguousarray(values) + + self.values_shape = values.shape[1:] + if values.ndim == 1: + self.values = values[:,None] + elif values.ndim == 2: + self.values = values + else: + self.values = values.reshape(values.shape[0], + np.prod(values.shape[1:])) + + # Complex or real? + self.is_complex = np.issubdtype(self.values.dtype, np.complexfloating) + if self.is_complex: + self.values = self.values.astype(np.complex) + self.fill_value = complex(fill_value) + else: + self.values = self.values.astype(np.double) + self.fill_value = float(fill_value) + + self.points = points + + def _check_init_shape(self, points, values, ndim=None): + """ + Check shape of points and values arrays + + """ + if values.shape[0] != points.shape[0]: + raise ValueError("different number of values and points") + if points.ndim != 2: + raise ValueError("invalid shape for input data points") + if points.shape[1] < 2: + raise ValueError("input data must be at least 2-D") + if ndim is not None and points.shape[1] != ndim: + raise ValueError("this mode of interpolation available only for " + "%-D data" % ndim) + + def _check_call_shape(self, xi): + xi = np.asanyarray(xi) + if xi.shape[-1] != self.points.shape[1]: + raise ValueError("number of dimensions in xi does not match x") + return xi + + def __call__(self, xi): + """ + interpolator(xi) + + Evaluate interpolator at given points. + + Parameters + ---------- + xi : ndarray of float, shape (..., ndim) + Points where to interpolate data at. + + """ + xi = _ndim_coords_from_arrays(xi) + xi = self._check_call_shape(xi) + xi = np.ascontiguousarray(xi.astype(np.double)) + shape = xi.shape + xi = xi.reshape(np.prod(shape[:-1]), shape[-1]) + + if self.is_complex: + r = self._evaluate_complex(xi) + else: + r = self._evaluate_double(xi) + + return r.reshape(shape[:-1] + self.values_shape) + +def _ndim_coords_from_arrays(points): + """ + Convert a tuple of coordinate arrays to a (..., ndim)-shaped array. + + """ + if (isinstance(points, tuple) or isinstance(points, list)) \ + and points and isinstance(points[0], np.ndarray): + p = map(np.asanyarray, points) + for j in xrange(1, len(p)): + if p[j].shape != p[0].shape: + raise ValueError("coordinate arrays do not have the same shape") + points = np.empty(p[0].shape + (len(points),), dtype=float) + for j, item in enumerate(p): + points[...,j] = item + else: + points = np.asanyarray(points) + return points + +#------------------------------------------------------------------------------ +# Linear interpolation in N-D +#------------------------------------------------------------------------------ + +class LinearNDInterpolator(NDInterpolatorBase): + """ + LinearNDInterpolator(points, values) + + Piecewise linear interpolant in N dimensions. + + .. versionadded:: 0.9 + + Parameters + ---------- + points : ndarray of floats, shape (npoints, ndims) + Data point coordinates. + values : ndarray of float or complex, shape (npoints, ...) + Data values. + fill_value : float, optional + Value used to fill in for requested points outside of the + convex hull of the input points. If not provided, then + the default is ``nan``. + + Notes + ----- + The interpolant is constructed by triangulating the input data + with Qhull [Qhull]_, and on each triangle performing linear + barycentric interpolation. + + References + ---------- + .. [Qhull] http://www.qhull.org/ + + """ + + def __init__(self, points, values, fill_value=np.nan): + NDInterpolatorBase.__init__(self, points, values, fill_value=fill_value) + self.tri = qhull.Delaunay(points) + +% for DTYPE, CDTYPE in zip(["double", "complex"], ["double", "double complex"]): + @cython.boundscheck(False) + def _evaluate_${DTYPE}(self, np.ndarray[np.double_t, ndim=2] xi): + cdef np.ndarray[np.${DTYPE}_t, ndim=2] values = self.values + cdef np.ndarray[np.${DTYPE}_t, ndim=2] out + cdef np.ndarray[np.double_t, ndim=2] points = self.points + cdef np.ndarray[np.int_t, ndim=2] vertices = self.tri.vertices + cdef double c[NPY_MAXDIMS] + cdef ${CDTYPE} fill_value + cdef int i, j, k, m, ndim, isimplex, inside, start, nvalues + cdef qhull.DelaunayInfo_t *info + + ndim = xi.shape[1] + start = 0 + fill_value = self.fill_value + + info = qhull._get_delaunay_info(self.tri, 1, 0) + + out = np.zeros((xi.shape[0], self.values.shape[1]), dtype=np.${DTYPE}) + nvalues = out.shape[1] + + eps = np.finfo(np.double).eps * 100 + + with nogil: + for i in xrange(xi.shape[0]): + + # 1) Find the simplex + + isimplex = qhull._find_simplex(info, c, + (xi.data) + i*ndim, + &start, eps) + + # 2) Linear barycentric interpolation + + if isimplex == -1: + # don't extrapolate + for k in xrange(nvalues): +% if DTYPE == "double": + out[i,k] = fill_value +% else: + out[i,k].real = fill_value.real + out[i,k].imag = fill_value.imag +% endif + continue + + for k in xrange(nvalues): +% if DTYPE == "double": + out[i,k] = 0 +% else: + out[i,k].real = 0 + out[i,k].imag = 0 +% endif + + for j in xrange(ndim+1): + for k in xrange(nvalues): + m = vertices[isimplex,j] +% if DTYPE == "double": + out[i,k] += c[j] * values[m,k] +% else: + out[i,k].real += c[j] * values[m, k].real + out[i,k].imag += c[j] * values[m, k].imag +% endif + + free(info) + return out +% endfor + + +#------------------------------------------------------------------------------ +# Gradient estimation in 2D +#------------------------------------------------------------------------------ + +class GradientEstimationWarning(Warning): + pass + + at cython.cdivision(True) +cdef int _estimate_gradients_2d_global(qhull.DelaunayInfo_t *d, double *data, + int maxiter, double tol, + double *y) nogil: + """ + Estimate gradients of a function at the vertices of a 2d triangulation. + + Parameters + ---------- + info : input + Triangulation in 2D + data : input + Function values at the vertices + maxiter : input + Maximum number of Gauss-Seidel iterations + tol : input + Absolute / relative stop tolerance + y : output, shape (npoints, 2) + Derivatives [F_x, F_y] at the vertices + + Returns + ------- + num_iterations + Number of iterations if converged, 0 if maxiter reached + without convergence + + Notes + ----- + This routine uses a re-implementation of the global approximate + curvature minimization algorithm described in [Nielson83] and [Renka84]. + + References + ---------- + .. [Nielson83] G. Nielson, + ''A method for interpolating scattered data based upon a minimum norm + network''. + Math. Comp., 40, 253 (1983). + .. [Renka84] R. J. Renka and A. K. Cline. + ''A Triangle-based C1 interpolation method.'', + Rocky Mountain J. Math., 14, 223 (1984). + + """ + cdef double Q[2*2] + cdef double s[2], r[2] + cdef int ipoint, iiter, k + cdef qhull.RidgeIter2D_t it + cdef double f1, f2, df2, ex, ey, L, L3, det, err, change + + # initialize + for ipoint in xrange(2*d.npoints): + y[ipoint] = 0 + + # + # Main point: + # + # Z = sum_T sum_{E in T} int_E |W''|^2 = min! + # + # where W'' is the second derivative of the Clough-Tocher + # interpolant to the direction of the edge E in triangle T. + # + # The minimization is done iteratively: for each vertex V, + # the sum + # + # Z_V = sum_{E connected to V} int_E |W''|^2 + # + # is minimized separately, using existing values at other V. + # + # Since the interpolant can be written as + # + # W(x) = f(x) + w(x)^T y + # + # where y = [ F_x(V); F_y(V) ], it is clear that the solution to + # the local problem is is given as a solution of the 2x2 matrix + # equation. + # + # Here, we use the Clough-Tocher interpolant, which restricted to + # a single edge is + # + # w(x) = (1 - x)**3 * f1 + # + x*(1 - x)**2 * (df1 + 3*f1) + # + x**2*(1 - x) * (df2 + 3*f2) + # + x**3 * f2 + # + # where f1, f2 are values at the vertices, and df1 and df2 are + # derivatives along the edge (away from the vertices). + # + # As a consequence, one finds + # + # L^3 int_{E} |W''|^2 = y^T A y + 2 B y + C + # + # with + # + # A = [4, -2; -2, 4] + # B = [6*(f1 - f2), 6*(f2 - f1)] + # y = [df1, df2] + # L = length of edge E + # + # and C is not needed for minimization. Since df1 = dF1.E, df2 = -dF2.E, + # with dF1 = [F_x(V_1), F_y(V_1)], and the edge vector E = V2 - V1, + # we have + # + # Z_V = dF1^T Q dF1 + 2 s.dF1 + const. + # + # which is minimized by + # + # dF1 = -Q^{-1} s + # + # where + # + # Q = sum_E [A_11 E E^T]/L_E^3 = 4 sum_E [E E^T]/L_E^3 + # s = sum_E [ B_1 + A_21 df2] E /L_E^3 + # = sum_E [ 6*(f1 - f2) + 2*(E.dF2)] E / L_E^3 + # + + # Gauss-Seidel + for iiter in xrange(maxiter): + err = 0 + for ipoint in xrange(d.npoints): + for k in xrange(2*2): + Q[k] = 0 + for k in xrange(2): + s[k] = 0 + + # walk over neighbours of given point + qhull._RidgeIter2D_init(&it, d, ipoint) + + while it.edge != -1: + # edge + ex = d.points[2*it.vertex2 + 0] - d.points[2*it.vertex + 0] + ey = d.points[2*it.vertex2 + 1] - d.points[2*it.vertex + 1] + L = sqrt(ex**2 + ey**2) + L3 = L*L*L + + # data at vertices + f1 = data[it.vertex] + f2 = data[it.vertex2] + + # scaled gradient projections on the edge + df2 = -ex*y[it.vertex2*2 + 0] - ey*y[it.vertex2*2 + 1] + + # edge sum + Q[0] += 4*ex*ex / L3 + Q[1] += 4*ex*ey / L3 + Q[3] += 4*ey*ey / L3 + + s[0] += (6*(f1 - f2) - 2*df2) * ex / L3 + s[1] += (6*(f1 - f2) - 2*df2) * ey / L3 + + # next edge + qhull._RidgeIter2D_next(&it) + + Q[2] = Q[1] + + # solve + + det = Q[0]*Q[3] - Q[1]*Q[2] + r[0] = ( Q[3]*s[0] - Q[1]*s[1])/det + r[1] = (-Q[2]*s[0] + Q[0]*s[1])/det + + change = fmax(fabs(y[it.vertex*2 + 0] + r[0]), + fabs(y[it.vertex*2 + 1] + r[1])) + + y[it.vertex*2 + 0] = -r[0] + y[it.vertex*2 + 1] = -r[1] + + # relative/absolute error + change /= fmax(1.0, fmax(fabs(r[0]), fabs(r[1]))) + err = fmax(err, change) + + if err < tol: + return iiter + 1 + + # Didn't converge before maxiter + return 0 + +def estimate_gradients_2d_global(tri, y, maxiter=400, tol=1e-6): + cdef np.ndarray[np.double_t, ndim=2] data + cdef np.ndarray[np.double_t, ndim=3] grad + cdef qhull.DelaunayInfo_t *info + cdef int k, ret, nvalues + + y = np.asanyarray(y) + + if y.shape[0] != tri.npoints: + raise ValueError("'y' has a wrong number of items") + + if np.issubdtype(y.dtype, np.complexfloating): + rg = estimate_gradients_2d_global(tri, y.real, maxiter=maxiter, tol=tol) + ig = estimate_gradients_2d_global(tri, y.imag, maxiter=maxiter, tol=tol) + r = np.zeros(rg.shape, dtype=complex) + r.real = rg + r.imag = ig + return r + + y_shape = y.shape + + if y.ndim == 1: + y = y[:,None] + + y = y.reshape(tri.npoints, -1).T + y = np.ascontiguousarray(y).astype(np.double) + yi = np.empty((y.shape[0], y.shape[1], 2)) + + data = y + grad = yi + + info = qhull._get_delaunay_info(tri, 0, 1) + nvalues = data.shape[0] + + for k in xrange(nvalues): + with nogil: + ret = _estimate_gradients_2d_global( + info, + data.data + info.npoints*k, + maxiter, + tol, + grad.data + 2*info.npoints*k) + + if ret == 0: + warnings.warn("Gradient estimation did not converge, " + "the results may be inaccurate", + GradientEstimationWarning) + + free(info) + return yi.transpose(1, 0, 2).reshape(y_shape + (2,)) + + +#------------------------------------------------------------------------------ +# Cubic interpolation in 2D +#------------------------------------------------------------------------------ + + +% for DTYPE, CDTYPE in zip(["double", "complex"], ["double", "double complex"]): + + at cython.cdivision(True) +cdef ${CDTYPE} _clough_tocher_2d_single_${DTYPE}(qhull.DelaunayInfo_t *d, + int isimplex, + double *b, + ${CDTYPE} *f, + ${CDTYPE} *df) nogil: + """ + Evaluate Clough-Tocher interpolant on a 2D triangle. + + Parameters + ---------- + d + Delaunay info + isimplex + Triangle to evaluate on + b : shape (3,) + Barycentric coordinates of the point on the triangle + f : shape (3,) + Function values at vertices + df : shape (3, 2) + Gradient values at vertices + + Returns + ------- + w + Value of the interpolant at the given point + + References + ---------- + .. [CT] See, for example, + P. Alfeld, + ''A trivariate Clough-Tocher scheme for tetrahedral data''. + Computer Aided Geometric Design, 1, 169 (1984); + G. Farin, + ''Triangular Bernstein-Bezier patches''. + Computer Aided Geometric Design, 3, 83 (1986). + + """ + cdef ${CDTYPE} \ + c3000, c0300, c0030, c0003, \ + c2100, c2010, c2001, c0210, c0201, c0021, \ + c1200, c1020, c1002, c0120, c0102, c0012, \ + c1101, c1011, c0111 + cdef ${CDTYPE} \ + f1, f2, f3, df12, df13, df21, df23, df31, df32 + cdef double \ + g1, g2, g3 + cdef double \ + e12x, e12y, e23x, e23y, e31x, e31y, \ + e14x, e14y, e24x, e24y, e34x, e34y + cdef ${CDTYPE} w + cdef double minval + cdef double b1, b2, b3, b4 + cdef int k, itri + cdef double c[3] + cdef double y[2] + + # XXX: optimize + refactor this! + + e12x = (+ d.points[0 + 2*d.vertices[3*isimplex + 1]] + - d.points[0 + 2*d.vertices[3*isimplex + 0]]) + e12y = (+ d.points[1 + 2*d.vertices[3*isimplex + 1]] + - d.points[1 + 2*d.vertices[3*isimplex + 0]]) + + e23x = (+ d.points[0 + 2*d.vertices[3*isimplex + 2]] + - d.points[0 + 2*d.vertices[3*isimplex + 1]]) + e23y = (+ d.points[1 + 2*d.vertices[3*isimplex + 2]] + - d.points[1 + 2*d.vertices[3*isimplex + 1]]) + + e31x = (+ d.points[0 + 2*d.vertices[3*isimplex + 0]] + - d.points[0 + 2*d.vertices[3*isimplex + 2]]) + e31y = (+ d.points[1 + 2*d.vertices[3*isimplex + 0]] + - d.points[1 + 2*d.vertices[3*isimplex + 2]]) + + e14x = (e12x - e31x)/3 + e14y = (e12y - e31y)/3 + + e24x = (-e12x + e23x)/3 + e24y = (-e12y + e23y)/3 + + e34x = (e31x - e23x)/3 + e34y = (e31y - e23y)/3 + + f1 = f[0] + f2 = f[1] + f3 = f[2] + + df12 = +(df[2*0+0]*e12x + df[2*0+1]*e12y) + df21 = -(df[2*1+0]*e12x + df[2*1+1]*e12y) + df23 = +(df[2*1+0]*e23x + df[2*1+1]*e23y) + df32 = -(df[2*2+0]*e23x + df[2*2+1]*e23y) + df31 = +(df[2*2+0]*e31x + df[2*2+1]*e31y) + df13 = -(df[2*0+0]*e31x + df[2*0+1]*e31y) + + c3000 = f1 + c2100 = (df12 + 3*c3000)/3 + c2010 = (df13 + 3*c3000)/3 + c0300 = f2 + c1200 = (df21 + 3*c0300)/3 + c0210 = (df23 + 3*c0300)/3 + c0030 = f3 + c1020 = (df31 + 3*c0030)/3 + c0120 = (df32 + 3*c0030)/3 + + c2001 = (c2100 + c2010 + c3000)/3 + c0201 = (c1200 + c0300 + c0210)/3 + c0021 = (c1020 + c0120 + c0030)/3 + + # + # Now, we need to impose the condition that the gradient of the spline + # to some direction `w` is a linear function along the edge. + # + # As long as two neighbouring triangles agree on the choice of the + # direction `w`, this ensures global C1 differentiability. + # Otherwise, the choice of the direction is arbitrary (except that + # it should not point along the edge, of course). + # + # In [CT]_, it is suggested to pick `w` as the normal of the edge. + # This choice is given by the formulas + # + # w_12 = E_24 + g1 * E_23 + # w_23 = E_34 + g2 * E_31 + # w_31 = E_14 + g3 * E_12 + # + # g1 = -(e24x*e23x + e24y*e23y) / (e23x**2 + e23y**2) + # g2 = -(e34x*e31x + e34y*e31y) / (e31x**2 + e31y**2) + # g3 = -(e14x*e12x + e14y*e12y) / (e12x**2 + e12y**2) + # + # However, this choice gives an interpolant that is *not* + # invariant under affine transforms. This has some bad + # consequences: for a very narrow triangle, the spline can + # develops huge oscillations. For instance, with the input data + # + # [(0, 0), (0, 1), (eps, eps)], eps = 0.01 + # F = [0, 0, 1] + # dF = [(0,0), (0,0), (0,0)] + # + # one observes that as eps -> 0, the absolute maximum value of the + # interpolant approaches infinity. + # + # So below, we aim to pick affine invariant `g1`, `g2`, `g3`. + # We choose + # + # w = V_4' - V_4 + # + # where V_4 is the centroid of the current triangle, and V_4' the + # centroid of the neighbour. Since this quantity transforms similarly + # as the gradient under affine transforms, the resulting interpolant + # is affine-invariant. Moreover, two neighbouring triangles clearly + # always agree on the choice of `w` (sign is unimportant), and so + # this choice also makes the interpolant C1. + # + # The drawback here is a performance penalty, since we need to + # peek into neighbouring triangles. + # + + for k in xrange(3): + itri = d.neighbors[3*isimplex + k] + + if itri == -1: + # No neighbour. + # Compute derivative to the centroid direction (e_12 + e_13)/2. + if k == 0: + g1 = -2./3 + elif k == 1: + g2 = -2./3 + elif k == 2: + g3 = -2./3 + continue + + # Centroid of the neighbour, in our local barycentric coordinates + + y[0] = (+ d.points[0 + 2*d.vertices[3*itri + 0]] + + d.points[0 + 2*d.vertices[3*itri + 1]] + + d.points[0 + 2*d.vertices[3*itri + 2]]) / 3 + + y[1] = (+ d.points[1 + 2*d.vertices[3*itri + 0]] + + d.points[1 + 2*d.vertices[3*itri + 1]] + + d.points[1 + 2*d.vertices[3*itri + 2]]) / 3 + + qhull._barycentric_coordinates(2, d.transform + isimplex*2*3, y, c) + + # Rewrite V_4'-V_4 = const*[(V_4-V_2) + g_i*(V_3 - V_2)] + + # Now, observe that the results can be written *in terms of + # barycentric coordinates*. Barycentric coordinates stay + # invariant under affine transformations, so we can directly + # conclude that the choice below is affine-invariant. + + if k == 0: + g1 = (2*c[2] + c[1] - 1) / (2 - 3*c[2] - 3*c[1]) + elif k == 1: + g2 = (2*c[0] + c[2] - 1) / (2 - 3*c[0] - 3*c[2]) + elif k == 2: + g3 = (2*c[1] + c[0] - 1) / (2 - 3*c[1] - 3*c[0]) + + c0111 = (g1*(-c0300 + 3*c0210 - 3*c0120 + c0030) + + (-c0300 + 2*c0210 - c0120 + c0021 + c0201))/2 + c1011 = (g2*(-c0030 + 3*c1020 - 3*c2010 + c3000) + + (-c0030 + 2*c1020 - c2010 + c2001 + c0021))/2 + c1101 = (g3*(-c3000 + 3*c2100 - 3*c1200 + c0300) + + (-c3000 + 2*c2100 - c1200 + c2001 + c0201))/2 + + c1002 = (c1101 + c1011 + c2001)/3 + c0102 = (c1101 + c0111 + c0201)/3 + c0012 = (c1011 + c0111 + c0021)/3 + + c0003 = (c1002 + c0102 + c0012)/3 + + # extended barycentric coordinates + minval = b[0] + for k in xrange(3): + if b[k] < minval: + minval = b[k] + + b1 = b[0] - minval + b2 = b[1] - minval + b3 = b[2] - minval + b4 = 3*minval + + # evaluate the polynomial -- the stupid and ugly way to do it, + # one of the 4 coordinates is in fact zero + w = (b1**3*c3000 + 3*b1**2*b2*c2100 + 3*b1**2*b3*c2010 + + 3*b1**2*b4*c2001 + 3*b1*b2**2*c1200 + + 6*b1*b2*b4*c1101 + 3*b1*b3**2*c1020 + 6*b1*b3*b4*c1011 + + 3*b1*b4**2*c1002 + b2**3*c0300 + 3*b2**2*b3*c0210 + + 3*b2**2*b4*c0201 + 3*b2*b3**2*c0120 + 6*b2*b3*b4*c0111 + + 3*b2*b4**2*c0102 + b3**3*c0030 + 3*b3**2*b4*c0021 + + 3*b3*b4**2*c0012 + b4**3*c0003) + + return w + +% endfor + +class CloughTocher2DInterpolator(NDInterpolatorBase): + """ + CloughTocher2DInterpolator(points, values, tol=1e-6) + + Piecewise cubic, C1 smooth, curvature-minimizing interpolant in 2D. + + .. versionadded:: 0.9 + + Parameters + ---------- + points : ndarray of floats, shape (npoints, ndims) + Data point coordinates. + values : ndarray of float or complex, shape (npoints, ...) + Data values. + fill_value : float, optional + Value used to fill in for requested points outside of the + convex hull of the input points. If not provided, then + the default is ``nan``. + tol : float, optional + Absolute/relative tolerance for gradient estimation. + maxiter : int, optional + Maximum number of iterations in gradient estimation. + + Notes + ----- + The interpolant is constructed by triangulating the input data + with Qhull [Qhull]_, and constructing a piecewise cubic + interpolating Bezier polynomial on each triangle, using a + Clough-Tocher scheme [CT]_. The interpolant is guaranteed to be + continuously differentiable. + + The gradients of the interpolant are chosen so that the curvature + of the interpolating surface is approximatively minimized. The + gradients necessary for this are estimated using the global + algorithm described in [Nielson83,Renka84]_. + + References + ---------- + + .. [Qhull] http://www.qhull.org/ + + .. [CT] See, for example, + P. Alfeld, + ''A trivariate Clough-Tocher scheme for tetrahedral data''. + Computer Aided Geometric Design, 1, 169 (1984); + G. Farin, + ''Triangular Bernstein-Bezier patches''. + Computer Aided Geometric Design, 3, 83 (1986). + + .. [Nielson83] G. Nielson, + ''A method for interpolating scattered data based upon a minimum norm + network''. + Math. Comp., 40, 253 (1983). + + .. [Renka84] R. J. Renka and A. K. Cline. + ''A Triangle-based C1 interpolation method.'', + Rocky Mountain J. Math., 14, 223 (1984). + + """ + + def __init__(self, points, values, fill_value=np.nan, + tol=1e-6, maxiter=400): + NDInterpolatorBase.__init__(self, points, values, ndim=2, + fill_value=fill_value) + self.tri = qhull.Delaunay(points) + self.grad = estimate_gradients_2d_global(self.tri, self.values, + tol=tol, maxiter=maxiter) + +% for DTYPE, CDTYPE in zip(["double", "complex"], ["double", "double complex"]): + + @cython.boundscheck(False) + def _evaluate_${DTYPE}(self, np.ndarray[np.double_t, ndim=2] xi): + cdef np.ndarray[np.${DTYPE}_t, ndim=2] values = self.values + cdef np.ndarray[np.${DTYPE}_t, ndim=3] grad = self.grad + cdef np.ndarray[np.${DTYPE}_t, ndim=2] out + cdef np.ndarray[np.double_t, ndim=2] points = self.points + cdef np.ndarray[np.int_t, ndim=2] vertices = self.tri.vertices + cdef double c[NPY_MAXDIMS] + cdef ${CDTYPE} f[NPY_MAXDIMS+1] + cdef ${CDTYPE} df[2*NPY_MAXDIMS+2] + cdef ${CDTYPE} w + cdef ${CDTYPE} fill_value + cdef int i, j, k, m, ndim, isimplex, inside, start, nvalues + cdef qhull.DelaunayInfo_t *info + + ndim = xi.shape[1] + start = 0 + fill_value = self.fill_value + + info = qhull._get_delaunay_info(self.tri, 1, 1) + + out = np.zeros((xi.shape[0], self.values.shape[1]), dtype=np.${DTYPE}) + nvalues = out.shape[1] + + eps = np.finfo(np.double).eps * 100 + + with nogil: + for i in xrange(xi.shape[0]): + # 1) Find the simplex + + isimplex = qhull._find_simplex(info, c, + (xi.data) + i*ndim, + &start, eps) + + # 2) Clough-Tocher interpolation + + if isimplex == -1: + # outside triangulation + for k in xrange(nvalues): +% if DTYPE == "double": + out[i,k] = fill_value +% else: + out[i,k].real = fill_value.real + out[i,k].imag = fill_value.imag +% endif + continue + + for k in xrange(nvalues): + for j in xrange(ndim+1): +% if DTYPE == "double": + f[j] = values[vertices[isimplex,j],k] + df[2*j] = grad[vertices[isimplex,j],k,0] + df[2*j+1] = grad[vertices[isimplex,j],k,1] +% else: + f[j].real = values[vertices[isimplex,j],k].real + f[j].imag = values[vertices[isimplex,j],k].imag + df[2*j].real = grad[vertices[isimplex,j],k,0].real + df[2*j].imag = grad[vertices[isimplex,j],k,0].imag + df[2*j+1].real = grad[vertices[isimplex,j],k,1].real + df[2*j+1].imag = grad[vertices[isimplex,j],k,1].imag +% endif + + w = _clough_tocher_2d_single_${DTYPE}(info, isimplex, c, + f, df) +% if DTYPE == "double": + out[i,k] = w +% else: + out[i,k].real = w.real + out[i,k].imag = w.imag +% endif + + free(info) + return out + +% endfor Added: trunk/scipy/interpolate/interpnd_info.py =================================================================== --- trunk/scipy/interpolate/interpnd_info.py (rev 0) +++ trunk/scipy/interpolate/interpnd_info.py 2010-08-31 21:57:20 UTC (rev 6655) @@ -0,0 +1,36 @@ +""" +Here we perform some symbolic computations required for the N-D +interpolation routines in `interpnd.pyx`. + +""" +from sympy import * + +def _estimate_gradients_2d_global(): + + # + # Compute + # + # + + f1, f2, df1, df2, x = symbols(['f1', 'f2', 'df1', 'df2', 'x']) + c = [f1, (df1 + 3*f1)/3, (df2 + 3*f2)/3, f2] + + w = 0 + for k in range(4): + w += binomial(3, k) * c[k] * x**k*(1-x)**(3-k) + + wpp = w.diff(x, 2).expand() + intwpp2 = (wpp**2).integrate((x, 0, 1)).expand() + + A = Matrix([[intwpp2.coeff(df1**2), intwpp2.coeff(df1*df2)/2], + [intwpp2.coeff(df1*df2)/2, intwpp2.coeff(df2**2)]]) + + B = Matrix([[intwpp2.coeff(df1).subs(df2, 0)], + [intwpp2.coeff(df2).subs(df1, 0)]]) / 2 + + print "A" + print A + print "B" + print B + print "solution" + print A.inv() * B Modified: trunk/scipy/interpolate/setup.py =================================================================== --- trunk/scipy/interpolate/setup.py 2010-08-31 21:56:34 UTC (rev 6654) +++ trunk/scipy/interpolate/setup.py 2010-08-31 21:57:20 UTC (rev 6655) @@ -11,6 +11,9 @@ sources=[join('fitpack', '*.f')], ) + config.add_extension('interpnd', + sources=['interpnd.c']) + config.add_extension('_fitpack', sources=['src/_fitpackmodule.c'], libraries=['fitpack'], Added: trunk/scipy/interpolate/tests/test_interpnd.py =================================================================== --- trunk/scipy/interpolate/tests/test_interpnd.py (rev 0) +++ trunk/scipy/interpolate/tests/test_interpnd.py 2010-08-31 21:57:20 UTC (rev 6655) @@ -0,0 +1,163 @@ +import numpy as np +from numpy.testing import * + +import scipy.interpolate.interpnd as interpnd +import scipy.spatial.qhull as qhull + +class TestLinearNDInterpolation(object): + def test_smoketest(self): + # Test at single points + x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)], + dtype=np.double) + y = np.arange(x.shape[0], dtype=np.double) + + yi = interpnd.LinearNDInterpolator(x, y)(x) + assert_almost_equal(y, yi) + + def test_complex_smoketest(self): + # Test at single points + x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)], + dtype=np.double) + y = np.arange(x.shape[0], dtype=np.double) + y = y - 3j*y + + yi = interpnd.LinearNDInterpolator(x, y)(x) + assert_almost_equal(y, yi) + + def test_square(self): + # Test barycentric interpolation on a square against a manual + # implementation + + points = np.array([(0,0), (0,1), (1,1), (1,0)], dtype=np.double) + values = np.array([1., 2., -3., 5.], dtype=np.double) + + # NB: assume triangles (0, 1, 3) and (1, 2, 3) + # + # 1----2 + # | \ | + # | \ | + # 0----3 + + def ip(x, y): + t1 = (x + y <= 1) + t2 = ~t1 + + x1 = x[t1] + y1 = y[t1] + + x2 = x[t2] + y2 = y[t2] + + z = 0*x + + z[t1] = (values[0]*(1 - x1 - y1) + + values[1]*y1 + + values[3]*x1) + + z[t2] = (values[2]*(x2 + y2 - 1) + + values[1]*(1 - x2) + + values[3]*(1 - y2)) + return z + + xx, yy = np.broadcast_arrays(np.linspace(0, 1, 14)[:,None], + np.linspace(0, 1, 14)[None,:]) + xx = xx.ravel() + yy = yy.ravel() + + xi = np.array([xx, yy]).T.copy() + zi = interpnd.LinearNDInterpolator(points, values)(xi) + + assert_almost_equal(zi, ip(xx, yy)) + +class TestEstimateGradients2DGlobal(object): + def test_smoketest(self): + x = np.array([(0, 0), (0, 2), + (1, 0), (1, 2), (0.25, 0.75), (0.6, 0.8)], dtype=float) + tri = qhull.Delaunay(x) + + # Should be exact for linear functions, independent of triangulation + + funcs = [ + (lambda x, y: 0*x + 1, (0, 0)), + (lambda x, y: 0 + x, (1, 0)), + (lambda x, y: -2 + y, (0, 1)), + (lambda x, y: 3 + 3*x + 14.15*y, (3, 14.15)) + ] + + for j, (func, grad) in enumerate(funcs): + z = func(x[:,0], x[:,1]) + dz = interpnd.estimate_gradients_2d_global(tri, z, tol=1e-6) + + assert_equal(dz.shape, (6, 2)) + assert_allclose(dz, np.array(grad)[None,:] + 0*dz, + rtol=1e-5, atol=1e-5, err_msg="item %d" % j) + +class TestCloughTocher2DInterpolator(object): + + def _check_accuracy(self, func, x=None, tol=1e-6, **kw): + np.random.seed(1234) + if x is None: + x = np.array([(0, 0), (0, 1), + (1, 0), (1, 1), (0.25, 0.75), (0.6, 0.8)], + dtype=float) + + ip = interpnd.CloughTocher2DInterpolator(x, func(x[:,0], x[:,1]), + tol=1e-6) + p = np.random.rand(50, 2) + + a = ip(p) + b = func(p[:,0], p[:,1]) + + try: + assert_allclose(a, b, **kw) + except AssertionError: + print abs(a - b) + print ip.grad + raise + + def test_linear_smoketest(self): + # Should be exact for linear functions, independent of triangulation + funcs = [ + lambda x, y: 0*x + 1, + lambda x, y: 0 + x, + lambda x, y: -2 + y, + lambda x, y: 3 + 3*x + 14.15*y, + ] + + for j, func in enumerate(funcs): + self._check_accuracy(func, tol=1e-13, atol=1e-7, rtol=1e-7, + err_msg="Function %d" % j) + + def test_quadratic_dense_smoketest(self): + # Should be reasonably accurate for quadratic functions + funcs = [ + lambda x, y: x**2, + lambda x, y: y**2, + lambda x, y: x**2 - y**2, + lambda x, y: x*y, + ] + + for j, func in enumerate(funcs): + self._check_accuracy(func, tol=1e-9, atol=0.22, rtol=0, + err_msg="Function %d" % j) + + def test_dense(self): + # Should be more accurate for dense meshes + funcs = [ + lambda x, y: x**2, + lambda x, y: y**2, + lambda x, y: x**2 - y**2, + lambda x, y: x*y, + lambda x, y: np.cos(2*np.pi*x)*np.sin(2*np.pi*y) + ] + + np.random.seed(4321) # use a different seed than the check! + grid = np.r_[np.array([(0,0), (0,1), (1,0), (1,1)], dtype=float), + np.random.rand(30*30, 2)] + + for j, func in enumerate(funcs): + self._check_accuracy(func, x=grid, tol=1e-9, atol=1e-2, rtol=1e-2, + err_msg="Function %d" % j) + +if __name__ == "__main__": + run_module_suite() From scipy-svn at scipy.org Tue Aug 31 17:58:25 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 16:58:25 -0500 (CDT) Subject: [Scipy-svn] r6656 - trunk/scipy/interpolate Message-ID: <20100831215825.23CD939CD18@scipy.org> Author: ptvirtan Date: 2010-08-31 16:58:25 -0500 (Tue, 31 Aug 2010) New Revision: 6656 Added: trunk/scipy/interpolate/interpnd.c Log: GEN: interpolate: regenerate interpnd.c Added: trunk/scipy/interpolate/interpnd.c =================================================================== --- trunk/scipy/interpolate/interpnd.c (rev 0) +++ trunk/scipy/interpolate/interpnd.c 2010-08-31 21:58:25 UTC (rev 6656) @@ -0,0 +1,9652 @@ + + +#define PY_SSIZE_T_CLEAN +#include "Python.h" +#include "structmember.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#else + +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#if PY_VERSION_HEX < 0x02040000 + #define METH_COEXIST 0 + #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) + #define PyDict_Contains(d,o) PySequence_Contains(d,o) +#endif + +#if PY_VERSION_HEX < 0x02050000 + typedef int Py_ssize_t; + #define PY_SSIZE_T_MAX INT_MAX + #define PY_SSIZE_T_MIN INT_MIN + #define PY_FORMAT_SIZE_T "" + #define PyInt_FromSsize_t(z) PyInt_FromLong(z) + #define PyInt_AsSsize_t(o) PyInt_AsLong(o) + #define PyNumber_Index(o) PyNumber_Int(o) + #define PyIndex_Check(o) PyNumber_Check(o) + #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message) +#endif + +#if PY_VERSION_HEX < 0x02060000 + #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) + #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) + #define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) + #define PyVarObject_HEAD_INIT(type, size) \ + PyObject_HEAD_INIT(type) size, + #define PyType_Modified(t) + + typedef struct { + void *buf; + PyObject *obj; + Py_ssize_t len; + Py_ssize_t itemsize; + int readonly; + int ndim; + char *format; + Py_ssize_t *shape; + Py_ssize_t *strides; + Py_ssize_t *suboffsets; + void *internal; + } Py_buffer; + + #define PyBUF_SIMPLE 0 + #define PyBUF_WRITABLE 0x0001 + #define PyBUF_FORMAT 0x0004 + #define PyBUF_ND 0x0008 + #define PyBUF_STRIDES (0x0010 | PyBUF_ND) + #define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) + #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) + #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) + #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) + +#endif + +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" +#endif + +#if PY_MAJOR_VERSION >= 3 + #define Py_TPFLAGS_CHECKTYPES 0 + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif + +#if (PY_VERSION_HEX < 0x02060000) || (PY_MAJOR_VERSION >= 3) + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif + +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyString_Type PyUnicode_Type + #define PyString_CheckExact PyUnicode_CheckExact +#else + #define PyBytes_Type PyString_Type + #define PyBytes_CheckExact PyString_CheckExact +#endif + +#if PY_MAJOR_VERSION >= 3 + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) + +#endif + +#if PY_MAJOR_VERSION >= 3 + #define PyMethod_New(func, self, klass) PyInstanceMethod_New(func) +#endif + +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#else + #define _USE_MATH_DEFINES +#endif + +#if PY_VERSION_HEX < 0x02050000 + #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),((char *)(n))) + #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),((char *)(n)),(a)) + #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),((char *)(n))) +#else + #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),(n)) + #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),(n),(a)) + #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),(n)) +#endif + +#if PY_VERSION_HEX < 0x02050000 + #define __Pyx_NAMESTR(n) ((char *)(n)) + #define __Pyx_DOCSTR(n) ((char *)(n)) +#else + #define __Pyx_NAMESTR(n) (n) + #define __Pyx_DOCSTR(n) (n) +#endif +#ifdef __cplusplus +#define __PYX_EXTERN_C extern "C" +#else +#define __PYX_EXTERN_C extern +#endif +#include +#define __PYX_HAVE_API__interpnd +#include "stdlib.h" +#include "stdio.h" +#include "numpy/arrayobject.h" +#include "numpy/ufuncobject.h" +#include "numpy/ndarraytypes.h" +#include "math.h" + +#ifndef CYTHON_INLINE + #if defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #else + #define CYTHON_INLINE + #endif +#endif + +typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + + + + +#if PY_MAJOR_VERSION < 3 +#define __Pyx_PyBytes_FromString PyString_FromString +#define __Pyx_PyBytes_FromStringAndSize PyString_FromStringAndSize +#define __Pyx_PyBytes_AsString PyString_AsString +#else +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +#define __Pyx_PyBytes_AsString PyBytes_AsString +#endif + +#define __Pyx_PyBytes_FromUString(s) __Pyx_PyBytes_FromString((char*)s) +#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) __Pyx_PyBytes_AsString(s)) + +#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False)) +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); + +#if !defined(T_PYSSIZET) +#if PY_VERSION_HEX < 0x02050000 +#define T_PYSSIZET T_INT +#elif !defined(T_LONGLONG) +#define T_PYSSIZET \ + ((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \ + ((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : -1)) +#else +#define T_PYSSIZET \ + ((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \ + ((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : \ + ((sizeof(Py_ssize_t) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1))) +#endif +#endif + + +#if !defined(T_ULONGLONG) +#define __Pyx_T_UNSIGNED_INT(x) \ + ((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \ + ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \ + ((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \ + ((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : -1)))) +#else +#define __Pyx_T_UNSIGNED_INT(x) \ + ((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \ + ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \ + ((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \ + ((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : \ + ((sizeof(x) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1))))) +#endif +#if !defined(T_LONGLONG) +#define __Pyx_T_SIGNED_INT(x) \ + ((sizeof(x) == sizeof(char)) ? T_BYTE : \ + ((sizeof(x) == sizeof(short)) ? T_SHORT : \ + ((sizeof(x) == sizeof(int)) ? T_INT : \ + ((sizeof(x) == sizeof(long)) ? T_LONG : -1)))) +#else +#define __Pyx_T_SIGNED_INT(x) \ + ((sizeof(x) == sizeof(char)) ? T_BYTE : \ + ((sizeof(x) == sizeof(short)) ? T_SHORT : \ + ((sizeof(x) == sizeof(int)) ? T_INT : \ + ((sizeof(x) == sizeof(long)) ? T_LONG : \ + ((sizeof(x) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1))))) +#endif + +#define __Pyx_T_FLOATING(x) \ + ((sizeof(x) == sizeof(float)) ? T_FLOAT : \ + ((sizeof(x) == sizeof(double)) ? T_DOUBLE : -1)) + +#if !defined(T_SIZET) +#if !defined(T_ULONGLONG) +#define T_SIZET \ + ((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \ + ((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : -1)) +#else +#define T_SIZET \ + ((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \ + ((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : \ + ((sizeof(size_t) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1))) +#endif +#endif + +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*); + +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) + + +#ifdef __GNUC__ + +#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif + +static PyObject *__pyx_m; +static PyObject *__pyx_b; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; +static const char **__pyx_f; + + +#if !defined(CYTHON_CCOMPLEX) + #if defined(__cplusplus) + #define CYTHON_CCOMPLEX 1 + #elif defined(_Complex_I) + #define CYTHON_CCOMPLEX 1 + #else + #define CYTHON_CCOMPLEX 0 + #endif +#endif + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #include + #else + #include + #endif +#endif + +#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) + #undef _Complex_I + #define _Complex_I 1.0fj +#endif + +typedef npy_int8 __pyx_t_5numpy_int8_t; + +typedef npy_int16 __pyx_t_5numpy_int16_t; + +typedef npy_int32 __pyx_t_5numpy_int32_t; + +typedef npy_int64 __pyx_t_5numpy_int64_t; + +typedef npy_uint8 __pyx_t_5numpy_uint8_t; + +typedef npy_uint16 __pyx_t_5numpy_uint16_t; + +typedef npy_uint32 __pyx_t_5numpy_uint32_t; + +typedef npy_uint64 __pyx_t_5numpy_uint64_t; + +typedef npy_float32 __pyx_t_5numpy_float32_t; + +typedef npy_float64 __pyx_t_5numpy_float64_t; + +typedef npy_long __pyx_t_5numpy_int_t; + +typedef npy_longlong __pyx_t_5numpy_long_t; + +typedef npy_intp __pyx_t_5numpy_intp_t; + +typedef npy_uintp __pyx_t_5numpy_uintp_t; + +typedef npy_ulong __pyx_t_5numpy_uint_t; + +typedef npy_ulonglong __pyx_t_5numpy_ulong_t; + +typedef npy_double __pyx_t_5numpy_float_t; + +typedef npy_double __pyx_t_5numpy_double_t; + +typedef npy_longdouble __pyx_t_5numpy_longdouble_t; + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< double > __pyx_t_double_complex; + #else + typedef double _Complex __pyx_t_double_complex; + #endif +#else + typedef struct { double real, imag; } __pyx_t_double_complex; +#endif + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< float > __pyx_t_float_complex; + #else + typedef float _Complex __pyx_t_float_complex; + #endif +#else + typedef struct { float real, imag; } __pyx_t_float_complex; +#endif + + + +typedef npy_cfloat __pyx_t_5numpy_cfloat_t; + +typedef npy_cdouble __pyx_t_5numpy_cdouble_t; + +typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; + +typedef npy_cdouble __pyx_t_5numpy_complex_t; + + + +typedef struct { + int ndim; + int npoints; + int nsimplex; + double *points; + int *vertices; + int *neighbors; + double *equations; + double *transform; + int *vertex_to_simplex; + double paraboloid_scale; + double paraboloid_shift; + double *max_bound; + double *min_bound; +} __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t; + + + +typedef struct { + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *info; + int vertex; + int edge; + int vertex2; + int triangle; + int start_triangle; + int start_edge; +} __pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t; + +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif + +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct * __Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule((char *)modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); + end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; + } + #define __Pyx_RefNannySetupContext(name) void *__pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) + #define __Pyx_RefNannyFinishContext() __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r);} } while(0) +#else + #define __Pyx_RefNannySetupContext(name) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) +#endif +#define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);} } while(0) +#define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r);} } while(0) + +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, PyObject* kw_name); + +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name); + + +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { + PyObject *r; + if (!j) return NULL; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + return r; +} + + +#define __Pyx_GetItemInt_List(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \ + __Pyx_GetItemInt_List_Fast(o, i, size <= sizeof(long)) : \ + __Pyx_GetItemInt_Generic(o, to_py_func(i))) + +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, int fits_long) { + if (likely(o != Py_None)) { + if (likely((0 <= i) & (i < PyList_GET_SIZE(o)))) { + PyObject *r = PyList_GET_ITEM(o, i); + Py_INCREF(r); + return r; + } + else if ((-PyList_GET_SIZE(o) <= i) & (i < 0)) { + PyObject *r = PyList_GET_ITEM(o, PyList_GET_SIZE(o) + i); + Py_INCREF(r); + return r; + } + } + return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i)); +} + +#define __Pyx_GetItemInt_Tuple(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \ + __Pyx_GetItemInt_Tuple_Fast(o, i, size <= sizeof(long)) : \ + __Pyx_GetItemInt_Generic(o, to_py_func(i))) + +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, int fits_long) { + if (likely(o != Py_None)) { + if (likely((0 <= i) & (i < PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, i); + Py_INCREF(r); + return r; + } + else if ((-PyTuple_GET_SIZE(o) <= i) & (i < 0)) { + PyObject *r = PyTuple_GET_ITEM(o, PyTuple_GET_SIZE(o) + i); + Py_INCREF(r); + return r; + } + } + return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i)); +} + + +#define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \ + __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \ + __Pyx_GetItemInt_Generic(o, to_py_func(i))) + +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) { + PyObject *r; + if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) { + r = PyList_GET_ITEM(o, i); + Py_INCREF(r); + } + else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) { + r = PyTuple_GET_ITEM(o, i); + Py_INCREF(r); + } + else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) { + r = PySequence_GetItem(o, i); + } + else { + r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i)); + } + return r; +} + +static double __Pyx__PyObject_AsDouble(PyObject* obj); + +#define __Pyx_PyObject_AsDouble(obj) \ + ((likely(PyFloat_CheckExact(obj))) ? \ + PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj)) + + +struct __Pyx_StructField_; + +typedef struct { + const char* name; + struct __Pyx_StructField_* fields; + size_t size; + char typegroup; +} __Pyx_TypeInfo; + +typedef struct __Pyx_StructField_ { + __Pyx_TypeInfo* type; + const char* name; + size_t offset; +} __Pyx_StructField; + +typedef struct { + __Pyx_StructField* field; + size_t parent_offset; +} __Pyx_BufFmt_StackElem; + + +static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info); +static int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); + +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); + +static void __Pyx_RaiseBufferFallbackError(void); +#define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1) + +static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); +#define __Pyx_BufPtrStrided3d(type, buf, i0, s0, i1, s1, i2, s2) (type)((char*)buf + i0 * s0 + i1 * s1 + i2 * s2) + +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); + +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void); + +static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); +static int __Pyx_EndUnpack(PyObject *); + +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); + +static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); + +static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, + const char *name, int exact); + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #define __Pyx_CREAL(z) ((z).real()) + #define __Pyx_CIMAG(z) ((z).imag()) + #else + #define __Pyx_CREAL(z) (__real__(z)) + #define __Pyx_CIMAG(z) (__imag__(z)) + #endif +#else + #define __Pyx_CREAL(z) ((z).real) + #define __Pyx_CIMAG(z) ((z).imag) +#endif + +#if defined(_WIN32) && defined(__cplusplus) && CYTHON_CCOMPLEX + #define __Pyx_SET_CREAL(z,x) ((z).real(x)) + #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) +#else + #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) + #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) +#endif + +static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); + +#if CYTHON_CCOMPLEX + #define __Pyx_c_eq(a, b) ((a)==(b)) + #define __Pyx_c_sum(a, b) ((a)+(b)) + #define __Pyx_c_diff(a, b) ((a)-(b)) + #define __Pyx_c_prod(a, b) ((a)*(b)) + #define __Pyx_c_quot(a, b) ((a)/(b)) + #define __Pyx_c_neg(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero(z) ((z)==(double)0) + #define __Pyx_c_conj(z) (::std::conj(z)) + + #else + #define __Pyx_c_is_zero(z) ((z)==0) + #define __Pyx_c_conj(z) (conj(z)) + + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg(__pyx_t_double_complex); + static CYTHON_INLINE int __Pyx_c_is_zero(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj(__pyx_t_double_complex); + +#endif +#if PY_MAJOR_VERSION < 3 +static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); +static void __Pyx_ReleaseBuffer(Py_buffer *view); +#else +#define __Pyx_GetBuffer PyObject_GetBuffer +#define __Pyx_ReleaseBuffer PyBuffer_Release +#endif + +Py_ssize_t __Pyx_zeros[] = {0, 0, 0}; +Py_ssize_t __Pyx_minusones[] = {-1, -1, -1}; + +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); + +static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); + +static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); + +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); + +static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_npy_intp(npy_intp); + +#ifndef __PYX_FORCE_INIT_THREADS + #if PY_VERSION_HEX < 0x02040200 + #define __PYX_FORCE_INIT_THREADS 1 + #else + #define __PYX_FORCE_INIT_THREADS 0 + #endif +#endif + +static __pyx_t_double_complex __Pyx_PyComplex_As___pyx_t_double_complex(PyObject*); + +static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); + +#if CYTHON_CCOMPLEX + #define __Pyx_c_eqf(a, b) ((a)==(b)) + #define __Pyx_c_sumf(a, b) ((a)+(b)) + #define __Pyx_c_difff(a, b) ((a)-(b)) + #define __Pyx_c_prodf(a, b) ((a)*(b)) + #define __Pyx_c_quotf(a, b) ((a)/(b)) + #define __Pyx_c_negf(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zerof(z) ((z)==(float)0) + #define __Pyx_c_conjf(z) (::std::conj(z)) + + #else + #define __Pyx_c_is_zerof(z) ((z)==0) + #define __Pyx_c_conjf(z) (conjf(z)) + + #endif +#else + static CYTHON_INLINE int __Pyx_c_eqf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sumf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_difff(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prodf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quotf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_negf(__pyx_t_float_complex); + static CYTHON_INLINE int __Pyx_c_is_zerof(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conjf(__pyx_t_float_complex); + +#endif + +static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject *); + +static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject *); + +static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject *); + +static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject *); + +static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject *); + +static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject *); + +static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject *); + +static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject *); + +static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject *); + +static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject *); + +static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject *); + +static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject *); + +static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject *); + +static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject *); + +static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *); + +static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, long size, int strict); + +static PyObject *__Pyx_ImportModule(const char *name); + +static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig); + +static void __Pyx_AddTraceback(const char *funcname); + +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + + + + + + + + + + + + +static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; +static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; +static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; +static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; +static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *, PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *, PyObject *, PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *, PyObject *, PyObject *, PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *, PyObject *, PyObject *, PyObject *, PyObject *); +static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); +static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *, PyObject *); +static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *); + + +static __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *(*__pyx_f_5scipy_7spatial_5qhull__get_delaunay_info)(PyObject *, int, int); +static int (*__pyx_f_5scipy_7spatial_5qhull__barycentric_inside)(int, double *, double *, double *, double); +static void (*__pyx_f_5scipy_7spatial_5qhull__barycentric_coordinate_single)(int, double *, double *, double *, int); +static void (*__pyx_f_5scipy_7spatial_5qhull__barycentric_coordinates)(int, double *, double *, double *); +static void (*__pyx_f_5scipy_7spatial_5qhull__lift_point)(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *); +static double (*__pyx_f_5scipy_7spatial_5qhull__distplane)(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int, double *); +static int (*__pyx_f_5scipy_7spatial_5qhull__is_point_fully_outside)(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double); +static int (*__pyx_f_5scipy_7spatial_5qhull__find_simplex_bruteforce)(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, double); +static int (*__pyx_f_5scipy_7spatial_5qhull__find_simplex_directed)(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, int *, double); +static int (*__pyx_f_5scipy_7spatial_5qhull__find_simplex)(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, int *, double); +static void (*__pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_init)(__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *, __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int); +static void (*__pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_next)(__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *); + + + + +static int __pyx_f_8interpnd__estimate_gradients_2d_global(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, int, double, double *); +static double __pyx_f_8interpnd__clough_tocher_2d_single_double(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int, double *, double *, double *); +static __pyx_t_double_complex __pyx_f_8interpnd__clough_tocher_2d_single_complex(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int, double *, __pyx_t_double_complex *, __pyx_t_double_complex *); +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_double_t = { "numpy.double_t", NULL, sizeof(__pyx_t_5numpy_double_t), 'R' }; +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_int_t = { "numpy.int_t", NULL, sizeof(__pyx_t_5numpy_int_t), 'I' }; +static __Pyx_TypeInfo __Pyx_TypeInfo_double = { "double", NULL, sizeof(double), 'R' }; +static __Pyx_StructField __Pyx_StructFields_nn___pyx_t_5numpy_complex_t[] = { + {&__Pyx_TypeInfo_double, "real", offsetof(__pyx_t_5numpy_complex_t, real)}, + {&__Pyx_TypeInfo_double, "imag", offsetof(__pyx_t_5numpy_complex_t, imag)}, + {NULL, NULL, 0} +}; +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_complex_t = { "numpy.complex_t", __Pyx_StructFields_nn___pyx_t_5numpy_complex_t, sizeof(__pyx_t_5numpy_complex_t), 'C' }; +#define __Pyx_MODULE_NAME "interpnd" +int __pyx_module_is_main_interpnd = 0; + + +static PyObject *__pyx_builtin_object; +static PyObject *__pyx_builtin_Warning; +static PyObject *__pyx_builtin_ValueError; +static PyObject *__pyx_builtin_map; +static PyObject *__pyx_builtin_xrange; +static PyObject *__pyx_builtin_enumerate; +static PyObject *__pyx_builtin_range; +static PyObject *__pyx_builtin_RuntimeError; +static char __pyx_k_2[] = "_ndim_coords_from_arrays"; +static char __pyx_k_3[] = "different number of values and points"; +static char __pyx_k_4[] = "invalid shape for input data points"; +static char __pyx_k_5[] = "input data must be at least 2-D"; +static char __pyx_k_6[] = "this mode of interpolation available only for %-D data"; +static char __pyx_k_7[] = "number of dimensions in xi does not match x"; +static char __pyx_k_8[] = "coordinate arrays do not have the same shape"; +static char __pyx_k_11[] = "'y' has a wrong number of items"; +static char __pyx_k_12[] = "estimate_gradients_2d_global"; +static char __pyx_k_13[] = "Gradient estimation did not converge, the results may be inaccurate"; +static char __pyx_k_14[] = "GradientEstimationWarning"; +static char __pyx_k_17[] = "ndarray is not C contiguous"; +static char __pyx_k_18[] = "ndarray is not Fortran contiguous"; +static char __pyx_k_19[] = "Non-native byte order not supported"; +static char __pyx_k_20[] = "unknown dtype code in numpy.pxd (%d)"; +static char __pyx_k_21[] = "Format string allocated too short, see comment in numpy.pxd"; +static char __pyx_k_22[] = "Format string allocated too short."; +static char __pyx_k_23[] = "\nSimple N-D interpolation\n\n.. versionadded:: 0.9\n\n"; +static char __pyx_k_24[] = "scipy.spatial.qhull"; +static char __pyx_k_25[] = "*"; +static char __pyx_k_26[] = "\n Common routines for interpolators.\n\n .. versionadded:: 0.9\n\n "; +static char __pyx_k_27[] = "\n LinearNDInterpolator(points, values)\n\n Piecewise linear interpolant in N dimensions. \n\n .. versionadded:: 0.9\n\n Parameters\n ----------\n points : ndarray of floats, shape (npoints, ndims)\n Data point coordinates.\n values : ndarray of float or complex, shape (npoints, ...)\n Data values.\n fill_value : float, optional\n Value used to fill in for requested points outside of the\n convex hull of the input points. If not provided, then\n the default is ``nan``.\n\n Notes\n -----\n The interpolant is constructed by triangulating the input data\n with Qhull [Qhull]_, and on each triangle performing linear\n barycentric interpolation.\n\n References\n ----------\n .. [Qhull] http://www.qhull.org/\n\n "; +static char __pyx_k_28[] = "LinearNDInterpolator"; +static char __pyx_k_29[] = "\n CloughTocher2DInterpolator(points, values, tol=1e-6)\n\n Piecewise cubic, C1 smooth, curvature-minimizing interpolant in 2D. \n\n .. versionadded:: 0.9\n\n Parameters\n ----------\n points : ndarray of floats, shape (npoints, ndims)\n Data point coordinates.\n values : ndarray of float or complex, shape (npoints, ...)\n Data values.\n fill_value : float, optional\n Value used to fill in for requested points outside of the\n convex hull of the input points. If not provided, then\n the default is ``nan``.\n tol : float, optional\n Absolute/relative tolerance for gradient estimation.\n maxiter : int, optional\n Maximum number of iterations in gradient estimation.\n\n Notes\n -----\n The interpolant is constructed by triangulating the input data\n with Qhull [Qhull]_, and constructing a piecewise cubic\n interpolating Bezier polynomial on each triangle, using a\n Clough-Tocher scheme [CT]_. The interpolant is guaranteed to be\n continuously differentiable.\n\n The gradients of the interpolant are chosen so that the curvature\n of the interpolating surface is approximatively minimized. The\n gradients necessary for this are estimated using the global\n algorithm described in [Nielson83,Renka84]_.\n\n References\n ----------\n\n .. [Qhull] http://www.qhull.org/\n\n .. [CT] See, for example,\n P. Alfeld,\n ''A trivariate Clough-Tocher scheme for tetrahedral data''.\n Computer Aided Geometric Design, 1, 169 (1984);\n G. Farin,\n ''Triangular Bernstein-Bezier patches''.\n Computer Aided Geometric Design, 3, 83 (1986).\n\n .. [Nielson83] G. Nielson,\n ''A method for interpolating scattered data based upon a minimum norm\n network''.\n Math. Comp., 40, 253 (1983).\n\n .. [Renka84] R. J. Renka and A. K. Cline.\n ''A Triangle-based C1 interpolation method.'',\n Rocky Mountain J. Math., 14, 223 (1984).\n\n "; +static char __pyx_k_30[] = "CloughTocher2DInterpolator"; +static char __pyx_k_31[] = "NDInterpolatorBase.__init__ (line 60)"; +static char __pyx_k_32[] = "NDInterpolatorBase._check_init_shape (line 93)"; +static char __pyx_k_33[] = "NDInterpolatorBase.__call__ (line 114)"; +static char __pyx_k_34[] = "_ndim_coords_from_arrays (line 139)"; +static char __pyx_k__B[] = "B"; +static char __pyx_k__H[] = "H"; +static char __pyx_k__I[] = "I"; +static char __pyx_k__L[] = "L"; +static char __pyx_k__O[] = "O"; +static char __pyx_k__Q[] = "Q"; +static char __pyx_k__T[] = "T"; +static char __pyx_k__b[] = "b"; +static char __pyx_k__d[] = "d"; +static char __pyx_k__f[] = "f"; +static char __pyx_k__g[] = "g"; +static char __pyx_k__h[] = "h"; +static char __pyx_k__i[] = "i"; +static char __pyx_k__l[] = "l"; +static char __pyx_k__q[] = "q"; +static char __pyx_k__y[] = "y"; +static char __pyx_k__Zd[] = "Zd"; +static char __pyx_k__Zf[] = "Zf"; +static char __pyx_k__Zg[] = "Zg"; +static char __pyx_k__np[] = "np"; +static char __pyx_k__xi[] = "xi"; +static char __pyx_k__buf[] = "buf"; +static char __pyx_k__eps[] = "eps"; +static char __pyx_k__map[] = "map"; +static char __pyx_k__nan[] = "nan"; +static char __pyx_k__obj[] = "obj"; +static char __pyx_k__tol[] = "tol"; +static char __pyx_k__tri[] = "tri"; +static char __pyx_k__base[] = "base"; +static char __pyx_k__data[] = "data"; +static char __pyx_k__edge[] = "edge"; +static char __pyx_k__grad[] = "grad"; +static char __pyx_k__imag[] = "imag"; +static char __pyx_k__ndim[] = "ndim"; +static char __pyx_k__prod[] = "prod"; +static char __pyx_k__real[] = "real"; +static char __pyx_k__self[] = "self"; +static char __pyx_k__warn[] = "warn"; +static char __pyx_k__descr[] = "descr"; +static char __pyx_k__dtype[] = "dtype"; +static char __pyx_k__empty[] = "empty"; +static char __pyx_k__finfo[] = "finfo"; +static char __pyx_k__names[] = "names"; +static char __pyx_k__numpy[] = "numpy"; +static char __pyx_k__qhull[] = "qhull"; +static char __pyx_k__range[] = "range"; +static char __pyx_k__shape[] = "shape"; +static char __pyx_k__zeros[] = "zeros"; +static char __pyx_k__astype[] = "astype"; +static char __pyx_k__double[] = "double"; +static char __pyx_k__fields[] = "fields"; +static char __pyx_k__format[] = "format"; +static char __pyx_k__object[] = "object"; +static char __pyx_k__points[] = "points"; +static char __pyx_k__values[] = "values"; +static char __pyx_k__vertex[] = "vertex"; +static char __pyx_k__xrange[] = "xrange"; +static char __pyx_k__Warning[] = "Warning"; +static char __pyx_k__complex[] = "complex"; +static char __pyx_k__maxiter[] = "maxiter"; +static char __pyx_k__npoints[] = "npoints"; +static char __pyx_k__reshape[] = "reshape"; +static char __pyx_k__strides[] = "strides"; +static char __pyx_k__vertex2[] = "vertex2"; +static char __pyx_k__Delaunay[] = "Delaunay"; +static char __pyx_k____call__[] = "__call__"; +static char __pyx_k____init__[] = "__init__"; +static char __pyx_k____main__[] = "__main__"; +static char __pyx_k____test__[] = "__test__"; +static char __pyx_k__itemsize[] = "itemsize"; +static char __pyx_k__readonly[] = "readonly"; +static char __pyx_k__type_num[] = "type_num"; +static char __pyx_k__vertices[] = "vertices"; +static char __pyx_k__warnings[] = "warnings"; +static char __pyx_k__byteorder[] = "byteorder"; +static char __pyx_k__enumerate[] = "enumerate"; +static char __pyx_k__neighbors[] = "neighbors"; +static char __pyx_k__transform[] = "transform"; +static char __pyx_k__transpose[] = "transpose"; +static char __pyx_k__ValueError[] = "ValueError"; +static char __pyx_k__asanyarray[] = "asanyarray"; +static char __pyx_k__fill_value[] = "fill_value"; +static char __pyx_k__is_complex[] = "is_complex"; +static char __pyx_k__issubdtype[] = "issubdtype"; +static char __pyx_k__suboffsets[] = "suboffsets"; +static char __pyx_k__RuntimeError[] = "RuntimeError"; +static char __pyx_k__values_shape[] = "values_shape"; +static char __pyx_k__complexfloating[] = "complexfloating"; +static char __pyx_k___evaluate_double[] = "_evaluate_double"; +static char __pyx_k___check_call_shape[] = "_check_call_shape"; +static char __pyx_k___check_init_shape[] = "_check_init_shape"; +static char __pyx_k___evaluate_complex[] = "_evaluate_complex"; +static char __pyx_k__ascontiguousarray[] = "ascontiguousarray"; +static char __pyx_k__NDInterpolatorBase[] = "NDInterpolatorBase"; +static PyObject *__pyx_kp_s_11; +static PyObject *__pyx_n_s_12; +static PyObject *__pyx_kp_s_13; +static PyObject *__pyx_n_s_14; +static PyObject *__pyx_kp_u_17; +static PyObject *__pyx_kp_u_18; +static PyObject *__pyx_kp_u_19; +static PyObject *__pyx_n_s_2; +static PyObject *__pyx_kp_u_20; +static PyObject *__pyx_kp_u_21; +static PyObject *__pyx_kp_u_22; +static PyObject *__pyx_n_s_24; +static PyObject *__pyx_n_s_25; +static PyObject *__pyx_kp_s_26; +static PyObject *__pyx_kp_s_27; +static PyObject *__pyx_n_s_28; +static PyObject *__pyx_kp_s_29; +static PyObject *__pyx_kp_s_3; +static PyObject *__pyx_n_s_30; +static PyObject *__pyx_kp_u_31; +static PyObject *__pyx_kp_u_32; +static PyObject *__pyx_kp_u_33; +static PyObject *__pyx_kp_u_34; +static PyObject *__pyx_kp_s_4; +static PyObject *__pyx_kp_s_5; +static PyObject *__pyx_kp_s_6; +static PyObject *__pyx_kp_s_7; +static PyObject *__pyx_kp_s_8; +static PyObject *__pyx_n_s__Delaunay; +static PyObject *__pyx_n_s__NDInterpolatorBase; +static PyObject *__pyx_n_s__RuntimeError; +static PyObject *__pyx_n_s__T; +static PyObject *__pyx_n_s__ValueError; +static PyObject *__pyx_n_s__Warning; +static PyObject *__pyx_n_s____call__; +static PyObject *__pyx_n_s____init__; +static PyObject *__pyx_n_s____main__; +static PyObject *__pyx_n_s____test__; +static PyObject *__pyx_n_s___check_call_shape; +static PyObject *__pyx_n_s___check_init_shape; +static PyObject *__pyx_n_s___evaluate_complex; +static PyObject *__pyx_n_s___evaluate_double; +static PyObject *__pyx_n_s__asanyarray; +static PyObject *__pyx_n_s__ascontiguousarray; +static PyObject *__pyx_n_s__astype; +static PyObject *__pyx_n_s__base; +static PyObject *__pyx_n_s__buf; +static PyObject *__pyx_n_s__byteorder; +static PyObject *__pyx_n_s__complex; +static PyObject *__pyx_n_s__complexfloating; +static PyObject *__pyx_n_s__data; +static PyObject *__pyx_n_s__descr; +static PyObject *__pyx_n_s__double; +static PyObject *__pyx_n_s__dtype; +static PyObject *__pyx_n_s__edge; +static PyObject *__pyx_n_s__empty; +static PyObject *__pyx_n_s__enumerate; +static PyObject *__pyx_n_s__eps; +static PyObject *__pyx_n_s__fields; +static PyObject *__pyx_n_s__fill_value; +static PyObject *__pyx_n_s__finfo; +static PyObject *__pyx_n_s__format; +static PyObject *__pyx_n_s__grad; +static PyObject *__pyx_n_s__imag; +static PyObject *__pyx_n_s__is_complex; +static PyObject *__pyx_n_s__issubdtype; +static PyObject *__pyx_n_s__itemsize; +static PyObject *__pyx_n_s__map; +static PyObject *__pyx_n_s__maxiter; +static PyObject *__pyx_n_s__names; +static PyObject *__pyx_n_s__nan; +static PyObject *__pyx_n_s__ndim; +static PyObject *__pyx_n_s__neighbors; +static PyObject *__pyx_n_s__np; +static PyObject *__pyx_n_s__npoints; +static PyObject *__pyx_n_s__numpy; +static PyObject *__pyx_n_s__obj; +static PyObject *__pyx_n_s__object; +static PyObject *__pyx_n_s__points; +static PyObject *__pyx_n_s__prod; +static PyObject *__pyx_n_s__qhull; +static PyObject *__pyx_n_s__range; +static PyObject *__pyx_n_s__readonly; +static PyObject *__pyx_n_s__real; +static PyObject *__pyx_n_s__reshape; +static PyObject *__pyx_n_s__self; +static PyObject *__pyx_n_s__shape; +static PyObject *__pyx_n_s__strides; +static PyObject *__pyx_n_s__suboffsets; +static PyObject *__pyx_n_s__tol; +static PyObject *__pyx_n_s__transform; +static PyObject *__pyx_n_s__transpose; +static PyObject *__pyx_n_s__tri; +static PyObject *__pyx_n_s__type_num; +static PyObject *__pyx_n_s__values; +static PyObject *__pyx_n_s__values_shape; +static PyObject *__pyx_n_s__vertex; +static PyObject *__pyx_n_s__vertex2; +static PyObject *__pyx_n_s__vertices; +static PyObject *__pyx_n_s__warn; +static PyObject *__pyx_n_s__warnings; +static PyObject *__pyx_n_s__xi; +static PyObject *__pyx_n_s__xrange; +static PyObject *__pyx_n_s__y; +static PyObject *__pyx_n_s__zeros; +static PyObject *__pyx_int_0; +static PyObject *__pyx_int_1; +static PyObject *__pyx_int_2; +static PyObject *__pyx_int_neg_1; +static PyObject *__pyx_int_15; +static PyObject *__pyx_int_100; +static PyObject *__pyx_int_400; +static PyObject *__pyx_k_1; +static PyObject *__pyx_k_9; +static PyObject *__pyx_k_10; +static PyObject *__pyx_k_15; +static PyObject *__pyx_k_16; + + + +static PyObject *__pyx_pf_8interpnd_18NDInterpolatorBase___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static char __pyx_doc_8interpnd_18NDInterpolatorBase___init__[] = "\n Check shape of points and values arrays, and reshape values to\n (npoints, nvalues). Ensure the `points` and values arrays are\n C-contiguous, and of correct type.\n "; +static PyMethodDef __pyx_mdef_8interpnd_18NDInterpolatorBase___init__ = {__Pyx_NAMESTR("__init__"), (PyCFunction)__pyx_pf_8interpnd_18NDInterpolatorBase___init__, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_8interpnd_18NDInterpolatorBase___init__)}; +static PyObject *__pyx_pf_8interpnd_18NDInterpolatorBase___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_points = 0; + PyObject *__pyx_v_values = 0; + PyObject *__pyx_v_fill_value = 0; + PyObject *__pyx_v_ndim = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + double __pyx_t_7; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__points,&__pyx_n_s__values,&__pyx_n_s__fill_value,&__pyx_n_s__ndim,0}; + __Pyx_RefNannySetupContext("__init__"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[5] = {0,0,0,0,0}; + values[3] = __pyx_k_1; + values[4] = ((PyObject *)Py_None); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__points); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 5, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__values); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 5, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 3: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fill_value); + if (unlikely(value)) { values[3] = value; kw_args--; } + } + case 4: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__ndim); + if (unlikely(value)) { values[4] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_points = values[1]; + __pyx_v_values = values[2]; + __pyx_v_fill_value = values[3]; + __pyx_v_ndim = values[4]; + } else { + __pyx_v_fill_value = __pyx_k_1; + __pyx_v_ndim = ((PyObject *)Py_None); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 5: + __pyx_v_ndim = PyTuple_GET_ITEM(__pyx_args, 4); + case 4: + __pyx_v_fill_value = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: + __pyx_v_values = PyTuple_GET_ITEM(__pyx_args, 2); + __pyx_v_points = PyTuple_GET_ITEM(__pyx_args, 1); + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; + } + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.NDInterpolatorBase.__init__"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF(__pyx_v_points); + __Pyx_INCREF(__pyx_v_values); + __Pyx_INCREF(__pyx_v_fill_value); + __Pyx_INCREF(__pyx_v_ndim); + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_points); + __pyx_v_points = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___check_init_shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __Pyx_INCREF(__pyx_v_values); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_values); + __Pyx_GIVEREF(__pyx_v_values); + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_1)); + if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__ndim), __pyx_v_ndim) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_3, __pyx_t_2, ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__ascontiguousarray); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyObject_GetAttr(__pyx_v_points, __pyx_n_s__astype); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_4, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_points); + __pyx_v_points = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__ascontiguousarray); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_values); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_values); + __Pyx_GIVEREF(__pyx_v_values); + __pyx_t_1 = PyObject_Call(__pyx_t_2, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_values); + __pyx_v_values = __pyx_t_1; + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_values, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PySequence_GetSlice(__pyx_t_1, 1, PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__values_shape, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_values, __pyx_n_s__ndim); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_int_1, Py_EQ); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_5) { + + + __pyx_t_1 = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_INCREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_3, 1, Py_None); + __Pyx_GIVEREF(Py_None); + __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetItem(__pyx_v_values, __pyx_t_3); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__values, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L6; + } + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_values, __pyx_n_s__ndim); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_int_2, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_5) { + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__values, __pyx_v_values) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + { + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_values, __pyx_n_s__reshape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyObject_GetAttr(__pyx_v_values, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_1, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__prod); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetAttr(__pyx_v_values, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_6 = PySequence_GetSlice(__pyx_t_1, 1, PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_6); + __pyx_t_6 = 0; + __pyx_t_6 = PyObject_Call(__pyx_t_4, __pyx_t_1, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_6); + __pyx_t_2 = 0; + __pyx_t_6 = 0; + __pyx_t_6 = PyObject_Call(__pyx_t_3, __pyx_t_1, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__values, __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __pyx_L6:; + + + __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__issubdtype); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__dtype); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__complexfloating); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_3 = 0; + __pyx_t_2 = 0; + __pyx_t_2 = PyObject_Call(__pyx_t_1, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__is_complex, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__is_complex); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__pyx_t_5) { + + + __pyx_t_2 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_6 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__astype); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__complex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyObject_Call(__pyx_t_6, __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__values, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_fill_value); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_fill_value); + __Pyx_GIVEREF(__pyx_v_fill_value); + __pyx_t_2 = PyObject_Call(((PyObject*)&PyComplex_Type), __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__fill_value, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + goto __pyx_L7; + } + { + + + __pyx_t_2 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__astype); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_6 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__double); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_6); + __pyx_t_6 = 0; + __pyx_t_6 = PyObject_Call(__pyx_t_1, __pyx_t_2, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__values, __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + + + __pyx_t_7 = __Pyx_PyObject_AsDouble(__pyx_v_fill_value); if (unlikely(__pyx_t_7 == ((double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = PyFloat_FromDouble(__pyx_t_7); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__fill_value, __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + __pyx_L7:; + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__points, __pyx_v_points) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("interpnd.NDInterpolatorBase.__init__"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF(__pyx_v_points); + __Pyx_DECREF(__pyx_v_values); + __Pyx_DECREF(__pyx_v_fill_value); + __Pyx_DECREF(__pyx_v_ndim); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_18NDInterpolatorBase__check_init_shape(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static char __pyx_doc_8interpnd_18NDInterpolatorBase__check_init_shape[] = "\n Check shape of points and values arrays\n\n "; +static PyMethodDef __pyx_mdef_8interpnd_18NDInterpolatorBase__check_init_shape = {__Pyx_NAMESTR("_check_init_shape"), (PyCFunction)__pyx_pf_8interpnd_18NDInterpolatorBase__check_init_shape, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_8interpnd_18NDInterpolatorBase__check_init_shape)}; +static PyObject *__pyx_pf_8interpnd_18NDInterpolatorBase__check_init_shape(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_points = 0; + PyObject *__pyx_v_values = 0; + PyObject *__pyx_v_ndim = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__points,&__pyx_n_s__values,&__pyx_n_s__ndim,0}; + __Pyx_RefNannySetupContext("_check_init_shape"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[4] = {0,0,0,0}; + values[3] = ((PyObject *)Py_None); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__points); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_check_init_shape", 0, 3, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__values); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_check_init_shape", 0, 3, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 3: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__ndim); + if (unlikely(value)) { values[3] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_check_init_shape") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_points = values[1]; + __pyx_v_values = values[2]; + __pyx_v_ndim = values[3]; + } else { + __pyx_v_ndim = ((PyObject *)Py_None); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: + __pyx_v_ndim = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: + __pyx_v_values = PyTuple_GET_ITEM(__pyx_args, 2); + __pyx_v_points = PyTuple_GET_ITEM(__pyx_args, 1); + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; + } + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_check_init_shape", 0, 3, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.NDInterpolatorBase._check_init_shape"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF(__pyx_v_points); + __Pyx_INCREF(__pyx_v_values); + __Pyx_INCREF(__pyx_v_ndim); + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_values, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_1, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetAttr(__pyx_v_points, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_RichCompare(__pyx_t_2, __pyx_t_3, Py_NE); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_4) { + + + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_3)); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_kp_s_3)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_3)); + __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_points, __pyx_n_s__ndim); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_int_2, Py_NE); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_4) { + + + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_4)); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_kp_s_4)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_4)); + __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L7; + } + __pyx_L7:; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_points, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_int_2, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_4) { + + + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_5)); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_kp_s_5)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_5)); + __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_1, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L8; + } + __pyx_L8:; + + + __pyx_t_4 = (__pyx_v_ndim != Py_None); + if (__pyx_t_4) { + __pyx_t_1 = PyObject_GetAttr(__pyx_v_points, __pyx_n_s__shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_v_ndim, Py_NE); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_6 = __pyx_t_5; + } else { + __pyx_t_6 = __pyx_t_4; + } + if (__pyx_t_6) { + + + __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_6), __pyx_v_ndim); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_1, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L9; + } + __pyx_L9:; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("interpnd.NDInterpolatorBase._check_init_shape"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF(__pyx_v_points); + __Pyx_DECREF(__pyx_v_values); + __Pyx_DECREF(__pyx_v_ndim); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_18NDInterpolatorBase__check_call_shape(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static PyMethodDef __pyx_mdef_8interpnd_18NDInterpolatorBase__check_call_shape = {__Pyx_NAMESTR("_check_call_shape"), (PyCFunction)__pyx_pf_8interpnd_18NDInterpolatorBase__check_call_shape, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)}; +static PyObject *__pyx_pf_8interpnd_18NDInterpolatorBase__check_call_shape(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_xi = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__xi,0}; + __Pyx_RefNannySetupContext("_check_call_shape"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__xi); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_check_call_shape", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_check_call_shape") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_xi = values[1]; + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_xi = PyTuple_GET_ITEM(__pyx_args, 1); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_check_call_shape", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.NDInterpolatorBase._check_call_shape"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF(__pyx_v_xi); + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__asanyarray); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_xi); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_xi); + __Pyx_GIVEREF(__pyx_v_xi); + __pyx_t_3 = PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_xi); + __pyx_v_xi = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, -1, sizeof(long), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__points); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__shape); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_2, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_t_3, Py_NE); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__pyx_t_4) { + + + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_7)); + PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_7)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_7)); + __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_xi); + __pyx_r = __pyx_v_xi; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("interpnd.NDInterpolatorBase._check_call_shape"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF(__pyx_v_xi); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_18NDInterpolatorBase___call__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static char __pyx_doc_8interpnd_18NDInterpolatorBase___call__[] = "\n interpolator(xi)\n\n Evaluate interpolator at given points.\n\n Parameters\n ----------\n xi : ndarray of float, shape (..., ndim)\n Points where to interpolate data at.\n\n "; +static PyMethodDef __pyx_mdef_8interpnd_18NDInterpolatorBase___call__ = {__Pyx_NAMESTR("__call__"), (PyCFunction)__pyx_pf_8interpnd_18NDInterpolatorBase___call__, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_8interpnd_18NDInterpolatorBase___call__)}; +static PyObject *__pyx_pf_8interpnd_18NDInterpolatorBase___call__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_xi = 0; + PyObject *__pyx_v_shape; + PyObject *__pyx_v_r; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__xi,0}; + __Pyx_RefNannySetupContext("__call__"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__xi); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__call__", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__call__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_xi = values[1]; + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_xi = PyTuple_GET_ITEM(__pyx_args, 1); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__call__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.NDInterpolatorBase.__call__"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF(__pyx_v_xi); + __pyx_v_shape = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_r = Py_None; __Pyx_INCREF(Py_None); + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_xi); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_xi); + __Pyx_GIVEREF(__pyx_v_xi); + __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_xi); + __pyx_v_xi = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___check_call_shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_xi); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_xi); + __Pyx_GIVEREF(__pyx_v_xi); + __pyx_t_1 = PyObject_Call(__pyx_t_3, __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_xi); + __pyx_v_xi = __pyx_t_1; + __pyx_t_1 = 0; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__ascontiguousarray); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__astype); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = PyObject_Call(__pyx_t_2, __pyx_t_3, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_xi); + __pyx_v_xi = __pyx_t_4; + __pyx_t_4 = 0; + + + __pyx_t_4 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__shape); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_v_shape); + __pyx_v_shape = __pyx_t_4; + __pyx_t_4 = 0; + + + __pyx_t_4 = PyObject_GetAttr(__pyx_v_xi, __pyx_n_s__reshape); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__prod); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PySequence_GetSlice(__pyx_v_shape, 0, -1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_shape, -1, sizeof(long), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_3 = 0; + __pyx_t_1 = 0; + __pyx_t_1 = PyObject_Call(__pyx_t_4, __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_xi); + __pyx_v_xi = __pyx_t_1; + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__is_complex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_5) { + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___evaluate_complex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_xi); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_xi); + __Pyx_GIVEREF(__pyx_v_xi); + __pyx_t_4 = PyObject_Call(__pyx_t_1, __pyx_t_2, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_r); + __pyx_v_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L6; + } + { + + + __pyx_t_4 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s___evaluate_double); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_xi); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_xi); + __Pyx_GIVEREF(__pyx_v_xi); + __pyx_t_1 = PyObject_Call(__pyx_t_4, __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_v_r); + __pyx_v_r = __pyx_t_1; + __pyx_t_1 = 0; + } + __pyx_L6:; + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyObject_GetAttr(__pyx_v_r, __pyx_n_s__reshape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PySequence_GetSlice(__pyx_v_shape, 0, -1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values_shape); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyNumber_Add(__pyx_t_2, __pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_r = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("interpnd.NDInterpolatorBase.__call__"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF(__pyx_v_shape); + __Pyx_DECREF(__pyx_v_r); + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF(__pyx_v_xi); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd__ndim_coords_from_arrays(PyObject *__pyx_self, PyObject *__pyx_v_points); +static char __pyx_doc_8interpnd__ndim_coords_from_arrays[] = "\n Convert a tuple of coordinate arrays to a (..., ndim)-shaped array.\n\n "; +static PyObject *__pyx_pf_8interpnd__ndim_coords_from_arrays(PyObject *__pyx_self, PyObject *__pyx_v_points) { + PyObject *__pyx_v_p; + PyObject *__pyx_v_j; + PyObject *__pyx_v_item; + PyObject *__pyx_r = NULL; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + Py_ssize_t __pyx_t_7; + Py_ssize_t __pyx_t_8; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + __Pyx_RefNannySetupContext("_ndim_coords_from_arrays"); + __pyx_self = __pyx_self; + __Pyx_INCREF(__pyx_v_points); + __pyx_v_p = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_j = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_item = Py_None; __Pyx_INCREF(Py_None); + + + __pyx_t_1 = PyObject_TypeCheck(__pyx_v_points, ((PyTypeObject *)((PyObject*)&PyTuple_Type))); + if (!__pyx_t_1) { + __pyx_t_2 = PyObject_TypeCheck(__pyx_v_points, ((PyTypeObject *)((PyObject*)&PyList_Type))); + __pyx_t_3 = __pyx_t_2; + } else { + __pyx_t_3 = __pyx_t_1; + } + if (__pyx_t_3) { + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_points); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__pyx_t_1) { + __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_points, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyObject_TypeCheck(__pyx_t_4, ((PyTypeObject *)((PyObject*)__pyx_ptype_5numpy_ndarray))); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_5 = __pyx_t_2; + } else { + __pyx_t_5 = __pyx_t_1; + } + __pyx_t_1 = __pyx_t_5; + } else { + __pyx_t_1 = __pyx_t_3; + } + if (__pyx_t_1) { + + + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__asanyarray); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_6); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __pyx_t_6 = 0; + __pyx_t_6 = PyObject_Call(__pyx_builtin_map, __pyx_t_4, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_v_p); + __pyx_v_p = __pyx_t_6; + __pyx_t_6 = 0; + + + __pyx_t_8 = PyObject_Length(__pyx_v_p); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_int_1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_int_1); + __Pyx_GIVEREF(__pyx_int_1); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_6); + __pyx_t_6 = 0; + __pyx_t_6 = PyObject_Call(__pyx_builtin_xrange, __pyx_t_4, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyList_CheckExact(__pyx_t_6) || PyTuple_CheckExact(__pyx_t_6)) { + __pyx_t_7 = 0; __pyx_t_4 = __pyx_t_6; __Pyx_INCREF(__pyx_t_4); + } else { + __pyx_t_7 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + } + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + for (;;) { + if (likely(PyList_CheckExact(__pyx_t_4))) { + if (__pyx_t_7 >= PyList_GET_SIZE(__pyx_t_4)) break; + __pyx_t_6 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_7); __Pyx_INCREF(__pyx_t_6); __pyx_t_7++; + } else if (likely(PyTuple_CheckExact(__pyx_t_4))) { + if (__pyx_t_7 >= PyTuple_GET_SIZE(__pyx_t_4)) break; + __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_7); __Pyx_INCREF(__pyx_t_6); __pyx_t_7++; + } else { + __pyx_t_6 = PyIter_Next(__pyx_t_4); + if (!__pyx_t_6) { + if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + break; + } + __Pyx_GOTREF(__pyx_t_6); + } + __Pyx_DECREF(__pyx_v_j); + __pyx_v_j = __pyx_t_6; + __pyx_t_6 = 0; + + + __pyx_t_6 = PyObject_GetItem(__pyx_v_p, __pyx_v_j); if (!__pyx_t_6) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_9 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__shape); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_p, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_6) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_10 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__shape); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyObject_RichCompare(__pyx_t_9, __pyx_t_10, Py_NE); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (__pyx_t_1) { + + + __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_8)); + PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_kp_s_8)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_8)); + __pyx_t_10 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_6, NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_Raise(__pyx_t_10, 0, 0); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L8; + } + __pyx_L8:; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_10 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__empty); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_p, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__shape); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_7 = PyObject_Length(__pyx_v_points); if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyInt_FromSsize_t(__pyx_t_7); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = PyNumber_Add(__pyx_t_6, __pyx_t_9); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_4)); + if (PyDict_SetItem(__pyx_t_4, ((PyObject *)__pyx_n_s__dtype), ((PyObject *)((PyObject*)&PyFloat_Type))) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = PyEval_CallObjectWithKeywords(__pyx_t_10, __pyx_t_9, ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_v_points); + __pyx_v_points = __pyx_t_6; + __pyx_t_6 = 0; + + + __Pyx_INCREF(__pyx_int_0); + __pyx_t_6 = __pyx_int_0; + if (PyList_CheckExact(__pyx_v_p) || PyTuple_CheckExact(__pyx_v_p)) { + __pyx_t_7 = 0; __pyx_t_4 = __pyx_v_p; __Pyx_INCREF(__pyx_t_4); + } else { + __pyx_t_7 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_p); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + } + for (;;) { + if (likely(PyList_CheckExact(__pyx_t_4))) { + if (__pyx_t_7 >= PyList_GET_SIZE(__pyx_t_4)) break; + __pyx_t_9 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_7); __Pyx_INCREF(__pyx_t_9); __pyx_t_7++; + } else if (likely(PyTuple_CheckExact(__pyx_t_4))) { + if (__pyx_t_7 >= PyTuple_GET_SIZE(__pyx_t_4)) break; + __pyx_t_9 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_7); __Pyx_INCREF(__pyx_t_9); __pyx_t_7++; + } else { + __pyx_t_9 = PyIter_Next(__pyx_t_4); + if (!__pyx_t_9) { + if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + break; + } + __Pyx_GOTREF(__pyx_t_9); + } + __Pyx_DECREF(__pyx_v_item); + __pyx_v_item = __pyx_t_9; + __pyx_t_9 = 0; + __Pyx_INCREF(__pyx_t_6); + __Pyx_DECREF(__pyx_v_j); + __pyx_v_j = __pyx_t_6; + __pyx_t_9 = PyNumber_Add(__pyx_t_6, __pyx_int_1); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_6); + __pyx_t_6 = __pyx_t_9; + __pyx_t_9 = 0; + + + __pyx_t_9 = PyTuple_New(2); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_INCREF(Py_Ellipsis); + PyTuple_SET_ITEM(__pyx_t_9, 0, Py_Ellipsis); + __Pyx_GIVEREF(Py_Ellipsis); + __Pyx_INCREF(__pyx_v_j); + PyTuple_SET_ITEM(__pyx_t_9, 1, __pyx_v_j); + __Pyx_GIVEREF(__pyx_v_j); + if (PyObject_SetItem(__pyx_v_points, __pyx_t_9, __pyx_v_item) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L5; + } + { + + + __pyx_t_6 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_6, __pyx_n_s__asanyarray); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __pyx_t_9 = PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_v_points); + __pyx_v_points = __pyx_t_9; + __pyx_t_9 = 0; + } + __pyx_L5:; + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_points); + __pyx_r = __pyx_v_points; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_AddTraceback("interpnd._ndim_coords_from_arrays"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF(__pyx_v_p); + __Pyx_DECREF(__pyx_v_j); + __Pyx_DECREF(__pyx_v_item); + __Pyx_DECREF(__pyx_v_points); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_20LinearNDInterpolator___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static PyMethodDef __pyx_mdef_8interpnd_20LinearNDInterpolator___init__ = {__Pyx_NAMESTR("__init__"), (PyCFunction)__pyx_pf_8interpnd_20LinearNDInterpolator___init__, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)}; +static PyObject *__pyx_pf_8interpnd_20LinearNDInterpolator___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_points = 0; + PyObject *__pyx_v_values = 0; + PyObject *__pyx_v_fill_value = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__points,&__pyx_n_s__values,&__pyx_n_s__fill_value,0}; + __Pyx_RefNannySetupContext("__init__"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[4] = {0,0,0,0}; + values[3] = __pyx_k_9; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__points); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__values); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 3: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fill_value); + if (unlikely(value)) { values[3] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_points = values[1]; + __pyx_v_values = values[2]; + __pyx_v_fill_value = values[3]; + } else { + __pyx_v_fill_value = __pyx_k_9; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: + __pyx_v_fill_value = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: + __pyx_v_values = PyTuple_GET_ITEM(__pyx_args, 2); + __pyx_v_points = PyTuple_GET_ITEM(__pyx_args, 1); + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; + } + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.LinearNDInterpolator.__init__"); + return NULL; + __pyx_L4_argument_unpacking_done:; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__NDInterpolatorBase); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____init__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_self); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self); + __Pyx_GIVEREF(__pyx_v_self); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __Pyx_INCREF(__pyx_v_values); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_values); + __Pyx_GIVEREF(__pyx_v_values); + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__fill_value), __pyx_v_fill_value) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_2, __pyx_t_1, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__qhull); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__Delaunay); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __pyx_t_1 = PyObject_Call(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__tri, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("interpnd.LinearNDInterpolator.__init__"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_20LinearNDInterpolator__evaluate_double(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static PyMethodDef __pyx_mdef_8interpnd_20LinearNDInterpolator__evaluate_double = {__Pyx_NAMESTR("_evaluate_double"), (PyCFunction)__pyx_pf_8interpnd_20LinearNDInterpolator__evaluate_double, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)}; +static PyObject *__pyx_pf_8interpnd_20LinearNDInterpolator__evaluate_double(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyArrayObject *__pyx_v_xi = 0; + PyArrayObject *__pyx_v_values = 0; + PyArrayObject *__pyx_v_out; + PyArrayObject *__pyx_v_points = 0; + PyArrayObject *__pyx_v_vertices = 0; + double __pyx_v_c[NPY_MAXDIMS]; + double __pyx_v_fill_value; + int __pyx_v_i; + int __pyx_v_j; + int __pyx_v_k; + int __pyx_v_m; + int __pyx_v_ndim; + int __pyx_v_isimplex; + int __pyx_v_start; + int __pyx_v_nvalues; + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_info; + PyObject *__pyx_v_eps; + Py_buffer __pyx_bstruct_xi; + Py_ssize_t __pyx_bstride_0_xi = 0; + Py_ssize_t __pyx_bstride_1_xi = 0; + Py_ssize_t __pyx_bshape_0_xi = 0; + Py_ssize_t __pyx_bshape_1_xi = 0; + Py_buffer __pyx_bstruct_vertices; + Py_ssize_t __pyx_bstride_0_vertices = 0; + Py_ssize_t __pyx_bstride_1_vertices = 0; + Py_ssize_t __pyx_bshape_0_vertices = 0; + Py_ssize_t __pyx_bshape_1_vertices = 0; + Py_buffer __pyx_bstruct_points; + Py_ssize_t __pyx_bstride_0_points = 0; + Py_ssize_t __pyx_bstride_1_points = 0; + Py_ssize_t __pyx_bshape_0_points = 0; + Py_ssize_t __pyx_bshape_1_points = 0; + Py_buffer __pyx_bstruct_values; + Py_ssize_t __pyx_bstride_0_values = 0; + Py_ssize_t __pyx_bstride_1_values = 0; + Py_ssize_t __pyx_bshape_0_values = 0; + Py_ssize_t __pyx_bshape_1_values = 0; + Py_buffer __pyx_bstruct_out; + Py_ssize_t __pyx_bstride_0_out = 0; + Py_ssize_t __pyx_bstride_1_out = 0; + Py_ssize_t __pyx_bshape_0_out = 0; + Py_ssize_t __pyx_bshape_1_out = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyArrayObject *__pyx_t_2 = NULL; + PyArrayObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyArrayObject *__pyx_t_5 = NULL; + double __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyArrayObject *__pyx_t_10 = NULL; + int __pyx_t_11; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + npy_intp __pyx_t_15; + int __pyx_t_16; + int __pyx_t_17; + int __pyx_t_18; + int __pyx_t_19; + int __pyx_t_20; + int __pyx_t_21; + int __pyx_t_22; + long __pyx_t_23; + int __pyx_t_24; + int __pyx_t_25; + int __pyx_t_26; + int __pyx_t_27; + int __pyx_t_28; + int __pyx_t_29; + int __pyx_t_30; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__xi,0}; + __Pyx_RefNannySetupContext("_evaluate_double"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__xi); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_evaluate_double", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_evaluate_double") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_xi = ((PyArrayObject *)values[1]); + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_xi = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 1)); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_evaluate_double", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.LinearNDInterpolator._evaluate_double"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF((PyObject *)__pyx_v_xi); + __pyx_v_out = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_eps = Py_None; __Pyx_INCREF(Py_None); + __pyx_bstruct_values.buf = NULL; + __pyx_bstruct_out.buf = NULL; + __pyx_bstruct_points.buf = NULL; + __pyx_bstruct_vertices.buf = NULL; + __pyx_bstruct_xi.buf = NULL; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_xi), __pyx_ptype_5numpy_ndarray, 1, "xi", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_xi, (PyObject*)__pyx_v_xi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_bstride_0_xi = __pyx_bstruct_xi.strides[0]; __pyx_bstride_1_xi = __pyx_bstruct_xi.strides[1]; + __pyx_bshape_0_xi = __pyx_bstruct_xi.shape[0]; __pyx_bshape_1_xi = __pyx_bstruct_xi.shape[1]; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_values, (PyObject*)__pyx_t_2, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_values = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_values.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_values = __pyx_bstruct_values.strides[0]; __pyx_bstride_1_values = __pyx_bstruct_values.strides[1]; + __pyx_bshape_0_values = __pyx_bstruct_values.shape[0]; __pyx_bshape_1_values = __pyx_bstruct_values.shape[1]; + } + } + __pyx_t_2 = 0; + __pyx_v_values = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__points); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_points, (PyObject*)__pyx_t_3, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_points = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_points.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_points = __pyx_bstruct_points.strides[0]; __pyx_bstride_1_points = __pyx_bstruct_points.strides[1]; + __pyx_bshape_0_points = __pyx_bstruct_points.shape[0]; __pyx_bshape_1_points = __pyx_bstruct_points.shape[1]; + } + } + __pyx_t_3 = 0; + __pyx_v_points = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__tri); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__vertices); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = ((PyArrayObject *)__pyx_t_4); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_vertices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_vertices.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_vertices = __pyx_bstruct_vertices.strides[0]; __pyx_bstride_1_vertices = __pyx_bstruct_vertices.strides[1]; + __pyx_bshape_0_vertices = __pyx_bstruct_vertices.shape[0]; __pyx_bshape_1_vertices = __pyx_bstruct_vertices.shape[1]; + } + } + __pyx_t_5 = 0; + __pyx_v_vertices = ((PyArrayObject *)__pyx_t_4); + __pyx_t_4 = 0; + + + __pyx_v_ndim = (__pyx_v_xi->dimensions[1]); + + + __pyx_v_start = 0; + + + __pyx_t_4 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__fill_value); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = __pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_6 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_fill_value = __pyx_t_6; + + + __pyx_t_4 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__tri); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_v_info = __pyx_f_5scipy_7spatial_5qhull__get_delaunay_info(__pyx_t_4, 1, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyInt_to_py_npy_intp((__pyx_v_xi->dimensions[0])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_7 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = PyObject_GetAttr(__pyx_t_7, __pyx_n_s__shape); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_GetItemInt(__pyx_t_8, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_7) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_7); + __pyx_t_4 = 0; + __pyx_t_7 = 0; + __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_8); + __pyx_t_8 = 0; + __pyx_t_8 = PyDict_New(); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_8)); + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_9 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__double); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_8, ((PyObject *)__pyx_n_s__dtype), __pyx_t_9) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = PyEval_CallObjectWithKeywords(__pyx_t_1, __pyx_t_7, ((PyObject *)__pyx_t_8)); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0; + if (!(likely(((__pyx_t_9) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_9, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_10 = ((PyArrayObject *)__pyx_t_9); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __pyx_t_11 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_11 < 0)) { + PyErr_Fetch(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_v_out, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_13); Py_XDECREF(__pyx_t_14); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_12, __pyx_t_13, __pyx_t_14); + } + } + __pyx_bstride_0_out = __pyx_bstruct_out.strides[0]; __pyx_bstride_1_out = __pyx_bstruct_out.strides[1]; + __pyx_bshape_0_out = __pyx_bstruct_out.shape[0]; __pyx_bshape_1_out = __pyx_bstruct_out.shape[1]; + if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_10 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_out)); + __pyx_v_out = ((PyArrayObject *)__pyx_t_9); + __pyx_t_9 = 0; + + + __pyx_v_nvalues = (__pyx_v_out->dimensions[1]); + + + __pyx_t_9 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = PyObject_GetAttr(__pyx_t_9, __pyx_n_s__finfo); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_7 = PyObject_GetAttr(__pyx_t_9, __pyx_n_s__double); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_7); + __pyx_t_7 = 0; + __pyx_t_7 = PyObject_Call(__pyx_t_8, __pyx_t_9, NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = PyObject_GetAttr(__pyx_t_7, __pyx_n_s__eps); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = PyNumber_Multiply(__pyx_t_9, __pyx_int_100); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_v_eps); + __pyx_v_eps = __pyx_t_7; + __pyx_t_7 = 0; + + + { PyThreadState *_save; + Py_UNBLOCK_THREADS + { + + + __pyx_t_15 = (__pyx_v_xi->dimensions[0]); + for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_15; __pyx_t_11+=1) { + __pyx_v_i = __pyx_t_11; + + + __pyx_t_6 = __pyx_PyFloat_AsDouble(__pyx_v_eps); if (unlikely((__pyx_t_6 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L7;} + __pyx_v_isimplex = __pyx_f_5scipy_7spatial_5qhull__find_simplex(__pyx_v_info, __pyx_v_c, (((double *)__pyx_v_xi->data) + (__pyx_v_i * __pyx_v_ndim)), (&__pyx_v_start), __pyx_t_6); + + + __pyx_t_16 = (__pyx_v_isimplex == -1); + if (__pyx_t_16) { + + + __pyx_t_17 = __pyx_v_nvalues; + for (__pyx_t_18 = 0; __pyx_t_18 < __pyx_t_17; __pyx_t_18+=1) { + __pyx_v_k = __pyx_t_18; + + + __pyx_t_19 = __pyx_v_i; + __pyx_t_20 = __pyx_v_k; + if (__pyx_t_19 < 0) __pyx_t_19 += __pyx_bshape_0_out; + if (__pyx_t_20 < 0) __pyx_t_20 += __pyx_bshape_1_out; + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_out.buf, __pyx_t_19, __pyx_bstride_0_out, __pyx_t_20, __pyx_bstride_1_out) = __pyx_v_fill_value; + } + + + goto __pyx_L9_continue; + goto __pyx_L11; + } + __pyx_L11:; + + + __pyx_t_17 = __pyx_v_nvalues; + for (__pyx_t_18 = 0; __pyx_t_18 < __pyx_t_17; __pyx_t_18+=1) { + __pyx_v_k = __pyx_t_18; + + + __pyx_t_21 = __pyx_v_i; + __pyx_t_22 = __pyx_v_k; + if (__pyx_t_21 < 0) __pyx_t_21 += __pyx_bshape_0_out; + if (__pyx_t_22 < 0) __pyx_t_22 += __pyx_bshape_1_out; + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_out.buf, __pyx_t_21, __pyx_bstride_0_out, __pyx_t_22, __pyx_bstride_1_out) = 0; + } + + + __pyx_t_23 = (__pyx_v_ndim + 1); + for (__pyx_t_17 = 0; __pyx_t_17 < __pyx_t_23; __pyx_t_17+=1) { + __pyx_v_j = __pyx_t_17; + + + __pyx_t_18 = __pyx_v_nvalues; + for (__pyx_t_24 = 0; __pyx_t_24 < __pyx_t_18; __pyx_t_24+=1) { + __pyx_v_k = __pyx_t_24; + + + __pyx_t_25 = __pyx_v_isimplex; + __pyx_t_26 = __pyx_v_j; + if (__pyx_t_25 < 0) __pyx_t_25 += __pyx_bshape_0_vertices; + if (__pyx_t_26 < 0) __pyx_t_26 += __pyx_bshape_1_vertices; + __pyx_v_m = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_25, __pyx_bstride_0_vertices, __pyx_t_26, __pyx_bstride_1_vertices)); + + + __pyx_t_27 = __pyx_v_m; + __pyx_t_28 = __pyx_v_k; + if (__pyx_t_27 < 0) __pyx_t_27 += __pyx_bshape_0_values; + if (__pyx_t_28 < 0) __pyx_t_28 += __pyx_bshape_1_values; + __pyx_t_29 = __pyx_v_i; + __pyx_t_30 = __pyx_v_k; + if (__pyx_t_29 < 0) __pyx_t_29 += __pyx_bshape_0_out; + if (__pyx_t_30 < 0) __pyx_t_30 += __pyx_bshape_1_out; + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_out.buf, __pyx_t_29, __pyx_bstride_0_out, __pyx_t_30, __pyx_bstride_1_out) += ((__pyx_v_c[__pyx_v_j]) * (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_values.buf, __pyx_t_27, __pyx_bstride_0_values, __pyx_t_28, __pyx_bstride_1_values))); + } + } + __pyx_L9_continue:; + } + } + { + int __pyx_why; + __pyx_why = 0; goto __pyx_L8; + __pyx_L7: __pyx_why = 4; goto __pyx_L8; + __pyx_L8:; + + + Py_BLOCK_THREADS + switch (__pyx_why) { + case 4: goto __pyx_L1_error; + } + } + } + + + free(((void *)__pyx_v_info)); + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_out)); + __pyx_r = ((PyObject *)__pyx_v_out); + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xi); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_values); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("interpnd.LinearNDInterpolator._evaluate_double"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xi); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_values); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_values); + __Pyx_DECREF((PyObject *)__pyx_v_out); + __Pyx_XDECREF((PyObject *)__pyx_v_points); + __Pyx_XDECREF((PyObject *)__pyx_v_vertices); + __Pyx_DECREF(__pyx_v_eps); + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF((PyObject *)__pyx_v_xi); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_20LinearNDInterpolator__evaluate_complex(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static PyMethodDef __pyx_mdef_8interpnd_20LinearNDInterpolator__evaluate_complex = {__Pyx_NAMESTR("_evaluate_complex"), (PyCFunction)__pyx_pf_8interpnd_20LinearNDInterpolator__evaluate_complex, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)}; +static PyObject *__pyx_pf_8interpnd_20LinearNDInterpolator__evaluate_complex(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyArrayObject *__pyx_v_xi = 0; + PyArrayObject *__pyx_v_values = 0; + PyArrayObject *__pyx_v_out; + PyArrayObject *__pyx_v_points = 0; + PyArrayObject *__pyx_v_vertices = 0; + double __pyx_v_c[NPY_MAXDIMS]; + __pyx_t_double_complex __pyx_v_fill_value; + int __pyx_v_i; + int __pyx_v_j; + int __pyx_v_k; + int __pyx_v_m; + int __pyx_v_ndim; + int __pyx_v_isimplex; + int __pyx_v_start; + int __pyx_v_nvalues; + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_info; + PyObject *__pyx_v_eps; + Py_buffer __pyx_bstruct_xi; + Py_ssize_t __pyx_bstride_0_xi = 0; + Py_ssize_t __pyx_bstride_1_xi = 0; + Py_ssize_t __pyx_bshape_0_xi = 0; + Py_ssize_t __pyx_bshape_1_xi = 0; + Py_buffer __pyx_bstruct_vertices; + Py_ssize_t __pyx_bstride_0_vertices = 0; + Py_ssize_t __pyx_bstride_1_vertices = 0; + Py_ssize_t __pyx_bshape_0_vertices = 0; + Py_ssize_t __pyx_bshape_1_vertices = 0; + Py_buffer __pyx_bstruct_points; + Py_ssize_t __pyx_bstride_0_points = 0; + Py_ssize_t __pyx_bstride_1_points = 0; + Py_ssize_t __pyx_bshape_0_points = 0; + Py_ssize_t __pyx_bshape_1_points = 0; + Py_buffer __pyx_bstruct_values; + Py_ssize_t __pyx_bstride_0_values = 0; + Py_ssize_t __pyx_bstride_1_values = 0; + Py_ssize_t __pyx_bshape_0_values = 0; + Py_ssize_t __pyx_bshape_1_values = 0; + Py_buffer __pyx_bstruct_out; + Py_ssize_t __pyx_bstride_0_out = 0; + Py_ssize_t __pyx_bstride_1_out = 0; + Py_ssize_t __pyx_bshape_0_out = 0; + Py_ssize_t __pyx_bshape_1_out = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyArrayObject *__pyx_t_2 = NULL; + PyArrayObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyArrayObject *__pyx_t_5 = NULL; + __pyx_t_double_complex __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyArrayObject *__pyx_t_10 = NULL; + int __pyx_t_11; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + npy_intp __pyx_t_15; + double __pyx_t_16; + int __pyx_t_17; + int __pyx_t_18; + int __pyx_t_19; + int __pyx_t_20; + int __pyx_t_21; + int __pyx_t_22; + int __pyx_t_23; + int __pyx_t_24; + int __pyx_t_25; + int __pyx_t_26; + int __pyx_t_27; + long __pyx_t_28; + int __pyx_t_29; + int __pyx_t_30; + int __pyx_t_31; + int __pyx_t_32; + int __pyx_t_33; + int __pyx_t_34; + int __pyx_t_35; + int __pyx_t_36; + int __pyx_t_37; + int __pyx_t_38; + int __pyx_t_39; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__xi,0}; + __Pyx_RefNannySetupContext("_evaluate_complex"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__xi); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_evaluate_complex", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_evaluate_complex") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_xi = ((PyArrayObject *)values[1]); + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_xi = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 1)); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_evaluate_complex", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.LinearNDInterpolator._evaluate_complex"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF((PyObject *)__pyx_v_xi); + __pyx_v_out = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_eps = Py_None; __Pyx_INCREF(Py_None); + __pyx_bstruct_values.buf = NULL; + __pyx_bstruct_out.buf = NULL; + __pyx_bstruct_points.buf = NULL; + __pyx_bstruct_vertices.buf = NULL; + __pyx_bstruct_xi.buf = NULL; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_xi), __pyx_ptype_5numpy_ndarray, 1, "xi", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_xi, (PyObject*)__pyx_v_xi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_bstride_0_xi = __pyx_bstruct_xi.strides[0]; __pyx_bstride_1_xi = __pyx_bstruct_xi.strides[1]; + __pyx_bshape_0_xi = __pyx_bstruct_xi.shape[0]; __pyx_bshape_1_xi = __pyx_bstruct_xi.shape[1]; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[2]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_values, (PyObject*)__pyx_t_2, &__Pyx_TypeInfo_nn___pyx_t_5numpy_complex_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_values = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_values.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_values = __pyx_bstruct_values.strides[0]; __pyx_bstride_1_values = __pyx_bstruct_values.strides[1]; + __pyx_bshape_0_values = __pyx_bstruct_values.shape[0]; __pyx_bshape_1_values = __pyx_bstruct_values.shape[1]; + } + } + __pyx_t_2 = 0; + __pyx_v_values = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__points); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_points, (PyObject*)__pyx_t_3, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_points = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_points.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_points = __pyx_bstruct_points.strides[0]; __pyx_bstride_1_points = __pyx_bstruct_points.strides[1]; + __pyx_bshape_0_points = __pyx_bstruct_points.shape[0]; __pyx_bshape_1_points = __pyx_bstruct_points.shape[1]; + } + } + __pyx_t_3 = 0; + __pyx_v_points = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__tri); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__vertices); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = ((PyArrayObject *)__pyx_t_4); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_vertices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_vertices.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_vertices = __pyx_bstruct_vertices.strides[0]; __pyx_bstride_1_vertices = __pyx_bstruct_vertices.strides[1]; + __pyx_bshape_0_vertices = __pyx_bstruct_vertices.shape[0]; __pyx_bshape_1_vertices = __pyx_bstruct_vertices.shape[1]; + } + } + __pyx_t_5 = 0; + __pyx_v_vertices = ((PyArrayObject *)__pyx_t_4); + __pyx_t_4 = 0; + + + __pyx_v_ndim = (__pyx_v_xi->dimensions[1]); + + + __pyx_v_start = 0; + + + __pyx_t_4 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__fill_value); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = __Pyx_PyComplex_As___pyx_t_double_complex(__pyx_t_4); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_fill_value = __pyx_t_6; + + + __pyx_t_4 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__tri); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_v_info = __pyx_f_5scipy_7spatial_5qhull__get_delaunay_info(__pyx_t_4, 1, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyInt_to_py_npy_intp((__pyx_v_xi->dimensions[0])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_7 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = PyObject_GetAttr(__pyx_t_7, __pyx_n_s__shape); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_GetItemInt(__pyx_t_8, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_7) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_7); + __pyx_t_4 = 0; + __pyx_t_7 = 0; + __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_8); + __pyx_t_8 = 0; + __pyx_t_8 = PyDict_New(); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_8)); + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_9 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__complex); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_8, ((PyObject *)__pyx_n_s__dtype), __pyx_t_9) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = PyEval_CallObjectWithKeywords(__pyx_t_1, __pyx_t_7, ((PyObject *)__pyx_t_8)); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0; + if (!(likely(((__pyx_t_9) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_9, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_10 = ((PyArrayObject *)__pyx_t_9); + { + __Pyx_BufFmt_StackElem __pyx_stack[2]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __pyx_t_11 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_t_10, &__Pyx_TypeInfo_nn___pyx_t_5numpy_complex_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_11 < 0)) { + PyErr_Fetch(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_v_out, &__Pyx_TypeInfo_nn___pyx_t_5numpy_complex_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_13); Py_XDECREF(__pyx_t_14); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_12, __pyx_t_13, __pyx_t_14); + } + } + __pyx_bstride_0_out = __pyx_bstruct_out.strides[0]; __pyx_bstride_1_out = __pyx_bstruct_out.strides[1]; + __pyx_bshape_0_out = __pyx_bstruct_out.shape[0]; __pyx_bshape_1_out = __pyx_bstruct_out.shape[1]; + if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_10 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_out)); + __pyx_v_out = ((PyArrayObject *)__pyx_t_9); + __pyx_t_9 = 0; + + + __pyx_v_nvalues = (__pyx_v_out->dimensions[1]); + + + __pyx_t_9 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_8 = PyObject_GetAttr(__pyx_t_9, __pyx_n_s__finfo); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_7 = PyObject_GetAttr(__pyx_t_9, __pyx_n_s__double); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_7); + __pyx_t_7 = 0; + __pyx_t_7 = PyObject_Call(__pyx_t_8, __pyx_t_9, NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = PyObject_GetAttr(__pyx_t_7, __pyx_n_s__eps); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = PyNumber_Multiply(__pyx_t_9, __pyx_int_100); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_v_eps); + __pyx_v_eps = __pyx_t_7; + __pyx_t_7 = 0; + + + { PyThreadState *_save; + Py_UNBLOCK_THREADS + { + + + __pyx_t_15 = (__pyx_v_xi->dimensions[0]); + for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_15; __pyx_t_11+=1) { + __pyx_v_i = __pyx_t_11; + + + __pyx_t_16 = __pyx_PyFloat_AsDouble(__pyx_v_eps); if (unlikely((__pyx_t_16 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L7;} + __pyx_v_isimplex = __pyx_f_5scipy_7spatial_5qhull__find_simplex(__pyx_v_info, __pyx_v_c, (((double *)__pyx_v_xi->data) + (__pyx_v_i * __pyx_v_ndim)), (&__pyx_v_start), __pyx_t_16); + + + __pyx_t_17 = (__pyx_v_isimplex == -1); + if (__pyx_t_17) { + + + __pyx_t_18 = __pyx_v_nvalues; + for (__pyx_t_19 = 0; __pyx_t_19 < __pyx_t_18; __pyx_t_19+=1) { + __pyx_v_k = __pyx_t_19; + + + __pyx_t_20 = __pyx_v_i; + __pyx_t_21 = __pyx_v_k; + if (__pyx_t_20 < 0) __pyx_t_20 += __pyx_bshape_0_out; + if (__pyx_t_21 < 0) __pyx_t_21 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_20, __pyx_bstride_0_out, __pyx_t_21, __pyx_bstride_1_out)).real = __Pyx_CREAL(__pyx_v_fill_value); + + + __pyx_t_22 = __pyx_v_i; + __pyx_t_23 = __pyx_v_k; + if (__pyx_t_22 < 0) __pyx_t_22 += __pyx_bshape_0_out; + if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_22, __pyx_bstride_0_out, __pyx_t_23, __pyx_bstride_1_out)).imag = __Pyx_CIMAG(__pyx_v_fill_value); + } + + + goto __pyx_L9_continue; + goto __pyx_L11; + } + __pyx_L11:; + + + __pyx_t_18 = __pyx_v_nvalues; + for (__pyx_t_19 = 0; __pyx_t_19 < __pyx_t_18; __pyx_t_19+=1) { + __pyx_v_k = __pyx_t_19; + + + __pyx_t_24 = __pyx_v_i; + __pyx_t_25 = __pyx_v_k; + if (__pyx_t_24 < 0) __pyx_t_24 += __pyx_bshape_0_out; + if (__pyx_t_25 < 0) __pyx_t_25 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_24, __pyx_bstride_0_out, __pyx_t_25, __pyx_bstride_1_out)).real = 0; + + + __pyx_t_26 = __pyx_v_i; + __pyx_t_27 = __pyx_v_k; + if (__pyx_t_26 < 0) __pyx_t_26 += __pyx_bshape_0_out; + if (__pyx_t_27 < 0) __pyx_t_27 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_26, __pyx_bstride_0_out, __pyx_t_27, __pyx_bstride_1_out)).imag = 0; + } + + + __pyx_t_28 = (__pyx_v_ndim + 1); + for (__pyx_t_18 = 0; __pyx_t_18 < __pyx_t_28; __pyx_t_18+=1) { + __pyx_v_j = __pyx_t_18; + + + __pyx_t_19 = __pyx_v_nvalues; + for (__pyx_t_29 = 0; __pyx_t_29 < __pyx_t_19; __pyx_t_29+=1) { + __pyx_v_k = __pyx_t_29; + + + __pyx_t_30 = __pyx_v_isimplex; + __pyx_t_31 = __pyx_v_j; + if (__pyx_t_30 < 0) __pyx_t_30 += __pyx_bshape_0_vertices; + if (__pyx_t_31 < 0) __pyx_t_31 += __pyx_bshape_1_vertices; + __pyx_v_m = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_30, __pyx_bstride_0_vertices, __pyx_t_31, __pyx_bstride_1_vertices)); + + + __pyx_t_32 = __pyx_v_m; + __pyx_t_33 = __pyx_v_k; + if (__pyx_t_32 < 0) __pyx_t_32 += __pyx_bshape_0_values; + if (__pyx_t_33 < 0) __pyx_t_33 += __pyx_bshape_1_values; + __pyx_t_34 = __pyx_v_i; + __pyx_t_35 = __pyx_v_k; + if (__pyx_t_34 < 0) __pyx_t_34 += __pyx_bshape_0_out; + if (__pyx_t_35 < 0) __pyx_t_35 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_34, __pyx_bstride_0_out, __pyx_t_35, __pyx_bstride_1_out)).real += ((__pyx_v_c[__pyx_v_j]) * (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_values.buf, __pyx_t_32, __pyx_bstride_0_values, __pyx_t_33, __pyx_bstride_1_values)).real); + + + __pyx_t_36 = __pyx_v_m; + __pyx_t_37 = __pyx_v_k; + if (__pyx_t_36 < 0) __pyx_t_36 += __pyx_bshape_0_values; + if (__pyx_t_37 < 0) __pyx_t_37 += __pyx_bshape_1_values; + __pyx_t_38 = __pyx_v_i; + __pyx_t_39 = __pyx_v_k; + if (__pyx_t_38 < 0) __pyx_t_38 += __pyx_bshape_0_out; + if (__pyx_t_39 < 0) __pyx_t_39 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_38, __pyx_bstride_0_out, __pyx_t_39, __pyx_bstride_1_out)).imag += ((__pyx_v_c[__pyx_v_j]) * (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_values.buf, __pyx_t_36, __pyx_bstride_0_values, __pyx_t_37, __pyx_bstride_1_values)).imag); + } + } + __pyx_L9_continue:; + } + } + { + int __pyx_why; + __pyx_why = 0; goto __pyx_L8; + __pyx_L7: __pyx_why = 4; goto __pyx_L8; + __pyx_L8:; + + + Py_BLOCK_THREADS + switch (__pyx_why) { + case 4: goto __pyx_L1_error; + } + } + } + + + free(((void *)__pyx_v_info)); + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_out)); + __pyx_r = ((PyObject *)__pyx_v_out); + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xi); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_values); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("interpnd.LinearNDInterpolator._evaluate_complex"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xi); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_values); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_values); + __Pyx_DECREF((PyObject *)__pyx_v_out); + __Pyx_XDECREF((PyObject *)__pyx_v_points); + __Pyx_XDECREF((PyObject *)__pyx_v_vertices); + __Pyx_DECREF(__pyx_v_eps); + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF((PyObject *)__pyx_v_xi); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static int __pyx_f_8interpnd__estimate_gradients_2d_global(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, double *__pyx_v_data, int __pyx_v_maxiter, double __pyx_v_tol, double *__pyx_v_y) { + double __pyx_v_Q[(2 * 2)]; + double __pyx_v_s[2]; + double __pyx_v_r[2]; + int __pyx_v_ipoint; + int __pyx_v_iiter; + int __pyx_v_k; + __pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t __pyx_v_it; + double __pyx_v_f1; + double __pyx_v_f2; + double __pyx_v_df2; + double __pyx_v_ex; + double __pyx_v_ey; + double __pyx_v_L; + double __pyx_v_L3; + double __pyx_v_det; + double __pyx_v_err; + double __pyx_v_change; + int __pyx_r; + long __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + int __pyx_t_7; + + + __pyx_t_1 = (2 * __pyx_v_d->npoints); + for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) { + __pyx_v_ipoint = __pyx_t_2; + + + (__pyx_v_y[__pyx_v_ipoint]) = 0; + } + + + __pyx_t_2 = __pyx_v_maxiter; + for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { + __pyx_v_iiter = __pyx_t_3; + + + __pyx_v_err = 0; + + + __pyx_t_4 = __pyx_v_d->npoints; + for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { + __pyx_v_ipoint = __pyx_t_5; + + + for (__pyx_t_6 = 0; __pyx_t_6 < 4; __pyx_t_6+=1) { + __pyx_v_k = __pyx_t_6; + + + (__pyx_v_Q[__pyx_v_k]) = 0; + } + + + for (__pyx_t_6 = 0; __pyx_t_6 < 2; __pyx_t_6+=1) { + __pyx_v_k = __pyx_t_6; + + + (__pyx_v_s[__pyx_v_k]) = 0; + } + + + __pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_init((&__pyx_v_it), __pyx_v_d, __pyx_v_ipoint); + + + while (1) { + __pyx_t_7 = (__pyx_v_it.edge != -1); + if (!__pyx_t_7) break; + + + __pyx_v_ex = ((__pyx_v_d->points[((2 * __pyx_v_it.vertex2) + 0)]) - (__pyx_v_d->points[((2 * __pyx_v_it.vertex) + 0)])); + + + __pyx_v_ey = ((__pyx_v_d->points[((2 * __pyx_v_it.vertex2) + 1)]) - (__pyx_v_d->points[((2 * __pyx_v_it.vertex) + 1)])); + + + __pyx_v_L = sqrt((pow(__pyx_v_ex, 2) + pow(__pyx_v_ey, 2))); + + + __pyx_v_L3 = ((__pyx_v_L * __pyx_v_L) * __pyx_v_L); + + + __pyx_v_f1 = (__pyx_v_data[__pyx_v_it.vertex]); + + + __pyx_v_f2 = (__pyx_v_data[__pyx_v_it.vertex2]); + + + __pyx_v_df2 = (((-__pyx_v_ex) * (__pyx_v_y[((__pyx_v_it.vertex2 * 2) + 0)])) - (__pyx_v_ey * (__pyx_v_y[((__pyx_v_it.vertex2 * 2) + 1)]))); + + + (__pyx_v_Q[0]) += (((4 * __pyx_v_ex) * __pyx_v_ex) / __pyx_v_L3); + + + (__pyx_v_Q[1]) += (((4 * __pyx_v_ex) * __pyx_v_ey) / __pyx_v_L3); + + + (__pyx_v_Q[3]) += (((4 * __pyx_v_ey) * __pyx_v_ey) / __pyx_v_L3); + + + (__pyx_v_s[0]) += ((((6 * (__pyx_v_f1 - __pyx_v_f2)) - (2 * __pyx_v_df2)) * __pyx_v_ex) / __pyx_v_L3); + + + (__pyx_v_s[1]) += ((((6 * (__pyx_v_f1 - __pyx_v_f2)) - (2 * __pyx_v_df2)) * __pyx_v_ey) / __pyx_v_L3); + + + __pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_next((&__pyx_v_it)); + } + + + (__pyx_v_Q[2]) = (__pyx_v_Q[1]); + + + __pyx_v_det = (((__pyx_v_Q[0]) * (__pyx_v_Q[3])) - ((__pyx_v_Q[1]) * (__pyx_v_Q[2]))); + + + (__pyx_v_r[0]) = ((((__pyx_v_Q[3]) * (__pyx_v_s[0])) - ((__pyx_v_Q[1]) * (__pyx_v_s[1]))) / __pyx_v_det); + + + (__pyx_v_r[1]) = ((((-(__pyx_v_Q[2])) * (__pyx_v_s[0])) + ((__pyx_v_Q[0]) * (__pyx_v_s[1]))) / __pyx_v_det); + + + __pyx_v_change = fmax(fabs(((__pyx_v_y[((__pyx_v_it.vertex * 2) + 0)]) + (__pyx_v_r[0]))), fabs(((__pyx_v_y[((__pyx_v_it.vertex * 2) + 1)]) + (__pyx_v_r[1])))); + + + (__pyx_v_y[((__pyx_v_it.vertex * 2) + 0)]) = (-(__pyx_v_r[0])); + + + (__pyx_v_y[((__pyx_v_it.vertex * 2) + 1)]) = (-(__pyx_v_r[1])); + + + __pyx_v_change /= fmax(1.0, fmax(fabs((__pyx_v_r[0])), fabs((__pyx_v_r[1])))); + + + __pyx_v_err = fmax(__pyx_v_err, __pyx_v_change); + } + + + __pyx_t_7 = (__pyx_v_err < __pyx_v_tol); + if (__pyx_t_7) { + + + __pyx_r = (__pyx_v_iiter + 1); + goto __pyx_L0; + goto __pyx_L15; + } + __pyx_L15:; + } + + + __pyx_r = 0; + goto __pyx_L0; + + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_estimate_gradients_2d_global(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static PyObject *__pyx_pf_8interpnd_estimate_gradients_2d_global(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_tri = 0; + PyObject *__pyx_v_y = 0; + PyObject *__pyx_v_maxiter = 0; + PyObject *__pyx_v_tol = 0; + PyArrayObject *__pyx_v_data; + PyArrayObject *__pyx_v_grad; + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_info; + int __pyx_v_k; + int __pyx_v_ret; + int __pyx_v_nvalues; + PyObject *__pyx_v_rg; + PyObject *__pyx_v_ig; + PyObject *__pyx_v_r; + PyObject *__pyx_v_y_shape; + PyObject *__pyx_v_yi; + Py_buffer __pyx_bstruct_grad; + Py_ssize_t __pyx_bstride_0_grad = 0; + Py_ssize_t __pyx_bstride_1_grad = 0; + Py_ssize_t __pyx_bstride_2_grad = 0; + Py_ssize_t __pyx_bshape_0_grad = 0; + Py_ssize_t __pyx_bshape_1_grad = 0; + Py_ssize_t __pyx_bshape_2_grad = 0; + Py_buffer __pyx_bstruct_data; + Py_ssize_t __pyx_bstride_0_data = 0; + Py_ssize_t __pyx_bstride_1_data = 0; + Py_ssize_t __pyx_bshape_0_data = 0; + Py_ssize_t __pyx_bshape_1_data = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyArrayObject *__pyx_t_11 = NULL; + int __pyx_t_12; + int __pyx_t_13; + double __pyx_t_14; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__tri,&__pyx_n_s__y,&__pyx_n_s__maxiter,&__pyx_n_s__tol,0}; + __Pyx_RefNannySetupContext("estimate_gradients_2d_global"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[4] = {0,0,0,0}; + values[2] = ((PyObject *)__pyx_int_400); + values[3] = __pyx_k_10; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__tri); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__y); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("estimate_gradients_2d_global", 0, 2, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__maxiter); + if (unlikely(value)) { values[2] = value; kw_args--; } + } + case 3: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__tol); + if (unlikely(value)) { values[3] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "estimate_gradients_2d_global") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_tri = values[0]; + __pyx_v_y = values[1]; + __pyx_v_maxiter = values[2]; + __pyx_v_tol = values[3]; + } else { + __pyx_v_maxiter = ((PyObject *)__pyx_int_400); + __pyx_v_tol = __pyx_k_10; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: + __pyx_v_tol = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: + __pyx_v_maxiter = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: + __pyx_v_y = PyTuple_GET_ITEM(__pyx_args, 1); + __pyx_v_tri = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; + } + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("estimate_gradients_2d_global", 0, 2, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.estimate_gradients_2d_global"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_tri); + __Pyx_INCREF(__pyx_v_y); + __Pyx_INCREF(__pyx_v_maxiter); + __Pyx_INCREF(__pyx_v_tol); + __pyx_v_data = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_grad = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_rg = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_ig = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_r = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_y_shape = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_yi = Py_None; __Pyx_INCREF(Py_None); + __pyx_bstruct_data.buf = NULL; + __pyx_bstruct_grad.buf = NULL; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 486; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__asanyarray); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 486; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 486; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_y); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_y); + __Pyx_GIVEREF(__pyx_v_y); + __pyx_t_3 = PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 486; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_y); + __pyx_v_y = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_y, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_GetAttr(__pyx_v_tri, __pyx_n_s__npoints); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_t_3, Py_NE); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__pyx_t_4) { + + + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 489; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_11)); + PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_11)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_11)); + __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 489; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 489; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__issubdtype); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_GetAttr(__pyx_v_y, __pyx_n_s__dtype); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__complexfloating); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_3 = 0; + __pyx_t_5 = 0; + __pyx_t_5 = PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_4) { + + + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s_12); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyObject_GetAttr(__pyx_v_y, __pyx_n_s__real); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_tri); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_tri); + __Pyx_GIVEREF(__pyx_v_tri); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_1)); + if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__maxiter), __pyx_v_maxiter) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__tol), __pyx_v_tol) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyEval_CallObjectWithKeywords(__pyx_t_5, __pyx_t_2, ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_rg); + __pyx_v_rg = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s_12); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyObject_GetAttr(__pyx_v_y, __pyx_n_s__imag); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_tri); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_tri); + __Pyx_GIVEREF(__pyx_v_tri); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_1)); + if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__maxiter), __pyx_v_maxiter) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__tol), __pyx_v_tol) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = PyEval_CallObjectWithKeywords(__pyx_t_3, __pyx_t_2, ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_ig); + __pyx_v_ig = __pyx_t_5; + __pyx_t_5 = 0; + + + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyObject_GetAttr(__pyx_v_rg, __pyx_n_s__shape); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_5)); + if (PyDict_SetItem(__pyx_t_5, ((PyObject *)__pyx_n_s__dtype), ((PyObject*)&PyComplex_Type)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyEval_CallObjectWithKeywords(__pyx_t_1, __pyx_t_2, ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_v_r); + __pyx_v_r = __pyx_t_3; + __pyx_t_3 = 0; + + + if (PyObject_SetAttr(__pyx_v_r, __pyx_n_s__real, __pyx_v_rg) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 495; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + if (PyObject_SetAttr(__pyx_v_r, __pyx_n_s__imag, __pyx_v_ig) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 496; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_r); + __pyx_r = __pyx_v_r; + goto __pyx_L0; + goto __pyx_L7; + } + __pyx_L7:; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_y, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 499; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_v_y_shape); + __pyx_v_y_shape = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetAttr(__pyx_v_y, __pyx_n_s__ndim); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 501; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_1, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 501; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 501; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_4) { + + + __pyx_t_5 = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 502; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 502; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __Pyx_INCREF(Py_None); + PyTuple_SET_ITEM(__pyx_t_3, 1, Py_None); + __Pyx_GIVEREF(Py_None); + __pyx_t_5 = 0; + __pyx_t_5 = PyObject_GetItem(__pyx_v_y, __pyx_t_3); if (!__pyx_t_5) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 502; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_y); + __pyx_v_y = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L8; + } + __pyx_L8:; + + + __pyx_t_5 = PyObject_GetAttr(__pyx_v_y, __pyx_n_s__reshape); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_GetAttr(__pyx_v_tri, __pyx_n_s__npoints); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __Pyx_INCREF(__pyx_int_neg_1); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_neg_1); + __Pyx_GIVEREF(__pyx_int_neg_1); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_5, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__T); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_y); + __pyx_v_y = __pyx_t_2; + __pyx_t_2 = 0; + + + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__ascontiguousarray); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_y); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_y); + __Pyx_GIVEREF(__pyx_v_y); + __pyx_t_5 = PyObject_Call(__pyx_t_3, __pyx_t_2, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__astype); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 505; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_v_y); + __pyx_v_y = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__empty); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_GetAttr(__pyx_v_y, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_3, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyObject_GetAttr(__pyx_v_y, __pyx_n_s__shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_INCREF(__pyx_int_2); + PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_int_2); + __Pyx_GIVEREF(__pyx_int_2); + __pyx_t_2 = 0; + __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_v_yi); + __pyx_v_yi = __pyx_t_3; + __pyx_t_3 = 0; + + + if (!(likely(((__pyx_v_y) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_y, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 508; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = ((PyArrayObject *)__pyx_v_y); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_data); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_data, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_data, (PyObject*)__pyx_v_data, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_8, __pyx_t_9, __pyx_t_10); + } + } + __pyx_bstride_0_data = __pyx_bstruct_data.strides[0]; __pyx_bstride_1_data = __pyx_bstruct_data.strides[1]; + __pyx_bshape_0_data = __pyx_bstruct_data.shape[0]; __pyx_bshape_1_data = __pyx_bstruct_data.shape[1]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 508; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_6 = 0; + __Pyx_INCREF(__pyx_v_y); + __Pyx_DECREF(((PyObject *)__pyx_v_data)); + __pyx_v_data = ((PyArrayObject *)__pyx_v_y); + + + if (!(likely(((__pyx_v_yi) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_yi, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 509; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_11 = ((PyArrayObject *)__pyx_v_yi); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_grad); + __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_grad, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack); + if (unlikely(__pyx_t_7 < 0)) { + PyErr_Fetch(&__pyx_t_10, &__pyx_t_9, &__pyx_t_8); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_grad, (PyObject*)__pyx_v_grad, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_8); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_10, __pyx_t_9, __pyx_t_8); + } + } + __pyx_bstride_0_grad = __pyx_bstruct_grad.strides[0]; __pyx_bstride_1_grad = __pyx_bstruct_grad.strides[1]; __pyx_bstride_2_grad = __pyx_bstruct_grad.strides[2]; + __pyx_bshape_0_grad = __pyx_bstruct_grad.shape[0]; __pyx_bshape_1_grad = __pyx_bstruct_grad.shape[1]; __pyx_bshape_2_grad = __pyx_bstruct_grad.shape[2]; + if (unlikely(__pyx_t_7 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 509; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_11 = 0; + __Pyx_INCREF(__pyx_v_yi); + __Pyx_DECREF(((PyObject *)__pyx_v_grad)); + __pyx_v_grad = ((PyArrayObject *)__pyx_v_yi); + + + __pyx_v_info = __pyx_f_5scipy_7spatial_5qhull__get_delaunay_info(__pyx_v_tri, 0, 1); + + + __pyx_v_nvalues = (__pyx_v_data->dimensions[0]); + + + __pyx_t_7 = __pyx_v_nvalues; + for (__pyx_t_12 = 0; __pyx_t_12 < __pyx_t_7; __pyx_t_12+=1) { + __pyx_v_k = __pyx_t_12; + + + { PyThreadState *_save; + Py_UNBLOCK_THREADS + { + + + __pyx_t_13 = __Pyx_PyInt_AsInt(__pyx_v_maxiter); if (unlikely((__pyx_t_13 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 519; __pyx_clineno = __LINE__; goto __pyx_L14;} + + + __pyx_t_14 = __pyx_PyFloat_AsDouble(__pyx_v_tol); if (unlikely((__pyx_t_14 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 520; __pyx_clineno = __LINE__; goto __pyx_L14;} + + + __pyx_v_ret = __pyx_f_8interpnd__estimate_gradients_2d_global(__pyx_v_info, (((double *)__pyx_v_data->data) + (__pyx_v_info->npoints * __pyx_v_k)), __pyx_t_13, __pyx_t_14, (((double *)__pyx_v_grad->data) + ((2 * __pyx_v_info->npoints) * __pyx_v_k))); + } + { + int __pyx_why; + __pyx_why = 0; goto __pyx_L15; + __pyx_L14: __pyx_why = 4; goto __pyx_L15; + __pyx_L15:; + + + Py_BLOCK_THREADS + switch (__pyx_why) { + case 4: goto __pyx_L1_error; + } + } + } + + + __pyx_t_4 = (__pyx_v_ret == 0); + if (__pyx_t_4) { + + + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__warnings); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 524; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__warn); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 524; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + + __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s_14); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 526; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 524; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_13)); + PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_kp_s_13)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13)); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 524; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L17; + } + __pyx_L17:; + } + + + free(__pyx_v_info); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_3 = PyObject_GetAttr(__pyx_v_yi, __pyx_n_s__transpose); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_int_1); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_int_1); + __Pyx_GIVEREF(__pyx_int_1); + __Pyx_INCREF(__pyx_int_0); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_int_0); + __Pyx_GIVEREF(__pyx_int_0); + __Pyx_INCREF(__pyx_int_2); + PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_int_2); + __Pyx_GIVEREF(__pyx_int_2); + __pyx_t_1 = PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__reshape); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_int_2); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_int_2); + __Pyx_GIVEREF(__pyx_int_2); + __pyx_t_3 = PyNumber_Add(__pyx_v_y_shape, __pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 529; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_grad); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_data); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("interpnd.estimate_gradients_2d_global"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_grad); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_data); + __pyx_L2:; + __Pyx_DECREF((PyObject *)__pyx_v_data); + __Pyx_DECREF((PyObject *)__pyx_v_grad); + __Pyx_DECREF(__pyx_v_rg); + __Pyx_DECREF(__pyx_v_ig); + __Pyx_DECREF(__pyx_v_r); + __Pyx_DECREF(__pyx_v_y_shape); + __Pyx_DECREF(__pyx_v_yi); + __Pyx_DECREF(__pyx_v_tri); + __Pyx_DECREF(__pyx_v_y); + __Pyx_DECREF(__pyx_v_maxiter); + __Pyx_DECREF(__pyx_v_tol); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static double __pyx_f_8interpnd__clough_tocher_2d_single_double(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, int __pyx_v_isimplex, double *__pyx_v_b, double *__pyx_v_f, double *__pyx_v_df) { + double __pyx_v_c3000; + double __pyx_v_c0300; + double __pyx_v_c0030; + double __pyx_v_c0003; + double __pyx_v_c2100; + double __pyx_v_c2010; + double __pyx_v_c2001; + double __pyx_v_c0210; + double __pyx_v_c0201; + double __pyx_v_c0021; + double __pyx_v_c1200; + double __pyx_v_c1020; + double __pyx_v_c1002; + double __pyx_v_c0120; + double __pyx_v_c0102; + double __pyx_v_c0012; + double __pyx_v_c1101; + double __pyx_v_c1011; + double __pyx_v_c0111; + double __pyx_v_f1; + double __pyx_v_f2; + double __pyx_v_f3; + double __pyx_v_df12; + double __pyx_v_df13; + double __pyx_v_df21; + double __pyx_v_df23; + double __pyx_v_df31; + double __pyx_v_df32; + double __pyx_v_g1; + double __pyx_v_g2; + double __pyx_v_g3; + double __pyx_v_e12x; + double __pyx_v_e12y; + double __pyx_v_e23x; + double __pyx_v_e23y; + double __pyx_v_e31x; + double __pyx_v_e31y; + double __pyx_v_e14x; + double __pyx_v_e14y; + double __pyx_v_e24x; + double __pyx_v_e24y; + double __pyx_v_e34x; + double __pyx_v_e34y; + double __pyx_v_w; + double __pyx_v_minval; + double __pyx_v_b1; + double __pyx_v_b2; + double __pyx_v_b3; + double __pyx_v_b4; + int __pyx_v_k; + int __pyx_v_itri; + double __pyx_v_c[3]; + double __pyx_v_y[2]; + double __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + + + __pyx_v_e12x = ((__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 1)])))]) - (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 0)])))])); + + + __pyx_v_e12y = ((__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 1)])))]) - (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 0)])))])); + + + __pyx_v_e23x = ((__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 2)])))]) - (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 1)])))])); + + + __pyx_v_e23y = ((__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 2)])))]) - (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 1)])))])); + + + __pyx_v_e31x = ((__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 0)])))]) - (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 2)])))])); + + + __pyx_v_e31y = ((__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 0)])))]) - (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 2)])))])); + + + __pyx_v_e14x = ((__pyx_v_e12x - __pyx_v_e31x) / 3); + + + __pyx_v_e14y = ((__pyx_v_e12y - __pyx_v_e31y) / 3); + + + __pyx_v_e24x = (((-__pyx_v_e12x) + __pyx_v_e23x) / 3); + + + __pyx_v_e24y = (((-__pyx_v_e12y) + __pyx_v_e23y) / 3); + + + __pyx_v_e34x = ((__pyx_v_e31x - __pyx_v_e23x) / 3); + + + __pyx_v_e34y = ((__pyx_v_e31y - __pyx_v_e23y) / 3); + + + __pyx_v_f1 = (__pyx_v_f[0]); + + + __pyx_v_f2 = (__pyx_v_f[1]); + + + __pyx_v_f3 = (__pyx_v_f[2]); + + + __pyx_v_df12 = (((__pyx_v_df[0]) * __pyx_v_e12x) + ((__pyx_v_df[1]) * __pyx_v_e12y)); + + + __pyx_v_df21 = (-(((__pyx_v_df[2]) * __pyx_v_e12x) + ((__pyx_v_df[3]) * __pyx_v_e12y))); + + + __pyx_v_df23 = (((__pyx_v_df[2]) * __pyx_v_e23x) + ((__pyx_v_df[3]) * __pyx_v_e23y)); + + + __pyx_v_df32 = (-(((__pyx_v_df[4]) * __pyx_v_e23x) + ((__pyx_v_df[5]) * __pyx_v_e23y))); + + + __pyx_v_df31 = (((__pyx_v_df[4]) * __pyx_v_e31x) + ((__pyx_v_df[5]) * __pyx_v_e31y)); + + + __pyx_v_df13 = (-(((__pyx_v_df[0]) * __pyx_v_e31x) + ((__pyx_v_df[1]) * __pyx_v_e31y))); + + + __pyx_v_c3000 = __pyx_v_f1; + + + __pyx_v_c2100 = ((__pyx_v_df12 + (3 * __pyx_v_c3000)) / 3); + + + __pyx_v_c2010 = ((__pyx_v_df13 + (3 * __pyx_v_c3000)) / 3); + + + __pyx_v_c0300 = __pyx_v_f2; + + + __pyx_v_c1200 = ((__pyx_v_df21 + (3 * __pyx_v_c0300)) / 3); + + + __pyx_v_c0210 = ((__pyx_v_df23 + (3 * __pyx_v_c0300)) / 3); + + + __pyx_v_c0030 = __pyx_v_f3; + + + __pyx_v_c1020 = ((__pyx_v_df31 + (3 * __pyx_v_c0030)) / 3); + + + __pyx_v_c0120 = ((__pyx_v_df32 + (3 * __pyx_v_c0030)) / 3); + + + __pyx_v_c2001 = (((__pyx_v_c2100 + __pyx_v_c2010) + __pyx_v_c3000) / 3); + + + __pyx_v_c0201 = (((__pyx_v_c1200 + __pyx_v_c0300) + __pyx_v_c0210) / 3); + + + __pyx_v_c0021 = (((__pyx_v_c1020 + __pyx_v_c0120) + __pyx_v_c0030) / 3); + + + for (__pyx_t_1 = 0; __pyx_t_1 < 3; __pyx_t_1+=1) { + __pyx_v_k = __pyx_t_1; + + + __pyx_v_itri = (__pyx_v_d->neighbors[((3 * __pyx_v_isimplex) + __pyx_v_k)]); + + + __pyx_t_2 = (__pyx_v_itri == -1); + if (__pyx_t_2) { + + + switch (__pyx_v_k) { + case 0: + + + __pyx_v_g1 = ((-2.0) / 3); + break; + + + case 1: + + + __pyx_v_g2 = ((-2.0) / 3); + break; + + + case 2: + + + __pyx_v_g3 = ((-2.0) / 3); + break; + } + + + goto __pyx_L3_continue; + goto __pyx_L5; + } + __pyx_L5:; + + + (__pyx_v_y[0]) = ((((__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 0)])))]) + (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 1)])))])) + (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 2)])))])) / 3); + + + (__pyx_v_y[1]) = ((((__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 0)])))]) + (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 1)])))])) + (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 2)])))])) / 3); + + + __pyx_f_5scipy_7spatial_5qhull__barycentric_coordinates(2, (__pyx_v_d->transform + ((__pyx_v_isimplex * 2) * 3)), __pyx_v_y, __pyx_v_c); + + + switch (__pyx_v_k) { + case 0: + + + __pyx_v_g1 = ((((2 * (__pyx_v_c[2])) + (__pyx_v_c[1])) - 1) / ((2 - (3 * (__pyx_v_c[2]))) - (3 * (__pyx_v_c[1])))); + break; + + + case 1: + + + __pyx_v_g2 = ((((2 * (__pyx_v_c[0])) + (__pyx_v_c[2])) - 1) / ((2 - (3 * (__pyx_v_c[0]))) - (3 * (__pyx_v_c[2])))); + break; + + + case 2: + + + __pyx_v_g3 = ((((2 * (__pyx_v_c[1])) + (__pyx_v_c[0])) - 1) / ((2 - (3 * (__pyx_v_c[1]))) - (3 * (__pyx_v_c[0])))); + break; + } + __pyx_L3_continue:; + } + + + __pyx_v_c0111 = (((__pyx_v_g1 * ((((-__pyx_v_c0300) + (3 * __pyx_v_c0210)) - (3 * __pyx_v_c0120)) + __pyx_v_c0030)) + (((((-__pyx_v_c0300) + (2 * __pyx_v_c0210)) - __pyx_v_c0120) + __pyx_v_c0021) + __pyx_v_c0201)) / 2); + + + __pyx_v_c1011 = (((__pyx_v_g2 * ((((-__pyx_v_c0030) + (3 * __pyx_v_c1020)) - (3 * __pyx_v_c2010)) + __pyx_v_c3000)) + (((((-__pyx_v_c0030) + (2 * __pyx_v_c1020)) - __pyx_v_c2010) + __pyx_v_c2001) + __pyx_v_c0021)) / 2); + + + __pyx_v_c1101 = (((__pyx_v_g3 * ((((-__pyx_v_c3000) + (3 * __pyx_v_c2100)) - (3 * __pyx_v_c1200)) + __pyx_v_c0300)) + (((((-__pyx_v_c3000) + (2 * __pyx_v_c2100)) - __pyx_v_c1200) + __pyx_v_c2001) + __pyx_v_c0201)) / 2); + + + __pyx_v_c1002 = (((__pyx_v_c1101 + __pyx_v_c1011) + __pyx_v_c2001) / 3); + + + __pyx_v_c0102 = (((__pyx_v_c1101 + __pyx_v_c0111) + __pyx_v_c0201) / 3); + + + __pyx_v_c0012 = (((__pyx_v_c1011 + __pyx_v_c0111) + __pyx_v_c0021) / 3); + + + __pyx_v_c0003 = (((__pyx_v_c1002 + __pyx_v_c0102) + __pyx_v_c0012) / 3); + + + __pyx_v_minval = (__pyx_v_b[0]); + + + for (__pyx_t_1 = 0; __pyx_t_1 < 3; __pyx_t_1+=1) { + __pyx_v_k = __pyx_t_1; + + + __pyx_t_2 = ((__pyx_v_b[__pyx_v_k]) < __pyx_v_minval); + if (__pyx_t_2) { + + + __pyx_v_minval = (__pyx_v_b[__pyx_v_k]); + goto __pyx_L8; + } + __pyx_L8:; + } + + + __pyx_v_b1 = ((__pyx_v_b[0]) - __pyx_v_minval); + + + __pyx_v_b2 = ((__pyx_v_b[1]) - __pyx_v_minval); + + + __pyx_v_b3 = ((__pyx_v_b[2]) - __pyx_v_minval); + + + __pyx_v_b4 = (3 * __pyx_v_minval); + + + __pyx_v_w = (((((((((((((((((((pow(__pyx_v_b1, 3) * __pyx_v_c3000) + (((3 * pow(__pyx_v_b1, 2)) * __pyx_v_b2) * __pyx_v_c2100)) + (((3 * pow(__pyx_v_b1, 2)) * __pyx_v_b3) * __pyx_v_c2010)) + (((3 * pow(__pyx_v_b1, 2)) * __pyx_v_b4) * __pyx_v_c2001)) + (((3 * __pyx_v_b1) * pow(__pyx_v_b2, 2)) * __pyx_v_c1200)) + ((((6 * __pyx_v_b1) * __pyx_v_b2) * __pyx_v_b4) * __pyx_v_c1101)) + (((3 * __pyx_v_b1) * pow(__pyx_v_b3, 2)) * __pyx_v_c1020)) + ((((6 * __pyx_v_b1) * __pyx_v_b3) * __pyx_v_b4) * __pyx_v_c1011)) + (((3 * __pyx_v_b1) * pow(__pyx_v_b4, 2)) * __pyx_v_c1002)) + (pow(__pyx_v_b2, 3) * __pyx_v_c0300)) + (((3 * pow(__pyx_v_b2, 2)) * __pyx_v_b3) * __pyx_v_c0210)) + (((3 * pow(__pyx_v_b2, 2)) * __pyx_v_b4) * __pyx_v_c0201)) + (((3 * __pyx_v_b2) * pow(__pyx_v_b3, 2)) * __pyx_v_c0120)) + ((((6 * __pyx_v_b2) * __pyx_v_b3) * __pyx_v_b4) * __pyx_v_c0111)) + (((3 * __pyx_v_b2) * pow(__pyx_v_b4, 2)) * __pyx_v_c0102)) + (pow(__pyx_v_b3, 3) * __pyx_v_c0030)) + (((3 * pow(__pyx_v_b3, 2)) * __pyx_v_b4) * __pyx_v_c0021)) + (((3 * __pyx_v_b3) * pow(__pyx_v_b4, 2)) * __pyx_v_c0012)) + (pow(__pyx_v_b4, 3) * __pyx_v_c0003)); + + + __pyx_r = __pyx_v_w; + goto __pyx_L0; + + __pyx_r = 0; + __pyx_L0:; + return __pyx_r; +} + + + +static __pyx_t_double_complex __pyx_f_8interpnd__clough_tocher_2d_single_complex(__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_d, int __pyx_v_isimplex, double *__pyx_v_b, __pyx_t_double_complex *__pyx_v_f, __pyx_t_double_complex *__pyx_v_df) { + __pyx_t_double_complex __pyx_v_c3000; + __pyx_t_double_complex __pyx_v_c0300; + __pyx_t_double_complex __pyx_v_c0030; + __pyx_t_double_complex __pyx_v_c0003; + __pyx_t_double_complex __pyx_v_c2100; + __pyx_t_double_complex __pyx_v_c2010; + __pyx_t_double_complex __pyx_v_c2001; + __pyx_t_double_complex __pyx_v_c0210; + __pyx_t_double_complex __pyx_v_c0201; + __pyx_t_double_complex __pyx_v_c0021; + __pyx_t_double_complex __pyx_v_c1200; + __pyx_t_double_complex __pyx_v_c1020; + __pyx_t_double_complex __pyx_v_c1002; + __pyx_t_double_complex __pyx_v_c0120; + __pyx_t_double_complex __pyx_v_c0102; + __pyx_t_double_complex __pyx_v_c0012; + __pyx_t_double_complex __pyx_v_c1101; + __pyx_t_double_complex __pyx_v_c1011; + __pyx_t_double_complex __pyx_v_c0111; + __pyx_t_double_complex __pyx_v_f1; + __pyx_t_double_complex __pyx_v_f2; + __pyx_t_double_complex __pyx_v_f3; + __pyx_t_double_complex __pyx_v_df12; + __pyx_t_double_complex __pyx_v_df13; + __pyx_t_double_complex __pyx_v_df21; + __pyx_t_double_complex __pyx_v_df23; + __pyx_t_double_complex __pyx_v_df31; + __pyx_t_double_complex __pyx_v_df32; + double __pyx_v_g1; + double __pyx_v_g2; + double __pyx_v_g3; + double __pyx_v_e12x; + double __pyx_v_e12y; + double __pyx_v_e23x; + double __pyx_v_e23y; + double __pyx_v_e31x; + double __pyx_v_e31y; + double __pyx_v_e14x; + double __pyx_v_e14y; + double __pyx_v_e24x; + double __pyx_v_e24y; + double __pyx_v_e34x; + double __pyx_v_e34y; + __pyx_t_double_complex __pyx_v_w; + double __pyx_v_minval; + double __pyx_v_b1; + double __pyx_v_b2; + double __pyx_v_b3; + double __pyx_v_b4; + int __pyx_v_k; + int __pyx_v_itri; + double __pyx_v_c[3]; + double __pyx_v_y[2]; + __pyx_t_double_complex __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + + + __pyx_v_e12x = ((__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 1)])))]) - (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 0)])))])); + + + __pyx_v_e12y = ((__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 1)])))]) - (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 0)])))])); + + + __pyx_v_e23x = ((__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 2)])))]) - (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 1)])))])); + + + __pyx_v_e23y = ((__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 2)])))]) - (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 1)])))])); + + + __pyx_v_e31x = ((__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 0)])))]) - (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 2)])))])); + + + __pyx_v_e31y = ((__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 0)])))]) - (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_isimplex) + 2)])))])); + + + __pyx_v_e14x = ((__pyx_v_e12x - __pyx_v_e31x) / 3); + + + __pyx_v_e14y = ((__pyx_v_e12y - __pyx_v_e31y) / 3); + + + __pyx_v_e24x = (((-__pyx_v_e12x) + __pyx_v_e23x) / 3); + + + __pyx_v_e24y = (((-__pyx_v_e12y) + __pyx_v_e23y) / 3); + + + __pyx_v_e34x = ((__pyx_v_e31x - __pyx_v_e23x) / 3); + + + __pyx_v_e34y = ((__pyx_v_e31y - __pyx_v_e23y) / 3); + + + __pyx_v_f1 = (__pyx_v_f[0]); + + + __pyx_v_f2 = (__pyx_v_f[1]); + + + __pyx_v_f3 = (__pyx_v_f[2]); + + + __pyx_v_df12 = __Pyx_c_sum(__Pyx_c_prod((__pyx_v_df[0]), __pyx_t_double_complex_from_parts(__pyx_v_e12x, 0)), __Pyx_c_prod((__pyx_v_df[1]), __pyx_t_double_complex_from_parts(__pyx_v_e12y, 0))); + + + __pyx_v_df21 = __Pyx_c_neg(__Pyx_c_sum(__Pyx_c_prod((__pyx_v_df[2]), __pyx_t_double_complex_from_parts(__pyx_v_e12x, 0)), __Pyx_c_prod((__pyx_v_df[3]), __pyx_t_double_complex_from_parts(__pyx_v_e12y, 0)))); + + + __pyx_v_df23 = __Pyx_c_sum(__Pyx_c_prod((__pyx_v_df[2]), __pyx_t_double_complex_from_parts(__pyx_v_e23x, 0)), __Pyx_c_prod((__pyx_v_df[3]), __pyx_t_double_complex_from_parts(__pyx_v_e23y, 0))); + + + __pyx_v_df32 = __Pyx_c_neg(__Pyx_c_sum(__Pyx_c_prod((__pyx_v_df[4]), __pyx_t_double_complex_from_parts(__pyx_v_e23x, 0)), __Pyx_c_prod((__pyx_v_df[5]), __pyx_t_double_complex_from_parts(__pyx_v_e23y, 0)))); + + + __pyx_v_df31 = __Pyx_c_sum(__Pyx_c_prod((__pyx_v_df[4]), __pyx_t_double_complex_from_parts(__pyx_v_e31x, 0)), __Pyx_c_prod((__pyx_v_df[5]), __pyx_t_double_complex_from_parts(__pyx_v_e31y, 0))); + + + __pyx_v_df13 = __Pyx_c_neg(__Pyx_c_sum(__Pyx_c_prod((__pyx_v_df[0]), __pyx_t_double_complex_from_parts(__pyx_v_e31x, 0)), __Pyx_c_prod((__pyx_v_df[1]), __pyx_t_double_complex_from_parts(__pyx_v_e31y, 0)))); + + + __pyx_v_c3000 = __pyx_v_f1; + + + __pyx_v_c2100 = __Pyx_c_quot(__Pyx_c_sum(__pyx_v_df12, __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c3000)), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c2010 = __Pyx_c_quot(__Pyx_c_sum(__pyx_v_df13, __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c3000)), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c0300 = __pyx_v_f2; + + + __pyx_v_c1200 = __Pyx_c_quot(__Pyx_c_sum(__pyx_v_df21, __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c0300)), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c0210 = __Pyx_c_quot(__Pyx_c_sum(__pyx_v_df23, __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c0300)), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c0030 = __pyx_v_f3; + + + __pyx_v_c1020 = __Pyx_c_quot(__Pyx_c_sum(__pyx_v_df31, __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c0030)), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c0120 = __Pyx_c_quot(__Pyx_c_sum(__pyx_v_df32, __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c0030)), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c2001 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_sum(__pyx_v_c2100, __pyx_v_c2010), __pyx_v_c3000), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c0201 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_sum(__pyx_v_c1200, __pyx_v_c0300), __pyx_v_c0210), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c0021 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_sum(__pyx_v_c1020, __pyx_v_c0120), __pyx_v_c0030), __pyx_t_double_complex_from_parts(3, 0)); + + + for (__pyx_t_1 = 0; __pyx_t_1 < 3; __pyx_t_1+=1) { + __pyx_v_k = __pyx_t_1; + + + __pyx_v_itri = (__pyx_v_d->neighbors[((3 * __pyx_v_isimplex) + __pyx_v_k)]); + + + __pyx_t_2 = (__pyx_v_itri == -1); + if (__pyx_t_2) { + + + switch (__pyx_v_k) { + case 0: + + + __pyx_v_g1 = ((-2.0) / 3); + break; + + + case 1: + + + __pyx_v_g2 = ((-2.0) / 3); + break; + + + case 2: + + + __pyx_v_g3 = ((-2.0) / 3); + break; + } + + + goto __pyx_L3_continue; + goto __pyx_L5; + } + __pyx_L5:; + + + (__pyx_v_y[0]) = ((((__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 0)])))]) + (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 1)])))])) + (__pyx_v_d->points[(0 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 2)])))])) / 3); + + + (__pyx_v_y[1]) = ((((__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 0)])))]) + (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 1)])))])) + (__pyx_v_d->points[(1 + (2 * (__pyx_v_d->vertices[((3 * __pyx_v_itri) + 2)])))])) / 3); + + + __pyx_f_5scipy_7spatial_5qhull__barycentric_coordinates(2, (__pyx_v_d->transform + ((__pyx_v_isimplex * 2) * 3)), __pyx_v_y, __pyx_v_c); + + + switch (__pyx_v_k) { + case 0: + + + __pyx_v_g1 = ((((2 * (__pyx_v_c[2])) + (__pyx_v_c[1])) - 1) / ((2 - (3 * (__pyx_v_c[2]))) - (3 * (__pyx_v_c[1])))); + break; + + + case 1: + + + __pyx_v_g2 = ((((2 * (__pyx_v_c[0])) + (__pyx_v_c[2])) - 1) / ((2 - (3 * (__pyx_v_c[0]))) - (3 * (__pyx_v_c[2])))); + break; + + + case 2: + + + __pyx_v_g3 = ((((2 * (__pyx_v_c[1])) + (__pyx_v_c[0])) - 1) / ((2 - (3 * (__pyx_v_c[1]))) - (3 * (__pyx_v_c[0])))); + break; + } + __pyx_L3_continue:; + } + + + __pyx_v_c0111 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_prod(__pyx_t_double_complex_from_parts(__pyx_v_g1, 0), __Pyx_c_sum(__Pyx_c_diff(__Pyx_c_sum(__Pyx_c_neg(__pyx_v_c0300), __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c0210)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c0120)), __pyx_v_c0030)), __Pyx_c_sum(__Pyx_c_sum(__Pyx_c_diff(__Pyx_c_sum(__Pyx_c_neg(__pyx_v_c0300), __Pyx_c_prod(__pyx_t_double_complex_from_parts(2, 0), __pyx_v_c0210)), __pyx_v_c0120), __pyx_v_c0021), __pyx_v_c0201)), __pyx_t_double_complex_from_parts(2, 0)); + + + __pyx_v_c1011 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_prod(__pyx_t_double_complex_from_parts(__pyx_v_g2, 0), __Pyx_c_sum(__Pyx_c_diff(__Pyx_c_sum(__Pyx_c_neg(__pyx_v_c0030), __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c1020)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c2010)), __pyx_v_c3000)), __Pyx_c_sum(__Pyx_c_sum(__Pyx_c_diff(__Pyx_c_sum(__Pyx_c_neg(__pyx_v_c0030), __Pyx_c_prod(__pyx_t_double_complex_from_parts(2, 0), __pyx_v_c1020)), __pyx_v_c2010), __pyx_v_c2001), __pyx_v_c0021)), __pyx_t_double_complex_from_parts(2, 0)); + + + __pyx_v_c1101 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_prod(__pyx_t_double_complex_from_parts(__pyx_v_g3, 0), __Pyx_c_sum(__Pyx_c_diff(__Pyx_c_sum(__Pyx_c_neg(__pyx_v_c3000), __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c2100)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(3, 0), __pyx_v_c1200)), __pyx_v_c0300)), __Pyx_c_sum(__Pyx_c_sum(__Pyx_c_diff(__Pyx_c_sum(__Pyx_c_neg(__pyx_v_c3000), __Pyx_c_prod(__pyx_t_double_complex_from_parts(2, 0), __pyx_v_c2100)), __pyx_v_c1200), __pyx_v_c2001), __pyx_v_c0201)), __pyx_t_double_complex_from_parts(2, 0)); + + + __pyx_v_c1002 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_sum(__pyx_v_c1101, __pyx_v_c1011), __pyx_v_c2001), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c0102 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_sum(__pyx_v_c1101, __pyx_v_c0111), __pyx_v_c0201), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c0012 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_sum(__pyx_v_c1011, __pyx_v_c0111), __pyx_v_c0021), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_c0003 = __Pyx_c_quot(__Pyx_c_sum(__Pyx_c_sum(__pyx_v_c1002, __pyx_v_c0102), __pyx_v_c0012), __pyx_t_double_complex_from_parts(3, 0)); + + + __pyx_v_minval = (__pyx_v_b[0]); + + + for (__pyx_t_1 = 0; __pyx_t_1 < 3; __pyx_t_1+=1) { + __pyx_v_k = __pyx_t_1; + + + __pyx_t_2 = ((__pyx_v_b[__pyx_v_k]) < __pyx_v_minval); + if (__pyx_t_2) { + + + __pyx_v_minval = (__pyx_v_b[__pyx_v_k]); + goto __pyx_L8; + } + __pyx_L8:; + } + + + __pyx_v_b1 = ((__pyx_v_b[0]) - __pyx_v_minval); + + + __pyx_v_b2 = ((__pyx_v_b[1]) - __pyx_v_minval); + + + __pyx_v_b3 = ((__pyx_v_b[2]) - __pyx_v_minval); + + + __pyx_v_b4 = (3 * __pyx_v_minval); + + + __pyx_v_w = __Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_sum(__Pyx_c_prod(__pyx_t_double_complex_from_parts(pow(__pyx_v_b1, 3), 0), __pyx_v_c3000), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * pow(__pyx_v_b1, 2)) * __pyx_v_b2), 0), __pyx_v_c2100)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * pow(__pyx_v_b1, 2)) * __pyx_v_b3), 0), __pyx_v_c2010)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * pow(__pyx_v_b1, 2)) * __pyx_v_b4), 0), __pyx_v_c2001)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * __pyx_v_b1) * pow(__pyx_v_b2, 2)), 0), __pyx_v_c1200)), __Pyx_c_prod(__pyx_t_double_complex_from_parts((((6 * __pyx_v_b1) * __pyx_v_b2) * __pyx_v_b4), 0), __pyx_v_c1101)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * __pyx_v_b1) * pow(__pyx_v_b3, 2)), 0), __pyx_v_c1020)), __Pyx_c_prod(__pyx_t_double_complex_from_parts((((6 * __pyx_v_b1) * __pyx_v_b3) * __pyx_v_b4), 0), __pyx_v_c1011)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * __pyx_v_b1) * pow(__pyx_v_b4, 2)), 0), __pyx_v_c1002)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(pow(__pyx_v_b2, 3), 0), __pyx_v_c0300)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * pow(__pyx_v_b2, 2)) * __pyx_v_b3), 0), __pyx_v_c0210)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * pow(__pyx_v_b2, 2)) * __pyx_v_b4), 0), __pyx_v_c0201)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * __pyx_v_b2) * pow(__pyx_v_b3, 2)), 0), __pyx_v_c0120)), __Pyx_c_prod(__pyx_t_double_complex_from_parts((((6 * __pyx_v_b2) * __pyx_v_b3) * __pyx_v_b4), 0), __pyx_v_c0111)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * __pyx_v_b2) * pow(__pyx_v_b4, 2)), 0), __pyx_v_c0102)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(pow(__pyx_v_b3, 3), 0), __pyx_v_c0030)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * pow(__pyx_v_b3, 2)) * __pyx_v_b4), 0), __pyx_v_c0021)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(((3 * __pyx_v_b3) * pow(__pyx_v_b4, 2)), 0), __pyx_v_c0012)), __Pyx_c_prod(__pyx_t_double_complex_from_parts(pow(__pyx_v_b4, 3), 0), __pyx_v_c0003)); + + + __pyx_r = __pyx_v_w; + goto __pyx_L0; + + __pyx_r = __pyx_t_double_complex_from_parts(0, 0); + __pyx_L0:; + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_26CloughTocher2DInterpolator___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static PyMethodDef __pyx_mdef_8interpnd_26CloughTocher2DInterpolator___init__ = {__Pyx_NAMESTR("__init__"), (PyCFunction)__pyx_pf_8interpnd_26CloughTocher2DInterpolator___init__, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)}; +static PyObject *__pyx_pf_8interpnd_26CloughTocher2DInterpolator___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_points = 0; + PyObject *__pyx_v_values = 0; + PyObject *__pyx_v_fill_value = 0; + PyObject *__pyx_v_tol = 0; + PyObject *__pyx_v_maxiter = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__points,&__pyx_n_s__values,&__pyx_n_s__fill_value,&__pyx_n_s__tol,&__pyx_n_s__maxiter,0}; + __Pyx_RefNannySetupContext("__init__"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[6] = {0,0,0,0,0,0}; + values[3] = __pyx_k_15; + values[4] = __pyx_k_16; + values[5] = ((PyObject *)__pyx_int_400); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); + case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__points); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 6, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__values); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 6, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 3: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fill_value); + if (unlikely(value)) { values[3] = value; kw_args--; } + } + case 4: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__tol); + if (unlikely(value)) { values[4] = value; kw_args--; } + } + case 5: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__maxiter); + if (unlikely(value)) { values[5] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_points = values[1]; + __pyx_v_values = values[2]; + __pyx_v_fill_value = values[3]; + __pyx_v_tol = values[4]; + __pyx_v_maxiter = values[5]; + } else { + __pyx_v_fill_value = __pyx_k_15; + __pyx_v_tol = __pyx_k_16; + __pyx_v_maxiter = ((PyObject *)__pyx_int_400); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 6: + __pyx_v_maxiter = PyTuple_GET_ITEM(__pyx_args, 5); + case 5: + __pyx_v_tol = PyTuple_GET_ITEM(__pyx_args, 4); + case 4: + __pyx_v_fill_value = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: + __pyx_v_values = PyTuple_GET_ITEM(__pyx_args, 2); + __pyx_v_points = PyTuple_GET_ITEM(__pyx_args, 1); + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; + } + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 0, 3, 6, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.CloughTocher2DInterpolator.__init__"); + return NULL; + __pyx_L4_argument_unpacking_done:; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__NDInterpolatorBase); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1050; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____init__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1050; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1050; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_self); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self); + __Pyx_GIVEREF(__pyx_v_self); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __Pyx_INCREF(__pyx_v_values); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_values); + __Pyx_GIVEREF(__pyx_v_values); + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1050; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__ndim), __pyx_int_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1050; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__fill_value), __pyx_v_fill_value) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1050; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_2, __pyx_t_1, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1050; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__qhull); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1052; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__Delaunay); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1052; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1052; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_points); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_points); + __Pyx_GIVEREF(__pyx_v_points); + __pyx_t_1 = PyObject_Call(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1052; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__tri, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1052; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s_12); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__tri); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_4 = 0; + __pyx_t_3 = 0; + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + + + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__tol), __pyx_v_tol) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__maxiter), __pyx_v_maxiter) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyEval_CallObjectWithKeywords(__pyx_t_1, __pyx_t_2, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + + + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__grad, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1053; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("interpnd.CloughTocher2DInterpolator.__init__"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_26CloughTocher2DInterpolator__evaluate_double(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static PyMethodDef __pyx_mdef_8interpnd_26CloughTocher2DInterpolator__evaluate_double = {__Pyx_NAMESTR("_evaluate_double"), (PyCFunction)__pyx_pf_8interpnd_26CloughTocher2DInterpolator__evaluate_double, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)}; +static PyObject *__pyx_pf_8interpnd_26CloughTocher2DInterpolator__evaluate_double(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyArrayObject *__pyx_v_xi = 0; + PyArrayObject *__pyx_v_values = 0; + PyArrayObject *__pyx_v_grad = 0; + PyArrayObject *__pyx_v_out; + PyArrayObject *__pyx_v_points = 0; + PyArrayObject *__pyx_v_vertices = 0; + double __pyx_v_c[NPY_MAXDIMS]; + double __pyx_v_f[(NPY_MAXDIMS + 1)]; + double __pyx_v_df[((2 * NPY_MAXDIMS) + 2)]; + double __pyx_v_w; + double __pyx_v_fill_value; + int __pyx_v_i; + int __pyx_v_j; + int __pyx_v_k; + int __pyx_v_ndim; + int __pyx_v_isimplex; + int __pyx_v_start; + int __pyx_v_nvalues; + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_info; + PyObject *__pyx_v_eps; + Py_buffer __pyx_bstruct_xi; + Py_ssize_t __pyx_bstride_0_xi = 0; + Py_ssize_t __pyx_bstride_1_xi = 0; + Py_ssize_t __pyx_bshape_0_xi = 0; + Py_ssize_t __pyx_bshape_1_xi = 0; + Py_buffer __pyx_bstruct_out; + Py_ssize_t __pyx_bstride_0_out = 0; + Py_ssize_t __pyx_bstride_1_out = 0; + Py_ssize_t __pyx_bshape_0_out = 0; + Py_ssize_t __pyx_bshape_1_out = 0; + Py_buffer __pyx_bstruct_vertices; + Py_ssize_t __pyx_bstride_0_vertices = 0; + Py_ssize_t __pyx_bstride_1_vertices = 0; + Py_ssize_t __pyx_bshape_0_vertices = 0; + Py_ssize_t __pyx_bshape_1_vertices = 0; + Py_buffer __pyx_bstruct_points; + Py_ssize_t __pyx_bstride_0_points = 0; + Py_ssize_t __pyx_bstride_1_points = 0; + Py_ssize_t __pyx_bshape_0_points = 0; + Py_ssize_t __pyx_bshape_1_points = 0; + Py_buffer __pyx_bstruct_values; + Py_ssize_t __pyx_bstride_0_values = 0; + Py_ssize_t __pyx_bstride_1_values = 0; + Py_ssize_t __pyx_bshape_0_values = 0; + Py_ssize_t __pyx_bshape_1_values = 0; + Py_buffer __pyx_bstruct_grad; + Py_ssize_t __pyx_bstride_0_grad = 0; + Py_ssize_t __pyx_bstride_1_grad = 0; + Py_ssize_t __pyx_bstride_2_grad = 0; + Py_ssize_t __pyx_bshape_0_grad = 0; + Py_ssize_t __pyx_bshape_1_grad = 0; + Py_ssize_t __pyx_bshape_2_grad = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyArrayObject *__pyx_t_2 = NULL; + PyArrayObject *__pyx_t_3 = NULL; + PyArrayObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + double __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyArrayObject *__pyx_t_11 = NULL; + int __pyx_t_12; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + npy_intp __pyx_t_16; + int __pyx_t_17; + int __pyx_t_18; + int __pyx_t_19; + int __pyx_t_20; + int __pyx_t_21; + long __pyx_t_22; + int __pyx_t_23; + int __pyx_t_24; + int __pyx_t_25; + __pyx_t_5numpy_int_t __pyx_t_26; + int __pyx_t_27; + int __pyx_t_28; + int __pyx_t_29; + __pyx_t_5numpy_int_t __pyx_t_30; + int __pyx_t_31; + long __pyx_t_32; + int __pyx_t_33; + int __pyx_t_34; + __pyx_t_5numpy_int_t __pyx_t_35; + int __pyx_t_36; + long __pyx_t_37; + int __pyx_t_38; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__xi,0}; + __Pyx_RefNannySetupContext("_evaluate_double"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__xi); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_evaluate_double", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1058; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_evaluate_double") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1058; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_xi = ((PyArrayObject *)values[1]); + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_xi = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 1)); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_evaluate_double", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1058; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.CloughTocher2DInterpolator._evaluate_double"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF((PyObject *)__pyx_v_xi); + __pyx_v_out = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_eps = Py_None; __Pyx_INCREF(Py_None); + __pyx_bstruct_values.buf = NULL; + __pyx_bstruct_grad.buf = NULL; + __pyx_bstruct_out.buf = NULL; + __pyx_bstruct_points.buf = NULL; + __pyx_bstruct_vertices.buf = NULL; + __pyx_bstruct_xi.buf = NULL; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_xi), __pyx_ptype_5numpy_ndarray, 1, "xi", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1058; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_xi, (PyObject*)__pyx_v_xi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1058; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_bstride_0_xi = __pyx_bstruct_xi.strides[0]; __pyx_bstride_1_xi = __pyx_bstruct_xi.strides[1]; + __pyx_bshape_0_xi = __pyx_bstruct_xi.shape[0]; __pyx_bshape_1_xi = __pyx_bstruct_xi.shape[1]; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1059; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1059; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_values, (PyObject*)__pyx_t_2, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_values = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_values.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1059; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_values = __pyx_bstruct_values.strides[0]; __pyx_bstride_1_values = __pyx_bstruct_values.strides[1]; + __pyx_bshape_0_values = __pyx_bstruct_values.shape[0]; __pyx_bshape_1_values = __pyx_bstruct_values.shape[1]; + } + } + __pyx_t_2 = 0; + __pyx_v_values = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__grad); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1060; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1060; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_grad, (PyObject*)__pyx_t_3, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) { + __pyx_v_grad = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_grad.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1060; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_grad = __pyx_bstruct_grad.strides[0]; __pyx_bstride_1_grad = __pyx_bstruct_grad.strides[1]; __pyx_bstride_2_grad = __pyx_bstruct_grad.strides[2]; + __pyx_bshape_0_grad = __pyx_bstruct_grad.shape[0]; __pyx_bshape_1_grad = __pyx_bstruct_grad.shape[1]; __pyx_bshape_2_grad = __pyx_bstruct_grad.shape[2]; + } + } + __pyx_t_3 = 0; + __pyx_v_grad = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__points); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1062; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1062; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_points, (PyObject*)__pyx_t_4, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_points = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_points.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1062; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_points = __pyx_bstruct_points.strides[0]; __pyx_bstride_1_points = __pyx_bstruct_points.strides[1]; + __pyx_bshape_0_points = __pyx_bstruct_points.shape[0]; __pyx_bshape_1_points = __pyx_bstruct_points.shape[1]; + } + } + __pyx_t_4 = 0; + __pyx_v_points = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__tri); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1063; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__vertices); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1063; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1063; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_vertices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_vertices.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1063; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_vertices = __pyx_bstruct_vertices.strides[0]; __pyx_bstride_1_vertices = __pyx_bstruct_vertices.strides[1]; + __pyx_bshape_0_vertices = __pyx_bstruct_vertices.shape[0]; __pyx_bshape_1_vertices = __pyx_bstruct_vertices.shape[1]; + } + } + __pyx_t_6 = 0; + __pyx_v_vertices = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + + __pyx_v_ndim = (__pyx_v_xi->dimensions[1]); + + + __pyx_v_start = 0; + + + __pyx_t_5 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__fill_value); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1074; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_5); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1074; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_v_fill_value = __pyx_t_7; + + + __pyx_t_5 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__tri); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1076; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_v_info = __pyx_f_5scipy_7spatial_5qhull__get_delaunay_info(__pyx_t_5, 1, 1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_PyInt_to_py_npy_intp((__pyx_v_xi->dimensions[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_8 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_9 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__shape); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = __Pyx_GetItemInt(__pyx_t_9, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_8) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = PyTuple_New(2); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_9, 1, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_8); + __pyx_t_5 = 0; + __pyx_t_8 = 0; + __pyx_t_8 = PyTuple_New(1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_9); + __Pyx_GIVEREF(__pyx_t_9); + __pyx_t_9 = 0; + __pyx_t_9 = PyDict_New(); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_9)); + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_10 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__double); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyDict_SetItem(__pyx_t_9, ((PyObject *)__pyx_n_s__dtype), __pyx_t_10) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_10 = PyEval_CallObjectWithKeywords(__pyx_t_1, __pyx_t_8, ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_9)); __pyx_t_9 = 0; + if (!(likely(((__pyx_t_10) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_10, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_11 = ((PyArrayObject *)__pyx_t_10); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __pyx_t_12 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_12 < 0)) { + PyErr_Fetch(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_v_out, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_13); Py_XDECREF(__pyx_t_14); Py_XDECREF(__pyx_t_15); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_13, __pyx_t_14, __pyx_t_15); + } + } + __pyx_bstride_0_out = __pyx_bstruct_out.strides[0]; __pyx_bstride_1_out = __pyx_bstruct_out.strides[1]; + __pyx_bshape_0_out = __pyx_bstruct_out.shape[0]; __pyx_bshape_1_out = __pyx_bstruct_out.shape[1]; + if (unlikely(__pyx_t_12 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1078; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_11 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_out)); + __pyx_v_out = ((PyArrayObject *)__pyx_t_10); + __pyx_t_10 = 0; + + + __pyx_v_nvalues = (__pyx_v_out->dimensions[1]); + + + __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1081; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_9 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__finfo); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1081; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1081; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_8 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__double); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1081; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1081; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_8); + __pyx_t_8 = 0; + __pyx_t_8 = PyObject_Call(__pyx_t_9, __pyx_t_10, NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1081; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_10 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__eps); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1081; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = PyNumber_Multiply(__pyx_t_10, __pyx_int_100); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1081; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_DECREF(__pyx_v_eps); + __pyx_v_eps = __pyx_t_8; + __pyx_t_8 = 0; + + + { PyThreadState *_save; + Py_UNBLOCK_THREADS + { + + + __pyx_t_16 = (__pyx_v_xi->dimensions[0]); + for (__pyx_t_12 = 0; __pyx_t_12 < __pyx_t_16; __pyx_t_12+=1) { + __pyx_v_i = __pyx_t_12; + + + __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_v_eps); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1089; __pyx_clineno = __LINE__; goto __pyx_L7;} + __pyx_v_isimplex = __pyx_f_5scipy_7spatial_5qhull__find_simplex(__pyx_v_info, __pyx_v_c, (((double *)__pyx_v_xi->data) + (__pyx_v_i * __pyx_v_ndim)), (&__pyx_v_start), __pyx_t_7); + + + __pyx_t_17 = (__pyx_v_isimplex == -1); + if (__pyx_t_17) { + + + __pyx_t_18 = __pyx_v_nvalues; + for (__pyx_t_19 = 0; __pyx_t_19 < __pyx_t_18; __pyx_t_19+=1) { + __pyx_v_k = __pyx_t_19; + + + __pyx_t_20 = __pyx_v_i; + __pyx_t_21 = __pyx_v_k; + if (__pyx_t_20 < 0) __pyx_t_20 += __pyx_bshape_0_out; + if (__pyx_t_21 < 0) __pyx_t_21 += __pyx_bshape_1_out; + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_out.buf, __pyx_t_20, __pyx_bstride_0_out, __pyx_t_21, __pyx_bstride_1_out) = __pyx_v_fill_value; + } + + + goto __pyx_L9_continue; + goto __pyx_L11; + } + __pyx_L11:; + + + __pyx_t_18 = __pyx_v_nvalues; + for (__pyx_t_19 = 0; __pyx_t_19 < __pyx_t_18; __pyx_t_19+=1) { + __pyx_v_k = __pyx_t_19; + + + __pyx_t_22 = (__pyx_v_ndim + 1); + for (__pyx_t_23 = 0; __pyx_t_23 < __pyx_t_22; __pyx_t_23+=1) { + __pyx_v_j = __pyx_t_23; + + + __pyx_t_24 = __pyx_v_isimplex; + __pyx_t_25 = __pyx_v_j; + if (__pyx_t_24 < 0) __pyx_t_24 += __pyx_bshape_0_vertices; + if (__pyx_t_25 < 0) __pyx_t_25 += __pyx_bshape_1_vertices; + __pyx_t_26 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_24, __pyx_bstride_0_vertices, __pyx_t_25, __pyx_bstride_1_vertices)); + __pyx_t_27 = __pyx_v_k; + if (__pyx_t_26 < 0) __pyx_t_26 += __pyx_bshape_0_values; + if (__pyx_t_27 < 0) __pyx_t_27 += __pyx_bshape_1_values; + (__pyx_v_f[__pyx_v_j]) = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_values.buf, __pyx_t_26, __pyx_bstride_0_values, __pyx_t_27, __pyx_bstride_1_values)); + + + __pyx_t_28 = __pyx_v_isimplex; + __pyx_t_29 = __pyx_v_j; + if (__pyx_t_28 < 0) __pyx_t_28 += __pyx_bshape_0_vertices; + if (__pyx_t_29 < 0) __pyx_t_29 += __pyx_bshape_1_vertices; + __pyx_t_30 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_28, __pyx_bstride_0_vertices, __pyx_t_29, __pyx_bstride_1_vertices)); + __pyx_t_31 = __pyx_v_k; + __pyx_t_32 = 0; + if (__pyx_t_30 < 0) __pyx_t_30 += __pyx_bshape_0_grad; + if (__pyx_t_31 < 0) __pyx_t_31 += __pyx_bshape_1_grad; + if (__pyx_t_32 < 0) __pyx_t_32 += __pyx_bshape_2_grad; + (__pyx_v_df[(2 * __pyx_v_j)]) = (*__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_grad.buf, __pyx_t_30, __pyx_bstride_0_grad, __pyx_t_31, __pyx_bstride_1_grad, __pyx_t_32, __pyx_bstride_2_grad)); + + + __pyx_t_33 = __pyx_v_isimplex; + __pyx_t_34 = __pyx_v_j; + if (__pyx_t_33 < 0) __pyx_t_33 += __pyx_bshape_0_vertices; + if (__pyx_t_34 < 0) __pyx_t_34 += __pyx_bshape_1_vertices; + __pyx_t_35 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_33, __pyx_bstride_0_vertices, __pyx_t_34, __pyx_bstride_1_vertices)); + __pyx_t_36 = __pyx_v_k; + __pyx_t_37 = 1; + if (__pyx_t_35 < 0) __pyx_t_35 += __pyx_bshape_0_grad; + if (__pyx_t_36 < 0) __pyx_t_36 += __pyx_bshape_1_grad; + if (__pyx_t_37 < 0) __pyx_t_37 += __pyx_bshape_2_grad; + (__pyx_v_df[((2 * __pyx_v_j) + 1)]) = (*__Pyx_BufPtrStrided3d(__pyx_t_5numpy_double_t *, __pyx_bstruct_grad.buf, __pyx_t_35, __pyx_bstride_0_grad, __pyx_t_36, __pyx_bstride_1_grad, __pyx_t_37, __pyx_bstride_2_grad)); + } + + + __pyx_v_w = __pyx_f_8interpnd__clough_tocher_2d_single_double(__pyx_v_info, __pyx_v_isimplex, __pyx_v_c, __pyx_v_f, __pyx_v_df); + + + __pyx_t_23 = __pyx_v_i; + __pyx_t_38 = __pyx_v_k; + if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_bshape_0_out; + if (__pyx_t_38 < 0) __pyx_t_38 += __pyx_bshape_1_out; + *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_bstruct_out.buf, __pyx_t_23, __pyx_bstride_0_out, __pyx_t_38, __pyx_bstride_1_out) = __pyx_v_w; + } + __pyx_L9_continue:; + } + } + { + int __pyx_why; + __pyx_why = 0; goto __pyx_L8; + __pyx_L7: __pyx_why = 4; goto __pyx_L8; + __pyx_L8:; + + + Py_BLOCK_THREADS + switch (__pyx_why) { + case 4: goto __pyx_L1_error; + } + } + } + + + free(((void *)__pyx_v_info)); + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_out)); + __pyx_r = ((PyObject *)__pyx_v_out); + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xi); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_values); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_grad); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("interpnd.CloughTocher2DInterpolator._evaluate_double"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xi); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_values); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_grad); + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_values); + __Pyx_XDECREF((PyObject *)__pyx_v_grad); + __Pyx_DECREF((PyObject *)__pyx_v_out); + __Pyx_XDECREF((PyObject *)__pyx_v_points); + __Pyx_XDECREF((PyObject *)__pyx_v_vertices); + __Pyx_DECREF(__pyx_v_eps); + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF((PyObject *)__pyx_v_xi); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static PyObject *__pyx_pf_8interpnd_26CloughTocher2DInterpolator__evaluate_complex(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); +static PyMethodDef __pyx_mdef_8interpnd_26CloughTocher2DInterpolator__evaluate_complex = {__Pyx_NAMESTR("_evaluate_complex"), (PyCFunction)__pyx_pf_8interpnd_26CloughTocher2DInterpolator__evaluate_complex, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)}; +static PyObject *__pyx_pf_8interpnd_26CloughTocher2DInterpolator__evaluate_complex(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_self = 0; + PyArrayObject *__pyx_v_xi = 0; + PyArrayObject *__pyx_v_values = 0; + PyArrayObject *__pyx_v_grad = 0; + PyArrayObject *__pyx_v_out; + PyArrayObject *__pyx_v_points = 0; + PyArrayObject *__pyx_v_vertices = 0; + double __pyx_v_c[NPY_MAXDIMS]; + __pyx_t_double_complex __pyx_v_f[(NPY_MAXDIMS + 1)]; + __pyx_t_double_complex __pyx_v_df[((2 * NPY_MAXDIMS) + 2)]; + __pyx_t_double_complex __pyx_v_w; + __pyx_t_double_complex __pyx_v_fill_value; + int __pyx_v_i; + int __pyx_v_j; + int __pyx_v_k; + int __pyx_v_ndim; + int __pyx_v_isimplex; + int __pyx_v_start; + int __pyx_v_nvalues; + __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *__pyx_v_info; + PyObject *__pyx_v_eps; + Py_buffer __pyx_bstruct_xi; + Py_ssize_t __pyx_bstride_0_xi = 0; + Py_ssize_t __pyx_bstride_1_xi = 0; + Py_ssize_t __pyx_bshape_0_xi = 0; + Py_ssize_t __pyx_bshape_1_xi = 0; + Py_buffer __pyx_bstruct_out; + Py_ssize_t __pyx_bstride_0_out = 0; + Py_ssize_t __pyx_bstride_1_out = 0; + Py_ssize_t __pyx_bshape_0_out = 0; + Py_ssize_t __pyx_bshape_1_out = 0; + Py_buffer __pyx_bstruct_vertices; + Py_ssize_t __pyx_bstride_0_vertices = 0; + Py_ssize_t __pyx_bstride_1_vertices = 0; + Py_ssize_t __pyx_bshape_0_vertices = 0; + Py_ssize_t __pyx_bshape_1_vertices = 0; + Py_buffer __pyx_bstruct_points; + Py_ssize_t __pyx_bstride_0_points = 0; + Py_ssize_t __pyx_bstride_1_points = 0; + Py_ssize_t __pyx_bshape_0_points = 0; + Py_ssize_t __pyx_bshape_1_points = 0; + Py_buffer __pyx_bstruct_values; + Py_ssize_t __pyx_bstride_0_values = 0; + Py_ssize_t __pyx_bstride_1_values = 0; + Py_ssize_t __pyx_bshape_0_values = 0; + Py_ssize_t __pyx_bshape_1_values = 0; + Py_buffer __pyx_bstruct_grad; + Py_ssize_t __pyx_bstride_0_grad = 0; + Py_ssize_t __pyx_bstride_1_grad = 0; + Py_ssize_t __pyx_bstride_2_grad = 0; + Py_ssize_t __pyx_bshape_0_grad = 0; + Py_ssize_t __pyx_bshape_1_grad = 0; + Py_ssize_t __pyx_bshape_2_grad = 0; + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + PyArrayObject *__pyx_t_2 = NULL; + PyArrayObject *__pyx_t_3 = NULL; + PyArrayObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + __pyx_t_double_complex __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyArrayObject *__pyx_t_11 = NULL; + int __pyx_t_12; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + npy_intp __pyx_t_16; + double __pyx_t_17; + int __pyx_t_18; + int __pyx_t_19; + int __pyx_t_20; + int __pyx_t_21; + int __pyx_t_22; + int __pyx_t_23; + int __pyx_t_24; + long __pyx_t_25; + int __pyx_t_26; + int __pyx_t_27; + int __pyx_t_28; + __pyx_t_5numpy_int_t __pyx_t_29; + int __pyx_t_30; + int __pyx_t_31; + int __pyx_t_32; + __pyx_t_5numpy_int_t __pyx_t_33; + int __pyx_t_34; + int __pyx_t_35; + int __pyx_t_36; + __pyx_t_5numpy_int_t __pyx_t_37; + int __pyx_t_38; + long __pyx_t_39; + int __pyx_t_40; + int __pyx_t_41; + __pyx_t_5numpy_int_t __pyx_t_42; + int __pyx_t_43; + long __pyx_t_44; + int __pyx_t_45; + int __pyx_t_46; + __pyx_t_5numpy_int_t __pyx_t_47; + int __pyx_t_48; + long __pyx_t_49; + int __pyx_t_50; + int __pyx_t_51; + __pyx_t_5numpy_int_t __pyx_t_52; + int __pyx_t_53; + long __pyx_t_54; + int __pyx_t_55; + int __pyx_t_56; + int __pyx_t_57; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__xi,0}; + __Pyx_RefNannySetupContext("_evaluate_complex"); + __pyx_self = __pyx_self; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + PyObject* values[2] = {0,0}; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__xi); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_evaluate_complex", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1114; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_evaluate_complex") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1114; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + __pyx_v_self = values[0]; + __pyx_v_xi = ((PyArrayObject *)values[1]); + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); + __pyx_v_xi = ((PyArrayObject *)PyTuple_GET_ITEM(__pyx_args, 1)); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_evaluate_complex", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1114; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("interpnd.CloughTocher2DInterpolator._evaluate_complex"); + return NULL; + __pyx_L4_argument_unpacking_done:; + __Pyx_INCREF(__pyx_v_self); + __Pyx_INCREF((PyObject *)__pyx_v_xi); + __pyx_v_out = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_eps = Py_None; __Pyx_INCREF(Py_None); + __pyx_bstruct_values.buf = NULL; + __pyx_bstruct_grad.buf = NULL; + __pyx_bstruct_out.buf = NULL; + __pyx_bstruct_points.buf = NULL; + __pyx_bstruct_vertices.buf = NULL; + __pyx_bstruct_xi.buf = NULL; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_xi), __pyx_ptype_5numpy_ndarray, 1, "xi", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1114; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_xi, (PyObject*)__pyx_v_xi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1114; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_bstride_0_xi = __pyx_bstruct_xi.strides[0]; __pyx_bstride_1_xi = __pyx_bstruct_xi.strides[1]; + __pyx_bshape_0_xi = __pyx_bstruct_xi.shape[0]; __pyx_bshape_1_xi = __pyx_bstruct_xi.shape[1]; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1115; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1115; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[2]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_values, (PyObject*)__pyx_t_2, &__Pyx_TypeInfo_nn___pyx_t_5numpy_complex_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_values = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_values.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1115; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_values = __pyx_bstruct_values.strides[0]; __pyx_bstride_1_values = __pyx_bstruct_values.strides[1]; + __pyx_bshape_0_values = __pyx_bstruct_values.shape[0]; __pyx_bshape_1_values = __pyx_bstruct_values.shape[1]; + } + } + __pyx_t_2 = 0; + __pyx_v_values = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__grad); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1116; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1116; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[2]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_grad, (PyObject*)__pyx_t_3, &__Pyx_TypeInfo_nn___pyx_t_5numpy_complex_t, PyBUF_FORMAT| PyBUF_STRIDES, 3, 0, __pyx_stack) == -1)) { + __pyx_v_grad = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_grad.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1116; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_grad = __pyx_bstruct_grad.strides[0]; __pyx_bstride_1_grad = __pyx_bstruct_grad.strides[1]; __pyx_bstride_2_grad = __pyx_bstruct_grad.strides[2]; + __pyx_bshape_0_grad = __pyx_bstruct_grad.shape[0]; __pyx_bshape_1_grad = __pyx_bstruct_grad.shape[1]; __pyx_bshape_2_grad = __pyx_bstruct_grad.shape[2]; + } + } + __pyx_t_3 = 0; + __pyx_v_grad = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__points); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1118; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1118; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_points, (PyObject*)__pyx_t_4, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_points = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_points.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1118; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_points = __pyx_bstruct_points.strides[0]; __pyx_bstride_1_points = __pyx_bstruct_points.strides[1]; + __pyx_bshape_0_points = __pyx_bstruct_points.shape[0]; __pyx_bshape_1_points = __pyx_bstruct_points.shape[1]; + } + } + __pyx_t_4 = 0; + __pyx_v_points = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + + __pyx_t_1 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__tri); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1119; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__vertices); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1119; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1119; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_vertices, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_vertices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_bstruct_vertices.buf = NULL; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1119; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } else {__pyx_bstride_0_vertices = __pyx_bstruct_vertices.strides[0]; __pyx_bstride_1_vertices = __pyx_bstruct_vertices.strides[1]; + __pyx_bshape_0_vertices = __pyx_bstruct_vertices.shape[0]; __pyx_bshape_1_vertices = __pyx_bstruct_vertices.shape[1]; + } + } + __pyx_t_6 = 0; + __pyx_v_vertices = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + + __pyx_v_ndim = (__pyx_v_xi->dimensions[1]); + + + __pyx_v_start = 0; + + + __pyx_t_5 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__fill_value); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_7 = __Pyx_PyComplex_As___pyx_t_double_complex(__pyx_t_5); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_v_fill_value = __pyx_t_7; + + + __pyx_t_5 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__tri); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_v_info = __pyx_f_5scipy_7spatial_5qhull__get_delaunay_info(__pyx_t_5, 1, 1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_PyInt_to_py_npy_intp((__pyx_v_xi->dimensions[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_8 = PyObject_GetAttr(__pyx_v_self, __pyx_n_s__values); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_9 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__shape); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = __Pyx_GetItemInt(__pyx_t_9, 1, sizeof(long), PyInt_FromLong); if (!__pyx_t_8) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __pyx_t_9 = PyTuple_New(2); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_9, 1, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_8); + __pyx_t_5 = 0; + __pyx_t_8 = 0; + __pyx_t_8 = PyTuple_New(1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_9); + __Pyx_GIVEREF(__pyx_t_9); + __pyx_t_9 = 0; + __pyx_t_9 = PyDict_New(); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_9)); + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_10 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__complex); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyDict_SetItem(__pyx_t_9, ((PyObject *)__pyx_n_s__dtype), __pyx_t_10) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_10 = PyEval_CallObjectWithKeywords(__pyx_t_1, __pyx_t_8, ((PyObject *)__pyx_t_9)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_9)); __pyx_t_9 = 0; + if (!(likely(((__pyx_t_10) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_10, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_11 = ((PyArrayObject *)__pyx_t_10); + { + __Pyx_BufFmt_StackElem __pyx_stack[2]; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __pyx_t_12 = __Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_complex_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack); + if (unlikely(__pyx_t_12 < 0)) { + PyErr_Fetch(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_bstruct_out, (PyObject*)__pyx_v_out, &__Pyx_TypeInfo_nn___pyx_t_5numpy_complex_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_13); Py_XDECREF(__pyx_t_14); Py_XDECREF(__pyx_t_15); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_13, __pyx_t_14, __pyx_t_15); + } + } + __pyx_bstride_0_out = __pyx_bstruct_out.strides[0]; __pyx_bstride_1_out = __pyx_bstruct_out.strides[1]; + __pyx_bshape_0_out = __pyx_bstruct_out.shape[0]; __pyx_bshape_1_out = __pyx_bstruct_out.shape[1]; + if (unlikely(__pyx_t_12 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_11 = 0; + __Pyx_DECREF(((PyObject *)__pyx_v_out)); + __pyx_v_out = ((PyArrayObject *)__pyx_t_10); + __pyx_t_10 = 0; + + + __pyx_v_nvalues = (__pyx_v_out->dimensions[1]); + + + __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_9 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__finfo); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_8 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__double); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_8); + __pyx_t_8 = 0; + __pyx_t_8 = PyObject_Call(__pyx_t_9, __pyx_t_10, NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_10 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__eps); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = PyNumber_Multiply(__pyx_t_10, __pyx_int_100); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1137; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_DECREF(__pyx_v_eps); + __pyx_v_eps = __pyx_t_8; + __pyx_t_8 = 0; + + + { PyThreadState *_save; + Py_UNBLOCK_THREADS + { + + + __pyx_t_16 = (__pyx_v_xi->dimensions[0]); + for (__pyx_t_12 = 0; __pyx_t_12 < __pyx_t_16; __pyx_t_12+=1) { + __pyx_v_i = __pyx_t_12; + + + __pyx_t_17 = __pyx_PyFloat_AsDouble(__pyx_v_eps); if (unlikely((__pyx_t_17 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1145; __pyx_clineno = __LINE__; goto __pyx_L7;} + __pyx_v_isimplex = __pyx_f_5scipy_7spatial_5qhull__find_simplex(__pyx_v_info, __pyx_v_c, (((double *)__pyx_v_xi->data) + (__pyx_v_i * __pyx_v_ndim)), (&__pyx_v_start), __pyx_t_17); + + + __pyx_t_18 = (__pyx_v_isimplex == -1); + if (__pyx_t_18) { + + + __pyx_t_19 = __pyx_v_nvalues; + for (__pyx_t_20 = 0; __pyx_t_20 < __pyx_t_19; __pyx_t_20+=1) { + __pyx_v_k = __pyx_t_20; + + + __pyx_t_21 = __pyx_v_i; + __pyx_t_22 = __pyx_v_k; + if (__pyx_t_21 < 0) __pyx_t_21 += __pyx_bshape_0_out; + if (__pyx_t_22 < 0) __pyx_t_22 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_21, __pyx_bstride_0_out, __pyx_t_22, __pyx_bstride_1_out)).real = __Pyx_CREAL(__pyx_v_fill_value); + + + __pyx_t_23 = __pyx_v_i; + __pyx_t_24 = __pyx_v_k; + if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_bshape_0_out; + if (__pyx_t_24 < 0) __pyx_t_24 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_23, __pyx_bstride_0_out, __pyx_t_24, __pyx_bstride_1_out)).imag = __Pyx_CIMAG(__pyx_v_fill_value); + } + + + goto __pyx_L9_continue; + goto __pyx_L11; + } + __pyx_L11:; + + + __pyx_t_19 = __pyx_v_nvalues; + for (__pyx_t_20 = 0; __pyx_t_20 < __pyx_t_19; __pyx_t_20+=1) { + __pyx_v_k = __pyx_t_20; + + + __pyx_t_25 = (__pyx_v_ndim + 1); + for (__pyx_t_26 = 0; __pyx_t_26 < __pyx_t_25; __pyx_t_26+=1) { + __pyx_v_j = __pyx_t_26; + + + __pyx_t_27 = __pyx_v_isimplex; + __pyx_t_28 = __pyx_v_j; + if (__pyx_t_27 < 0) __pyx_t_27 += __pyx_bshape_0_vertices; + if (__pyx_t_28 < 0) __pyx_t_28 += __pyx_bshape_1_vertices; + __pyx_t_29 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_27, __pyx_bstride_0_vertices, __pyx_t_28, __pyx_bstride_1_vertices)); + __pyx_t_30 = __pyx_v_k; + if (__pyx_t_29 < 0) __pyx_t_29 += __pyx_bshape_0_values; + if (__pyx_t_30 < 0) __pyx_t_30 += __pyx_bshape_1_values; + __Pyx_SET_CREAL((__pyx_v_f[__pyx_v_j]), (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_values.buf, __pyx_t_29, __pyx_bstride_0_values, __pyx_t_30, __pyx_bstride_1_values)).real); + + + __pyx_t_31 = __pyx_v_isimplex; + __pyx_t_32 = __pyx_v_j; + if (__pyx_t_31 < 0) __pyx_t_31 += __pyx_bshape_0_vertices; + if (__pyx_t_32 < 0) __pyx_t_32 += __pyx_bshape_1_vertices; + __pyx_t_33 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_31, __pyx_bstride_0_vertices, __pyx_t_32, __pyx_bstride_1_vertices)); + __pyx_t_34 = __pyx_v_k; + if (__pyx_t_33 < 0) __pyx_t_33 += __pyx_bshape_0_values; + if (__pyx_t_34 < 0) __pyx_t_34 += __pyx_bshape_1_values; + __Pyx_SET_CIMAG((__pyx_v_f[__pyx_v_j]), (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_values.buf, __pyx_t_33, __pyx_bstride_0_values, __pyx_t_34, __pyx_bstride_1_values)).imag); + + + __pyx_t_35 = __pyx_v_isimplex; + __pyx_t_36 = __pyx_v_j; + if (__pyx_t_35 < 0) __pyx_t_35 += __pyx_bshape_0_vertices; + if (__pyx_t_36 < 0) __pyx_t_36 += __pyx_bshape_1_vertices; + __pyx_t_37 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_35, __pyx_bstride_0_vertices, __pyx_t_36, __pyx_bstride_1_vertices)); + __pyx_t_38 = __pyx_v_k; + __pyx_t_39 = 0; + if (__pyx_t_37 < 0) __pyx_t_37 += __pyx_bshape_0_grad; + if (__pyx_t_38 < 0) __pyx_t_38 += __pyx_bshape_1_grad; + if (__pyx_t_39 < 0) __pyx_t_39 += __pyx_bshape_2_grad; + __Pyx_SET_CREAL((__pyx_v_df[(2 * __pyx_v_j)]), (*__Pyx_BufPtrStrided3d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_grad.buf, __pyx_t_37, __pyx_bstride_0_grad, __pyx_t_38, __pyx_bstride_1_grad, __pyx_t_39, __pyx_bstride_2_grad)).real); + + + __pyx_t_40 = __pyx_v_isimplex; + __pyx_t_41 = __pyx_v_j; + if (__pyx_t_40 < 0) __pyx_t_40 += __pyx_bshape_0_vertices; + if (__pyx_t_41 < 0) __pyx_t_41 += __pyx_bshape_1_vertices; + __pyx_t_42 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_40, __pyx_bstride_0_vertices, __pyx_t_41, __pyx_bstride_1_vertices)); + __pyx_t_43 = __pyx_v_k; + __pyx_t_44 = 0; + if (__pyx_t_42 < 0) __pyx_t_42 += __pyx_bshape_0_grad; + if (__pyx_t_43 < 0) __pyx_t_43 += __pyx_bshape_1_grad; + if (__pyx_t_44 < 0) __pyx_t_44 += __pyx_bshape_2_grad; + __Pyx_SET_CIMAG((__pyx_v_df[(2 * __pyx_v_j)]), (*__Pyx_BufPtrStrided3d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_grad.buf, __pyx_t_42, __pyx_bstride_0_grad, __pyx_t_43, __pyx_bstride_1_grad, __pyx_t_44, __pyx_bstride_2_grad)).imag); + + + __pyx_t_45 = __pyx_v_isimplex; + __pyx_t_46 = __pyx_v_j; + if (__pyx_t_45 < 0) __pyx_t_45 += __pyx_bshape_0_vertices; + if (__pyx_t_46 < 0) __pyx_t_46 += __pyx_bshape_1_vertices; + __pyx_t_47 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_45, __pyx_bstride_0_vertices, __pyx_t_46, __pyx_bstride_1_vertices)); + __pyx_t_48 = __pyx_v_k; + __pyx_t_49 = 1; + if (__pyx_t_47 < 0) __pyx_t_47 += __pyx_bshape_0_grad; + if (__pyx_t_48 < 0) __pyx_t_48 += __pyx_bshape_1_grad; + if (__pyx_t_49 < 0) __pyx_t_49 += __pyx_bshape_2_grad; + __Pyx_SET_CREAL((__pyx_v_df[((2 * __pyx_v_j) + 1)]), (*__Pyx_BufPtrStrided3d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_grad.buf, __pyx_t_47, __pyx_bstride_0_grad, __pyx_t_48, __pyx_bstride_1_grad, __pyx_t_49, __pyx_bstride_2_grad)).real); + + + __pyx_t_50 = __pyx_v_isimplex; + __pyx_t_51 = __pyx_v_j; + if (__pyx_t_50 < 0) __pyx_t_50 += __pyx_bshape_0_vertices; + if (__pyx_t_51 < 0) __pyx_t_51 += __pyx_bshape_1_vertices; + __pyx_t_52 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int_t *, __pyx_bstruct_vertices.buf, __pyx_t_50, __pyx_bstride_0_vertices, __pyx_t_51, __pyx_bstride_1_vertices)); + __pyx_t_53 = __pyx_v_k; + __pyx_t_54 = 1; + if (__pyx_t_52 < 0) __pyx_t_52 += __pyx_bshape_0_grad; + if (__pyx_t_53 < 0) __pyx_t_53 += __pyx_bshape_1_grad; + if (__pyx_t_54 < 0) __pyx_t_54 += __pyx_bshape_2_grad; + __Pyx_SET_CIMAG((__pyx_v_df[((2 * __pyx_v_j) + 1)]), (*__Pyx_BufPtrStrided3d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_grad.buf, __pyx_t_52, __pyx_bstride_0_grad, __pyx_t_53, __pyx_bstride_1_grad, __pyx_t_54, __pyx_bstride_2_grad)).imag); + } + + + __pyx_v_w = __pyx_f_8interpnd__clough_tocher_2d_single_complex(__pyx_v_info, __pyx_v_isimplex, __pyx_v_c, __pyx_v_f, __pyx_v_df); + + + __pyx_t_26 = __pyx_v_i; + __pyx_t_55 = __pyx_v_k; + if (__pyx_t_26 < 0) __pyx_t_26 += __pyx_bshape_0_out; + if (__pyx_t_55 < 0) __pyx_t_55 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_26, __pyx_bstride_0_out, __pyx_t_55, __pyx_bstride_1_out)).real = __Pyx_CREAL(__pyx_v_w); + + + __pyx_t_56 = __pyx_v_i; + __pyx_t_57 = __pyx_v_k; + if (__pyx_t_56 < 0) __pyx_t_56 += __pyx_bshape_0_out; + if (__pyx_t_57 < 0) __pyx_t_57 += __pyx_bshape_1_out; + (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_complex_t *, __pyx_bstruct_out.buf, __pyx_t_56, __pyx_bstride_0_out, __pyx_t_57, __pyx_bstride_1_out)).imag = __Pyx_CIMAG(__pyx_v_w); + } + __pyx_L9_continue:; + } + } + { + int __pyx_why; + __pyx_why = 0; goto __pyx_L8; + __pyx_L7: __pyx_why = 4; goto __pyx_L8; + __pyx_L8:; + + + Py_BLOCK_THREADS + switch (__pyx_why) { + case 4: goto __pyx_L1_error; + } + } + } + + + free(((void *)__pyx_v_info)); + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_out)); + __pyx_r = ((PyObject *)__pyx_v_out); + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_XDECREF(__pyx_t_10); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xi); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_values); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_grad); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("interpnd.CloughTocher2DInterpolator._evaluate_complex"); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_xi); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_out); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_vertices); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_points); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_values); + __Pyx_SafeReleaseBuffer(&__pyx_bstruct_grad); + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_values); + __Pyx_XDECREF((PyObject *)__pyx_v_grad); + __Pyx_DECREF((PyObject *)__pyx_v_out); + __Pyx_XDECREF((PyObject *)__pyx_v_points); + __Pyx_XDECREF((PyObject *)__pyx_v_vertices); + __Pyx_DECREF(__pyx_v_eps); + __Pyx_DECREF(__pyx_v_self); + __Pyx_DECREF((PyObject *)__pyx_v_xi); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); +static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { + int __pyx_v_copy_shape; + int __pyx_v_i; + int __pyx_v_ndim; + int __pyx_v_endian_detector; + int __pyx_v_little_endian; + int __pyx_v_t; + char *__pyx_v_f; + PyArray_Descr *__pyx_v_descr = 0; + int __pyx_v_offset; + int __pyx_v_hasfields; + int __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + int __pyx_t_7; + int __pyx_t_8; + char *__pyx_t_9; + __Pyx_RefNannySetupContext("__getbuffer__"); + if (__pyx_v_info == NULL) return 0; + __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(__pyx_v_info->obj); + __Pyx_INCREF((PyObject *)__pyx_v_self); + + + __pyx_v_endian_detector = 1; + + + __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); + + + __pyx_v_ndim = PyArray_NDIM(((PyArrayObject *)__pyx_v_self)); + + + __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t))); + if (__pyx_t_1) { + + + __pyx_v_copy_shape = 1; + goto __pyx_L5; + } + { + + + __pyx_v_copy_shape = 0; + } + __pyx_L5:; + + + __pyx_t_1 = ((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS); + if (__pyx_t_1) { + + + __pyx_t_2 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_C_CONTIGUOUS)); + __pyx_t_3 = __pyx_t_2; + } else { + __pyx_t_3 = __pyx_t_1; + } + if (__pyx_t_3) { + + + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_17)); + PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_kp_u_17)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_17)); + __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_4, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + __pyx_t_3 = ((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS); + if (__pyx_t_3) { + + + __pyx_t_1 = (!PyArray_CHKFLAGS(((PyArrayObject *)__pyx_v_self), NPY_F_CONTIGUOUS)); + __pyx_t_2 = __pyx_t_1; + } else { + __pyx_t_2 = __pyx_t_3; + } + if (__pyx_t_2) { + + + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_18)); + PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_kp_u_18)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_18)); + __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L7; + } + __pyx_L7:; + + + __pyx_v_info->buf = PyArray_DATA(((PyArrayObject *)__pyx_v_self)); + + + __pyx_v_info->ndim = __pyx_v_ndim; + + + __pyx_t_6 = __pyx_v_copy_shape; + if (__pyx_t_6) { + + + __pyx_v_info->strides = ((Py_ssize_t *)malloc((((sizeof(Py_ssize_t)) * __pyx_v_ndim) * 2))); + + + __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim); + + + __pyx_t_6 = __pyx_v_ndim; + for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_6; __pyx_t_7+=1) { + __pyx_v_i = __pyx_t_7; + + + (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]); + + + (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(((PyArrayObject *)__pyx_v_self))[__pyx_v_i]); + } + goto __pyx_L8; + } + { + + + __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(((PyArrayObject *)__pyx_v_self))); + + + __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(((PyArrayObject *)__pyx_v_self))); + } + __pyx_L8:; + + + __pyx_v_info->suboffsets = NULL; + + + __pyx_v_info->itemsize = PyArray_ITEMSIZE(((PyArrayObject *)__pyx_v_self)); + + + __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(((PyArrayObject *)__pyx_v_self))); + + + __pyx_v_f = NULL; + + + __Pyx_INCREF(((PyObject *)((PyArrayObject *)__pyx_v_self)->descr)); + __pyx_v_descr = ((PyArrayObject *)__pyx_v_self)->descr; + + + __pyx_v_hasfields = PyDataType_HASFIELDS(__pyx_v_descr); + + + __pyx_t_2 = (!__pyx_v_hasfields); + if (__pyx_t_2) { + __pyx_t_3 = (!__pyx_v_copy_shape); + __pyx_t_1 = __pyx_t_3; + } else { + __pyx_t_1 = __pyx_t_2; + } + if (__pyx_t_1) { + + + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); + __pyx_v_info->obj = Py_None; + goto __pyx_L11; + } + { + + + __Pyx_INCREF(__pyx_v_self); + __Pyx_GIVEREF(__pyx_v_self); + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); + __pyx_v_info->obj = __pyx_v_self; + } + __pyx_L11:; + + + __pyx_t_1 = (!__pyx_v_hasfields); + if (__pyx_t_1) { + + + __pyx_v_t = __pyx_v_descr->type_num; + + + __pyx_t_1 = (__pyx_v_descr->byteorder == '>'); + if (__pyx_t_1) { + __pyx_t_2 = __pyx_v_little_endian; + } else { + __pyx_t_2 = __pyx_t_1; + } + if (!__pyx_t_2) { + + + __pyx_t_1 = (__pyx_v_descr->byteorder == '<'); + if (__pyx_t_1) { + __pyx_t_3 = (!__pyx_v_little_endian); + __pyx_t_8 = __pyx_t_3; + } else { + __pyx_t_8 = __pyx_t_1; + } + __pyx_t_1 = __pyx_t_8; + } else { + __pyx_t_1 = __pyx_t_2; + } + if (__pyx_t_1) { + + + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_19)); + PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_kp_u_19)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_19)); + __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_4, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L13; + } + __pyx_L13:; + + + __pyx_t_1 = (__pyx_v_t == NPY_BYTE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__b; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_UBYTE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__B; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_SHORT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__h; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_USHORT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__H; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_INT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__i; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_UINT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__I; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_LONG); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__l; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_ULONG); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__L; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_LONGLONG); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__q; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_ULONGLONG); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__Q; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_FLOAT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__f; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_DOUBLE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__d; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_LONGDOUBLE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__g; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_CFLOAT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__Zf; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_CDOUBLE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__Zd; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_CLONGDOUBLE); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__Zg; + goto __pyx_L14; + } + + + __pyx_t_1 = (__pyx_v_t == NPY_OBJECT); + if (__pyx_t_1) { + __pyx_v_f = __pyx_k__O; + goto __pyx_L14; + } + { + + + __pyx_t_5 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_20), __pyx_t_5); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_L14:; + + + __pyx_v_info->format = __pyx_v_f; + + + __pyx_r = 0; + goto __pyx_L0; + goto __pyx_L12; + } + { + + + __pyx_v_info->format = ((char *)malloc(255)); + + + (__pyx_v_info->format[0]) = '^'; + + + __pyx_v_offset = 0; + + + __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 255), (&__pyx_v_offset)); if (unlikely(__pyx_t_9 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_f = __pyx_t_9; + + + (__pyx_v_f[0]) = 0; + } + __pyx_L12:; + + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("numpy.ndarray.__getbuffer__"); + __pyx_r = -1; + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = NULL; + goto __pyx_L2; + __pyx_L0:; + if (__pyx_v_info->obj == Py_None) { + __Pyx_GOTREF(Py_None); + __Pyx_DECREF(Py_None); __pyx_v_info->obj = NULL; + } + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_descr); + __Pyx_DECREF((PyObject *)__pyx_v_self); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static void __pyx_pf_5numpy_7ndarray___releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); +static void __pyx_pf_5numpy_7ndarray___releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) { + int __pyx_t_1; + __Pyx_RefNannySetupContext("__releasebuffer__"); + __Pyx_INCREF((PyObject *)__pyx_v_self); + + + __pyx_t_1 = PyArray_HASFIELDS(((PyArrayObject *)__pyx_v_self)); + if (__pyx_t_1) { + + + free(__pyx_v_info->format); + goto __pyx_L5; + } + __pyx_L5:; + + + __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t))); + if (__pyx_t_1) { + + + free(__pyx_v_info->strides); + goto __pyx_L6; + } + __pyx_L6:; + + __Pyx_DECREF((PyObject *)__pyx_v_self); + __Pyx_RefNannyFinishContext(); +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew1"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 756; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew2"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 759; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew3"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 762; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew4"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 765; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { + PyObject *__pyx_r = NULL; + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew5"); + + + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 768; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5"); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx_v_descr, char *__pyx_v_f, char *__pyx_v_end, int *__pyx_v_offset) { + PyArray_Descr *__pyx_v_child; + int __pyx_v_endian_detector; + int __pyx_v_little_endian; + PyObject *__pyx_v_fields; + PyObject *__pyx_v_childname; + PyObject *__pyx_v_new_offset; + PyObject *__pyx_v_t; + char *__pyx_r; + Py_ssize_t __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + int __pyx_t_7; + int __pyx_t_8; + int __pyx_t_9; + char *__pyx_t_10; + __Pyx_RefNannySetupContext("_util_dtypestring"); + __Pyx_INCREF((PyObject *)__pyx_v_descr); + __pyx_v_child = ((PyArray_Descr *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_fields = ((PyObject *)Py_None); __Pyx_INCREF(Py_None); + __pyx_v_childname = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_new_offset = Py_None; __Pyx_INCREF(Py_None); + __pyx_v_t = Py_None; __Pyx_INCREF(Py_None); + + + __pyx_v_endian_detector = 1; + + + __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); + + + if (likely(((PyObject *)__pyx_v_descr->names) != Py_None)) { + __pyx_t_1 = 0; __pyx_t_2 = ((PyObject *)__pyx_v_descr->names); __Pyx_INCREF(__pyx_t_2); + } else { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 781; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + for (;;) { + if (__pyx_t_1 >= PyTuple_GET_SIZE(__pyx_t_2)) break; + __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_1); __Pyx_INCREF(__pyx_t_3); __pyx_t_1++; + __Pyx_DECREF(__pyx_v_childname); + __pyx_v_childname = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_3 = PyObject_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (!__pyx_t_3) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected tuple, got %.200s", Py_TYPE(__pyx_t_3)->tp_name), 0))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 782; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(((PyObject *)__pyx_v_fields)); + __pyx_v_fields = ((PyObject *)__pyx_t_3); + __pyx_t_3 = 0; + + + if (likely(((PyObject *)__pyx_v_fields) != Py_None) && likely(PyTuple_GET_SIZE(((PyObject *)__pyx_v_fields)) == 2)) { + PyObject* tuple = ((PyObject *)__pyx_v_fields); + __pyx_t_3 = PyTuple_GET_ITEM(tuple, 0); __Pyx_INCREF(__pyx_t_3); + if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 783; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyTuple_GET_ITEM(tuple, 1); __Pyx_INCREF(__pyx_t_4); + __Pyx_DECREF(((PyObject *)__pyx_v_child)); + __pyx_v_child = ((PyArray_Descr *)__pyx_t_3); + __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_v_new_offset); + __pyx_v_new_offset = __pyx_t_4; + __pyx_t_4 = 0; + } else { + __Pyx_UnpackTupleError(((PyObject *)__pyx_v_fields), 2); + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 783; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + + + __pyx_t_4 = PyInt_FromLong((__pyx_v_end - __pyx_v_f)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_15, Py_LT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 785; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + + + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_21)); + PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_kp_u_21)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_21)); + __pyx_t_3 = PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L5; + } + __pyx_L5:; + + + __pyx_t_6 = (__pyx_v_child->byteorder == '>'); + if (__pyx_t_6) { + __pyx_t_7 = __pyx_v_little_endian; + } else { + __pyx_t_7 = __pyx_t_6; + } + if (!__pyx_t_7) { + + + __pyx_t_6 = (__pyx_v_child->byteorder == '<'); + if (__pyx_t_6) { + __pyx_t_8 = (!__pyx_v_little_endian); + __pyx_t_9 = __pyx_t_8; + } else { + __pyx_t_9 = __pyx_t_6; + } + __pyx_t_6 = __pyx_t_9; + } else { + __pyx_t_6 = __pyx_t_7; + } + if (__pyx_t_6) { + + + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_19)); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_kp_u_19)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_19)); + __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 790; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + + while (1) { + __pyx_t_5 = PyInt_FromLong((__pyx_v_offset[0])); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_v_new_offset, Py_LT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 800; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (!__pyx_t_6) break; + + + (__pyx_v_f[0]) = 120; + + + __pyx_v_f += 1; + + + (__pyx_v_offset[0]) += 1; + } + + + (__pyx_v_offset[0]) += __pyx_v_child->elsize; + + + __pyx_t_6 = (!PyDataType_HASFIELDS(__pyx_v_child)); + if (__pyx_t_6) { + + + __pyx_t_3 = PyInt_FromLong(__pyx_v_child->type_num); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 808; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_v_t); + __pyx_v_t = __pyx_t_3; + __pyx_t_3 = 0; + + + __pyx_t_6 = ((__pyx_v_end - __pyx_v_f) < 5); + if (__pyx_t_6) { + + + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 810; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(((PyObject *)__pyx_kp_u_22)); + PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_kp_u_22)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_22)); + __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 810; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 810; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L10; + } + __pyx_L10:; + + + __pyx_t_5 = PyInt_FromLong(NPY_BYTE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 813; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 813; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 813; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 98; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_UBYTE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 814; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 814; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 814; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 66; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_SHORT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 815; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 104; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_USHORT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 816; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 816; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 816; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 72; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_INT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 817; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 105; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_UINT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 818; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 73; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_LONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 819; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 108; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_ULONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 820; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 76; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_LONGLONG); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 821; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 821; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 821; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 113; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_ULONGLONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 822; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 81; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_FLOAT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 102; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_DOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 824; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 100; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 825; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 103; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_CFLOAT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 90; + (__pyx_v_f[1]) = 102; + __pyx_v_f += 1; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_CDOUBLE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 827; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 90; + (__pyx_v_f[1]) = 100; + __pyx_v_f += 1; + goto __pyx_L11; + } + + + __pyx_t_3 = PyInt_FromLong(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 828; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 90; + (__pyx_v_f[1]) = 103; + __pyx_v_f += 1; + goto __pyx_L11; + } + + + __pyx_t_5 = PyInt_FromLong(NPY_OBJECT); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_5, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 829; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 79; + goto __pyx_L11; + } + { + + + __pyx_t_3 = PyNumber_Remainder(((PyObject *)__pyx_kp_u_20), __pyx_v_t); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[1]; __pyx_lineno = 831; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_L11:; + + + __pyx_v_f += 1; + goto __pyx_L9; + } + { + + + __pyx_t_10 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_10 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 836; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_f = __pyx_t_10; + } + __pyx_L9:; + } + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_r = __pyx_v_f; + goto __pyx_L0; + + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("numpy._util_dtypestring"); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_DECREF((PyObject *)__pyx_v_child); + __Pyx_DECREF(__pyx_v_fields); + __Pyx_DECREF(__pyx_v_childname); + __Pyx_DECREF(__pyx_v_new_offset); + __Pyx_DECREF(__pyx_v_t); + __Pyx_DECREF((PyObject *)__pyx_v_descr); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + + + +static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { + PyObject *__pyx_v_baseptr; + int __pyx_t_1; + __Pyx_RefNannySetupContext("set_array_base"); + __Pyx_INCREF((PyObject *)__pyx_v_arr); + __Pyx_INCREF(__pyx_v_base); + + + __pyx_t_1 = (__pyx_v_base == Py_None); + if (__pyx_t_1) { + + + __pyx_v_baseptr = NULL; + goto __pyx_L3; + } + { + + + Py_INCREF(__pyx_v_base); + + + __pyx_v_baseptr = ((PyObject *)__pyx_v_base); + } + __pyx_L3:; + + + Py_XDECREF(__pyx_v_arr->base); + + + __pyx_v_arr->base = __pyx_v_baseptr; + + __Pyx_DECREF((PyObject *)__pyx_v_arr); + __Pyx_DECREF(__pyx_v_base); + __Pyx_RefNannyFinishContext(); +} + + + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { + PyObject *__pyx_r = NULL; + int __pyx_t_1; + __Pyx_RefNannySetupContext("get_array_base"); + __Pyx_INCREF((PyObject *)__pyx_v_arr); + + + __pyx_t_1 = (__pyx_v_arr->base == NULL); + if (__pyx_t_1) { + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_None); + __pyx_r = Py_None; + goto __pyx_L0; + goto __pyx_L3; + } + { + + + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_arr->base)); + __pyx_r = ((PyObject *)__pyx_v_arr->base); + goto __pyx_L0; + } + __pyx_L3:; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + __pyx_L0:; + __Pyx_DECREF((PyObject *)__pyx_v_arr); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static struct PyMethodDef __pyx_methods[] = { + {__Pyx_NAMESTR("_ndim_coords_from_arrays"), (PyCFunction)__pyx_pf_8interpnd__ndim_coords_from_arrays, METH_O, __Pyx_DOCSTR(__pyx_doc_8interpnd__ndim_coords_from_arrays)}, + {__Pyx_NAMESTR("estimate_gradients_2d_global"), (PyCFunction)__pyx_pf_8interpnd_estimate_gradients_2d_global, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)}, + {0, 0, 0, 0} +}; + +static void __pyx_init_filenames(void); + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + __Pyx_NAMESTR("interpnd"), + __Pyx_DOCSTR(__pyx_k_23), + -1, + __pyx_methods , + NULL, + NULL, + NULL, + NULL +}; +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_kp_s_11, __pyx_k_11, sizeof(__pyx_k_11), 0, 0, 1, 0}, + {&__pyx_n_s_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 0, 1, 1}, + {&__pyx_kp_s_13, __pyx_k_13, sizeof(__pyx_k_13), 0, 0, 1, 0}, + {&__pyx_n_s_14, __pyx_k_14, sizeof(__pyx_k_14), 0, 0, 1, 1}, + {&__pyx_kp_u_17, __pyx_k_17, sizeof(__pyx_k_17), 0, 1, 0, 0}, + {&__pyx_kp_u_18, __pyx_k_18, sizeof(__pyx_k_18), 0, 1, 0, 0}, + {&__pyx_kp_u_19, __pyx_k_19, sizeof(__pyx_k_19), 0, 1, 0, 0}, + {&__pyx_n_s_2, __pyx_k_2, sizeof(__pyx_k_2), 0, 0, 1, 1}, + {&__pyx_kp_u_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 1, 0, 0}, + {&__pyx_kp_u_21, __pyx_k_21, sizeof(__pyx_k_21), 0, 1, 0, 0}, + {&__pyx_kp_u_22, __pyx_k_22, sizeof(__pyx_k_22), 0, 1, 0, 0}, + {&__pyx_n_s_24, __pyx_k_24, sizeof(__pyx_k_24), 0, 0, 1, 1}, + {&__pyx_n_s_25, __pyx_k_25, sizeof(__pyx_k_25), 0, 0, 1, 1}, + {&__pyx_kp_s_26, __pyx_k_26, sizeof(__pyx_k_26), 0, 0, 1, 0}, + {&__pyx_kp_s_27, __pyx_k_27, sizeof(__pyx_k_27), 0, 0, 1, 0}, + {&__pyx_n_s_28, __pyx_k_28, sizeof(__pyx_k_28), 0, 0, 1, 1}, + {&__pyx_kp_s_29, __pyx_k_29, sizeof(__pyx_k_29), 0, 0, 1, 0}, + {&__pyx_kp_s_3, __pyx_k_3, sizeof(__pyx_k_3), 0, 0, 1, 0}, + {&__pyx_n_s_30, __pyx_k_30, sizeof(__pyx_k_30), 0, 0, 1, 1}, + {&__pyx_kp_u_31, __pyx_k_31, sizeof(__pyx_k_31), 0, 1, 0, 0}, + {&__pyx_kp_u_32, __pyx_k_32, sizeof(__pyx_k_32), 0, 1, 0, 0}, + {&__pyx_kp_u_33, __pyx_k_33, sizeof(__pyx_k_33), 0, 1, 0, 0}, + {&__pyx_kp_u_34, __pyx_k_34, sizeof(__pyx_k_34), 0, 1, 0, 0}, + {&__pyx_kp_s_4, __pyx_k_4, sizeof(__pyx_k_4), 0, 0, 1, 0}, + {&__pyx_kp_s_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 0, 1, 0}, + {&__pyx_kp_s_6, __pyx_k_6, sizeof(__pyx_k_6), 0, 0, 1, 0}, + {&__pyx_kp_s_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 0, 1, 0}, + {&__pyx_kp_s_8, __pyx_k_8, sizeof(__pyx_k_8), 0, 0, 1, 0}, + {&__pyx_n_s__Delaunay, __pyx_k__Delaunay, sizeof(__pyx_k__Delaunay), 0, 0, 1, 1}, + {&__pyx_n_s__NDInterpolatorBase, __pyx_k__NDInterpolatorBase, sizeof(__pyx_k__NDInterpolatorBase), 0, 0, 1, 1}, + {&__pyx_n_s__RuntimeError, __pyx_k__RuntimeError, sizeof(__pyx_k__RuntimeError), 0, 0, 1, 1}, + {&__pyx_n_s__T, __pyx_k__T, sizeof(__pyx_k__T), 0, 0, 1, 1}, + {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1}, + {&__pyx_n_s__Warning, __pyx_k__Warning, sizeof(__pyx_k__Warning), 0, 0, 1, 1}, + {&__pyx_n_s____call__, __pyx_k____call__, sizeof(__pyx_k____call__), 0, 0, 1, 1}, + {&__pyx_n_s____init__, __pyx_k____init__, sizeof(__pyx_k____init__), 0, 0, 1, 1}, + {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1}, + {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1}, + {&__pyx_n_s___check_call_shape, __pyx_k___check_call_shape, sizeof(__pyx_k___check_call_shape), 0, 0, 1, 1}, + {&__pyx_n_s___check_init_shape, __pyx_k___check_init_shape, sizeof(__pyx_k___check_init_shape), 0, 0, 1, 1}, + {&__pyx_n_s___evaluate_complex, __pyx_k___evaluate_complex, sizeof(__pyx_k___evaluate_complex), 0, 0, 1, 1}, + {&__pyx_n_s___evaluate_double, __pyx_k___evaluate_double, sizeof(__pyx_k___evaluate_double), 0, 0, 1, 1}, + {&__pyx_n_s__asanyarray, __pyx_k__asanyarray, sizeof(__pyx_k__asanyarray), 0, 0, 1, 1}, + {&__pyx_n_s__ascontiguousarray, __pyx_k__ascontiguousarray, sizeof(__pyx_k__ascontiguousarray), 0, 0, 1, 1}, + {&__pyx_n_s__astype, __pyx_k__astype, sizeof(__pyx_k__astype), 0, 0, 1, 1}, + {&__pyx_n_s__base, __pyx_k__base, sizeof(__pyx_k__base), 0, 0, 1, 1}, + {&__pyx_n_s__buf, __pyx_k__buf, sizeof(__pyx_k__buf), 0, 0, 1, 1}, + {&__pyx_n_s__byteorder, __pyx_k__byteorder, sizeof(__pyx_k__byteorder), 0, 0, 1, 1}, + {&__pyx_n_s__complex, __pyx_k__complex, sizeof(__pyx_k__complex), 0, 0, 1, 1}, + {&__pyx_n_s__complexfloating, __pyx_k__complexfloating, sizeof(__pyx_k__complexfloating), 0, 0, 1, 1}, + {&__pyx_n_s__data, __pyx_k__data, sizeof(__pyx_k__data), 0, 0, 1, 1}, + {&__pyx_n_s__descr, __pyx_k__descr, sizeof(__pyx_k__descr), 0, 0, 1, 1}, + {&__pyx_n_s__double, __pyx_k__double, sizeof(__pyx_k__double), 0, 0, 1, 1}, + {&__pyx_n_s__dtype, __pyx_k__dtype, sizeof(__pyx_k__dtype), 0, 0, 1, 1}, + {&__pyx_n_s__edge, __pyx_k__edge, sizeof(__pyx_k__edge), 0, 0, 1, 1}, + {&__pyx_n_s__empty, __pyx_k__empty, sizeof(__pyx_k__empty), 0, 0, 1, 1}, + {&__pyx_n_s__enumerate, __pyx_k__enumerate, sizeof(__pyx_k__enumerate), 0, 0, 1, 1}, + {&__pyx_n_s__eps, __pyx_k__eps, sizeof(__pyx_k__eps), 0, 0, 1, 1}, + {&__pyx_n_s__fields, __pyx_k__fields, sizeof(__pyx_k__fields), 0, 0, 1, 1}, + {&__pyx_n_s__fill_value, __pyx_k__fill_value, sizeof(__pyx_k__fill_value), 0, 0, 1, 1}, + {&__pyx_n_s__finfo, __pyx_k__finfo, sizeof(__pyx_k__finfo), 0, 0, 1, 1}, + {&__pyx_n_s__format, __pyx_k__format, sizeof(__pyx_k__format), 0, 0, 1, 1}, + {&__pyx_n_s__grad, __pyx_k__grad, sizeof(__pyx_k__grad), 0, 0, 1, 1}, + {&__pyx_n_s__imag, __pyx_k__imag, sizeof(__pyx_k__imag), 0, 0, 1, 1}, + {&__pyx_n_s__is_complex, __pyx_k__is_complex, sizeof(__pyx_k__is_complex), 0, 0, 1, 1}, + {&__pyx_n_s__issubdtype, __pyx_k__issubdtype, sizeof(__pyx_k__issubdtype), 0, 0, 1, 1}, + {&__pyx_n_s__itemsize, __pyx_k__itemsize, sizeof(__pyx_k__itemsize), 0, 0, 1, 1}, + {&__pyx_n_s__map, __pyx_k__map, sizeof(__pyx_k__map), 0, 0, 1, 1}, + {&__pyx_n_s__maxiter, __pyx_k__maxiter, sizeof(__pyx_k__maxiter), 0, 0, 1, 1}, + {&__pyx_n_s__names, __pyx_k__names, sizeof(__pyx_k__names), 0, 0, 1, 1}, + {&__pyx_n_s__nan, __pyx_k__nan, sizeof(__pyx_k__nan), 0, 0, 1, 1}, + {&__pyx_n_s__ndim, __pyx_k__ndim, sizeof(__pyx_k__ndim), 0, 0, 1, 1}, + {&__pyx_n_s__neighbors, __pyx_k__neighbors, sizeof(__pyx_k__neighbors), 0, 0, 1, 1}, + {&__pyx_n_s__np, __pyx_k__np, sizeof(__pyx_k__np), 0, 0, 1, 1}, + {&__pyx_n_s__npoints, __pyx_k__npoints, sizeof(__pyx_k__npoints), 0, 0, 1, 1}, + {&__pyx_n_s__numpy, __pyx_k__numpy, sizeof(__pyx_k__numpy), 0, 0, 1, 1}, + {&__pyx_n_s__obj, __pyx_k__obj, sizeof(__pyx_k__obj), 0, 0, 1, 1}, + {&__pyx_n_s__object, __pyx_k__object, sizeof(__pyx_k__object), 0, 0, 1, 1}, + {&__pyx_n_s__points, __pyx_k__points, sizeof(__pyx_k__points), 0, 0, 1, 1}, + {&__pyx_n_s__prod, __pyx_k__prod, sizeof(__pyx_k__prod), 0, 0, 1, 1}, + {&__pyx_n_s__qhull, __pyx_k__qhull, sizeof(__pyx_k__qhull), 0, 0, 1, 1}, + {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1}, + {&__pyx_n_s__readonly, __pyx_k__readonly, sizeof(__pyx_k__readonly), 0, 0, 1, 1}, + {&__pyx_n_s__real, __pyx_k__real, sizeof(__pyx_k__real), 0, 0, 1, 1}, + {&__pyx_n_s__reshape, __pyx_k__reshape, sizeof(__pyx_k__reshape), 0, 0, 1, 1}, + {&__pyx_n_s__self, __pyx_k__self, sizeof(__pyx_k__self), 0, 0, 1, 1}, + {&__pyx_n_s__shape, __pyx_k__shape, sizeof(__pyx_k__shape), 0, 0, 1, 1}, + {&__pyx_n_s__strides, __pyx_k__strides, sizeof(__pyx_k__strides), 0, 0, 1, 1}, + {&__pyx_n_s__suboffsets, __pyx_k__suboffsets, sizeof(__pyx_k__suboffsets), 0, 0, 1, 1}, + {&__pyx_n_s__tol, __pyx_k__tol, sizeof(__pyx_k__tol), 0, 0, 1, 1}, + {&__pyx_n_s__transform, __pyx_k__transform, sizeof(__pyx_k__transform), 0, 0, 1, 1}, + {&__pyx_n_s__transpose, __pyx_k__transpose, sizeof(__pyx_k__transpose), 0, 0, 1, 1}, + {&__pyx_n_s__tri, __pyx_k__tri, sizeof(__pyx_k__tri), 0, 0, 1, 1}, + {&__pyx_n_s__type_num, __pyx_k__type_num, sizeof(__pyx_k__type_num), 0, 0, 1, 1}, + {&__pyx_n_s__values, __pyx_k__values, sizeof(__pyx_k__values), 0, 0, 1, 1}, + {&__pyx_n_s__values_shape, __pyx_k__values_shape, sizeof(__pyx_k__values_shape), 0, 0, 1, 1}, + {&__pyx_n_s__vertex, __pyx_k__vertex, sizeof(__pyx_k__vertex), 0, 0, 1, 1}, + {&__pyx_n_s__vertex2, __pyx_k__vertex2, sizeof(__pyx_k__vertex2), 0, 0, 1, 1}, + {&__pyx_n_s__vertices, __pyx_k__vertices, sizeof(__pyx_k__vertices), 0, 0, 1, 1}, + {&__pyx_n_s__warn, __pyx_k__warn, sizeof(__pyx_k__warn), 0, 0, 1, 1}, + {&__pyx_n_s__warnings, __pyx_k__warnings, sizeof(__pyx_k__warnings), 0, 0, 1, 1}, + {&__pyx_n_s__xi, __pyx_k__xi, sizeof(__pyx_k__xi), 0, 0, 1, 1}, + {&__pyx_n_s__xrange, __pyx_k__xrange, sizeof(__pyx_k__xrange), 0, 0, 1, 1}, + {&__pyx_n_s__y, __pyx_k__y, sizeof(__pyx_k__y), 0, 0, 1, 1}, + {&__pyx_n_s__zeros, __pyx_k__zeros, sizeof(__pyx_k__zeros), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_object = __Pyx_GetName(__pyx_b, __pyx_n_s__object); if (!__pyx_builtin_object) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_Warning = __Pyx_GetName(__pyx_b, __pyx_n_s__Warning); if (!__pyx_builtin_Warning) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_map = __Pyx_GetName(__pyx_b, __pyx_n_s__map); if (!__pyx_builtin_map) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #if PY_MAJOR_VERSION >= 3 + __pyx_builtin_xrange = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_xrange) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #else + __pyx_builtin_xrange = __Pyx_GetName(__pyx_b, __pyx_n_s__xrange); if (!__pyx_builtin_xrange) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #endif + __pyx_builtin_enumerate = __Pyx_GetName(__pyx_b, __pyx_n_s__enumerate); if (!__pyx_builtin_enumerate) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 786; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + return 0; + __pyx_L1_error:; + return -1; +} + +static int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_2 = PyInt_FromLong(2); if (unlikely(!__pyx_int_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_15 = PyInt_FromLong(15); if (unlikely(!__pyx_int_15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_100 = PyInt_FromLong(100); if (unlikely(!__pyx_int_100)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_int_400 = PyInt_FromLong(400); if (unlikely(!__pyx_int_400)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + return 0; + __pyx_L1_error:; + return -1; +} + +#if PY_MAJOR_VERSION < 3 +PyMODINIT_FUNC initinterpnd(void); +PyMODINIT_FUNC initinterpnd(void) +#else +PyMODINIT_FUNC PyInit_interpnd(void); +PyMODINIT_FUNC PyInit_interpnd(void) +#endif +{ + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + #if CYTHON_REFNANNY + void* __pyx_refnanny = NULL; + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); + if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); + } + __pyx_refnanny = __Pyx_RefNanny->SetupContext("PyMODINIT_FUNC PyInit_interpnd(void)", __LINE__, __FILE__); + #endif + __pyx_init_filenames(); + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #if PY_MAJOR_VERSION < 3 + __pyx_empty_bytes = PyString_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #else + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #endif + + + #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + #ifdef WITH_THREAD + PyEval_InitThreads(); + #endif + #endif + + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4(__Pyx_NAMESTR("interpnd"), __pyx_methods, __Pyx_DOCSTR(__pyx_k_23), 0, PYTHON_API_VERSION); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (!__pyx_m) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + #if PY_MAJOR_VERSION < 3 + Py_INCREF(__pyx_m); + #endif + __pyx_b = PyImport_AddModule(__Pyx_NAMESTR(__Pyx_BUILTIN_MODULE_NAME)); + if (!__pyx_b) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + if (__Pyx_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + + if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__pyx_module_is_main_interpnd) { + if (__Pyx_SetAttrString(__pyx_m, "__name__", __pyx_n_s____main__) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + } + + if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + + + + __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 848; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + __pyx_t_1 = __Pyx_ImportModule("scipy.spatial.qhull"); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_get_delaunay_info", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__get_delaunay_info, "__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *(PyObject *, int, int)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_barycentric_inside", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__barycentric_inside, "int (int, double *, double *, double *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_barycentric_coordinate_single", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__barycentric_coordinate_single, "void (int, double *, double *, double *, int)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_barycentric_coordinates", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__barycentric_coordinates, "void (int, double *, double *, double *)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_lift_point", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__lift_point, "void (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_distplane", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__distplane, "double (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int, double *)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_is_point_fully_outside", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__is_point_fully_outside, "int (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_find_simplex_bruteforce", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__find_simplex_bruteforce, "int (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_find_simplex_directed", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__find_simplex_directed, "int (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, int *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_find_simplex", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__find_simplex, "int (__pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, double *, double *, int *, double)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_RidgeIter2D_init", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_init, "void (__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *, __pyx_t_5scipy_7spatial_5qhull_DelaunayInfo_t *, int)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_ImportFunction(__pyx_t_1, "_RidgeIter2D_next", (void (**)(void))&__pyx_f_5scipy_7spatial_5qhull__RidgeIter2D_next, "void (__pyx_t_5scipy_7spatial_5qhull_RidgeIter2D_t *)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + Py_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + + + __pyx_t_2 = __Pyx_Import(((PyObject *)__pyx_n_s__numpy), 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__np, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_2)); + __Pyx_INCREF(((PyObject *)__pyx_n_s_25)); + PyList_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_n_s_25)); + __Pyx_GIVEREF(((PyObject *)__pyx_n_s_25)); + __pyx_t_3 = __Pyx_Import(((PyObject *)__pyx_n_s_24), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__qhull, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + + __pyx_t_3 = __Pyx_Import(((PyObject *)__pyx_n_s__warnings), 0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__warnings, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_builtin_object); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_builtin_object); + __Pyx_GIVEREF(__pyx_builtin_object); + if (PyDict_SetItemString(((PyObject *)__pyx_t_3), "__doc__", ((PyObject *)__pyx_kp_s_26)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = __Pyx_CreateClass(__pyx_t_2, ((PyObject *)__pyx_t_3), __pyx_n_s__NDInterpolatorBase, "interpnd"); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__nan); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_k_1 = __pyx_t_5; + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + __pyx_t_5 = PyCFunction_New(&__pyx_mdef_8interpnd_18NDInterpolatorBase___init__, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = PyMethod_New(__pyx_t_5, 0, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyObject_SetAttr(__pyx_t_4, __pyx_n_s____init__, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_8interpnd_18NDInterpolatorBase__check_init_shape, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = PyMethod_New(__pyx_t_2, 0, __pyx_t_4); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_4, __pyx_n_s___check_init_shape, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + + __pyx_t_5 = PyCFunction_New(&__pyx_mdef_8interpnd_18NDInterpolatorBase__check_call_shape, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = PyMethod_New(__pyx_t_5, 0, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyObject_SetAttr(__pyx_t_4, __pyx_n_s___check_call_shape, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_8interpnd_18NDInterpolatorBase___call__, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = PyMethod_New(__pyx_t_2, 0, __pyx_t_4); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_4, __pyx_n_s____call__, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__NDInterpolatorBase, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + + + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__NDInterpolatorBase); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + if (PyDict_SetItemString(((PyObject *)__pyx_t_3), "__doc__", ((PyObject *)__pyx_kp_s_27)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = __Pyx_CreateClass(__pyx_t_5, ((PyObject *)__pyx_t_3), __pyx_n_s_28, "interpnd"); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s__nan); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_k_9 = __pyx_t_2; + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_8interpnd_20LinearNDInterpolator___init__, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = PyMethod_New(__pyx_t_2, 0, __pyx_t_4); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_4, __pyx_n_s____init__, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + + __pyx_t_5 = PyCFunction_New(&__pyx_mdef_8interpnd_20LinearNDInterpolator__evaluate_double, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_2 = PyMethod_New(__pyx_t_5, 0, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyObject_SetAttr(__pyx_t_4, __pyx_n_s___evaluate_double, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_8interpnd_20LinearNDInterpolator__evaluate_complex, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_5 = PyMethod_New(__pyx_t_2, 0, __pyx_t_4); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_4, __pyx_n_s___evaluate_complex, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_28, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + + + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_builtin_Warning); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_builtin_Warning); + __Pyx_GIVEREF(__pyx_builtin_Warning); + __pyx_t_5 = __Pyx_CreateClass(__pyx_t_4, ((PyObject *)__pyx_t_3), __pyx_n_s_14, "interpnd"); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_14, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + + + __pyx_t_3 = PyFloat_FromDouble(9.9999999999999995e-07); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 480; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_k_10 = __pyx_t_3; + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + + + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 988; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_t_5 = __Pyx_GetName(__pyx_m, __pyx_n_s__NDInterpolatorBase); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 988; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 988; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5); + __Pyx_GIVEREF(__pyx_t_5); + __pyx_t_5 = 0; + if (PyDict_SetItemString(((PyObject *)__pyx_t_3), "__doc__", ((PyObject *)__pyx_kp_s_29)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 988; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = __Pyx_CreateClass(__pyx_t_4, ((PyObject *)__pyx_t_3), __pyx_n_s_30, "interpnd"); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 988; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyObject_GetAttr(__pyx_t_4, __pyx_n_s__nan); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_k_15 = __pyx_t_2; + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + + + __pyx_t_2 = PyFloat_FromDouble(9.9999999999999995e-07); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1049; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_k_16 = __pyx_t_2; + __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_2 = 0; + + + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_8interpnd_26CloughTocher2DInterpolator___init__, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyMethod_New(__pyx_t_2, 0, __pyx_t_5); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_5, __pyx_n_s____init__, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1048; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + + __pyx_t_4 = PyCFunction_New(&__pyx_mdef_8interpnd_26CloughTocher2DInterpolator__evaluate_double, 0); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1058; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyMethod_New(__pyx_t_4, 0, __pyx_t_5); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1058; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_t_5, __pyx_n_s___evaluate_double, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1058; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + + __pyx_t_2 = PyCFunction_New(&__pyx_mdef_8interpnd_26CloughTocher2DInterpolator__evaluate_complex, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1114; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = PyMethod_New(__pyx_t_2, 0, __pyx_t_5); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1114; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (PyObject_SetAttr(__pyx_t_5, __pyx_n_s___evaluate_complex, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1114; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_30, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 988; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + + + __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_t_5 = PyObject_GetAttr(__pyx_m, __pyx_n_s__NDInterpolatorBase); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s____init__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_GetAttrString(__pyx_t_4, "__doc__"); + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_kp_u_31), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyObject_GetAttr(__pyx_m, __pyx_n_s__NDInterpolatorBase); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s___check_init_shape); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_GetAttrString(__pyx_t_4, "__doc__"); + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_kp_u_32), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyObject_GetAttr(__pyx_m, __pyx_n_s__NDInterpolatorBase); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyObject_GetAttr(__pyx_t_5, __pyx_n_s____call__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_GetAttrString(__pyx_t_4, "__doc__"); + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_kp_u_33), __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyObject_GetAttr(__pyx_m, __pyx_n_s_2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = __Pyx_GetAttrString(__pyx_t_5, "__doc__"); + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_kp_u_34), __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_3)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + if (__pyx_m) { + __Pyx_AddTraceback("init interpnd"); + Py_DECREF(__pyx_m); __pyx_m = 0; + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init interpnd"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if PY_MAJOR_VERSION < 3 + return; + #else + return __pyx_m; + #endif +} + +static const char *__pyx_filenames[] = { + "interpnd.pyx", + "numpy.pxd", +}; + + + +static void __pyx_init_filenames(void) { + __pyx_f = __pyx_filenames; +} + +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AS_STRING(kw_name)); + #endif +} + +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *number, *more_or_less; + + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + number = (num_expected == 1) ? "" : "s"; + PyErr_Format(PyExc_TypeError, + #if PY_VERSION_HEX < 0x02050000 + "%s() takes %s %d positional argument%s (%d given)", + #else + "%s() takes %s %zd positional argument%s (%zd given)", + #endif + func_name, more_or_less, num_expected, number, num_found); +} + +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + } else { + #if PY_MAJOR_VERSION < 3 + if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) { + #else + if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) { + #endif + goto invalid_keyword_type; + } else { + for (name = first_kw_arg; *name; name++) { + #if PY_MAJOR_VERSION >= 3 + if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && + PyUnicode_Compare(**name, key) == 0) break; + #else + if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && + _PyString_Eq(**name, key)) break; + #endif + } + if (*name) { + values[name-argnames] = value; + } else { + + for (name=argnames; name != first_kw_arg; name++) { + if (**name == key) goto arg_passed_twice; + #if PY_MAJOR_VERSION >= 3 + if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && + PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice; + #else + if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && + _PyString_Eq(**name, key)) goto arg_passed_twice; + #endif + } + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + } + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, **name); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%s() got an unexpected keyword argument '%s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + + +static double __Pyx__PyObject_AsDouble(PyObject* obj) { + PyObject* float_value; + if (Py_TYPE(obj)->tp_as_number && Py_TYPE(obj)->tp_as_number->nb_float) { + return PyFloat_AsDouble(obj); + } else if (PyUnicode_CheckExact(obj) || PyBytes_CheckExact(obj)) { +#if PY_MAJOR_VERSION >= 3 + float_value = PyFloat_FromString(obj); +#else + float_value = PyFloat_FromString(obj, 0); +#endif + } else { + PyObject* args = PyTuple_New(1); + if (unlikely(!args)) goto bad; + PyTuple_SET_ITEM(args, 0, obj); + float_value = PyObject_Call((PyObject*)&PyFloat_Type, args, 0); + PyTuple_SET_ITEM(args, 0, 0); + Py_DECREF(args); + } + if (likely(float_value)) { + double value = PyFloat_AS_DOUBLE(float_value); + Py_DECREF(float_value); + return value; + } +bad: + return (double)-1; +} + +static CYTHON_INLINE int __Pyx_IsLittleEndian(void) { + unsigned int n = 1; + return *(unsigned char*)(&n) != 0; +} + +typedef struct { + __Pyx_StructField root; + __Pyx_BufFmt_StackElem* head; + size_t fmt_offset; + int new_count, enc_count; + int is_complex; + char enc_type; + char packmode; +} __Pyx_BufFmt_Context; + +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + __Pyx_TypeInfo* type) { + stack[0].field = &ctx->root; + stack[0].parent_offset = 0; + ctx->root.type = type; + ctx->root.name = "buffer dtype"; + ctx->root.offset = 0; + ctx->head = stack; + ctx->head->field = &ctx->root; + ctx->fmt_offset = 0; + ctx->head->parent_offset = 0; + ctx->packmode = '@'; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->is_complex = 0; + while (type->typegroup == 'S') { + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = 0; + type = type->fields->type; + } +} + +static int __Pyx_BufFmt_ParseNumber(const char** ts) { + int count; + const char* t = *ts; + if (*t < '0' || *t > '9') { + return -1; + } else { + count = *t++ - '0'; + while (*t >= '0' && *t < '9') { + count *= 10; + count += *t++ - '0'; + } + } + *ts = t; + return count; +} + +static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { + char msg[] = {ch, 0}; + PyErr_Format(PyExc_ValueError, "Unexpected format string character: '%s'", msg); +} + +static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { + switch (ch) { + case 'b': return "'char'"; + case 'B': return "'unsigned char'"; + case 'h': return "'short'"; + case 'H': return "'unsigned short'"; + case 'i': return "'int'"; + case 'I': return "'unsigned int'"; + case 'l': return "'long'"; + case 'L': return "'unsigned long'"; + case 'q': return "'long long'"; + case 'Q': return "'unsigned long long'"; + case 'f': return (is_complex ? "'complex float'" : "'float'"); + case 'd': return (is_complex ? "'complex double'" : "'double'"); + case 'g': return (is_complex ? "'complex long double'" : "'long double'"); + case 'T': return "a struct"; + case 'O': return "Python object"; + case 'P': return "a pointer"; + case 0: return "end"; + default: return "unparseable format string"; + } +} + +static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': return 1; + case 'h': case 'H': return 2; + case 'i': case 'I': case 'l': case 'L': return 4; + case 'q': case 'Q': return 8; + case 'f': return (is_complex ? 8 : 4); + case 'd': return (is_complex ? 16 : 8); + case 'g': { + PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); + return 0; + } + case 'O': case 'P': return sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} + +static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { + switch (ch) { + case 'c': case 'b': case 'B': return 1; + case 'h': case 'H': return sizeof(short); + case 'i': case 'I': return sizeof(int); + case 'l': case 'L': return sizeof(long); + #ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(PY_LONG_LONG); + #endif + case 'f': return sizeof(float) * (is_complex ? 2 : 1); + case 'd': return sizeof(double) * (is_complex ? 2 : 1); + case 'g': return sizeof(long double) * (is_complex ? 2 : 1); + case 'O': case 'P': return sizeof(void*); + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} + +typedef struct { char c; short x; } __Pyx_st_short; +typedef struct { char c; int x; } __Pyx_st_int; +typedef struct { char c; long x; } __Pyx_st_long; +typedef struct { char c; float x; } __Pyx_st_float; +typedef struct { char c; double x; } __Pyx_st_double; +typedef struct { char c; long double x; } __Pyx_st_longdouble; +typedef struct { char c; void *x; } __Pyx_st_void_p; +#ifdef HAVE_LONG_LONG +typedef struct { char c; PY_LONG_LONG x; } __Pyx_s_long_long; +#endif + +static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': return 1; + case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); +#ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(__Pyx_s_long_long) - sizeof(PY_LONG_LONG); +#endif + case 'f': return sizeof(__Pyx_st_float) - sizeof(float); + case 'd': return sizeof(__Pyx_st_double) - sizeof(double); + case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} + +static size_t __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { + switch (ch) { + case 'c': case 'b': case 'h': case 'i': case 'l': case 'q': return 'I'; + case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U'; + case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R'); + case 'O': return 'O'; + case 'P': return 'P'; + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} + +static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { + if (ctx->head == NULL || ctx->head->field == &ctx->root) { + const char* expected; + const char* quote; + if (ctx->head == NULL) { + expected = "end"; + quote = ""; + } else { + expected = ctx->head->field->type->name; + quote = "'"; + } + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected %s%s%s but got %s", + quote, expected, quote, + __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); + } else { + __Pyx_StructField* field = ctx->head->field; + __Pyx_StructField* parent = (ctx->head - 1)->field; + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", + field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), + parent->type->name, field->name); + } +} + +static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { + char group; + size_t size, offset; + if (ctx->enc_type == 0) return 0; + group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); + do { + __Pyx_StructField* field = ctx->head->field; + __Pyx_TypeInfo* type = field->type; + + if (ctx->packmode == '@' || ctx->packmode == '^') { + size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); + } else { + size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); + } + if (ctx->packmode == '@') { + int align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); + int align_mod_offset; + if (align_at == 0) return -1; + align_mod_offset = ctx->fmt_offset % align_at; + if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; + } + + if (type->size != size || type->typegroup != group) { + if (type->typegroup == 'C' && type->fields != NULL) { + + size_t parent_offset = ctx->head->parent_offset + field->offset; + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = parent_offset; + continue; + } + + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + + offset = ctx->head->parent_offset + field->offset; + if (ctx->fmt_offset != offset) { + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch; next field is at offset %"PY_FORMAT_SIZE_T"d " + "but %"PY_FORMAT_SIZE_T"d expected", ctx->fmt_offset, offset); + return -1; + } + + ctx->fmt_offset += size; + + --ctx->enc_count; + + + while (1) { + if (field == &ctx->root) { + ctx->head = NULL; + if (ctx->enc_count != 0) { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + break; + } + ctx->head->field = ++field; + if (field->type == NULL) { + --ctx->head; + field = ctx->head->field; + continue; + } else if (field->type->typegroup == 'S') { + size_t parent_offset = ctx->head->parent_offset + field->offset; + if (field->type->fields->type == NULL) continue; + field = field->type->fields; + ++ctx->head; + ctx->head->field = field; + ctx->head->parent_offset = parent_offset; + break; + } else { + break; + } + } + } while (ctx->enc_count); + ctx->enc_type = 0; + ctx->is_complex = 0; + return 0; +} + +static int __Pyx_BufFmt_FirstPack(__Pyx_BufFmt_Context* ctx) { + if (ctx->enc_type != 0 || ctx->packmode != '@') { + PyErr_SetString(PyExc_ValueError, "Buffer packing mode currently only allowed at beginning of format string (this is a defect)"); + return -1; + } + return 0; +} + +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { + int got_Z = 0; + while (1) { + switch(*ts) { + case 0: + if (ctx->enc_type != 0 && ctx->head == NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + if (ctx->head != NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + return ts; + case ' ': + case 10: + case 13: + ++ts; + break; + case '<': + if (!__Pyx_IsLittleEndian()) { + PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); + return NULL; + } + if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL; + ctx->packmode = '='; + ++ts; + break; + case '>': + case '!': + if (__Pyx_IsLittleEndian()) { + PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); + return NULL; + } + if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL; + ctx->packmode = '='; + ++ts; + break; + case '=': + case '@': + case '^': + if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL; + ctx->packmode = *ts++; + break; + case 'T': + { + int i; + const char* ts_after_sub; + int struct_count = ctx->new_count; + ctx->new_count = 1; + ++ts; + if (*ts != '{') { + PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); + return NULL; + } + ++ts; + ts_after_sub = ts; + for (i = 0; i != struct_count; ++i) { + ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); + if (!ts_after_sub) return NULL; + } + ts = ts_after_sub; + } + break; + case '}': + ++ts; + return ts; + case 'x': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->fmt_offset += ctx->new_count; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ++ts; + break; + case 'Z': + got_Z = 1; + ++ts; + if (*ts != 'f' && *ts != 'd' && *ts != 'g') { + __Pyx_BufFmt_RaiseUnexpectedChar('Z'); + return NULL; + } + case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': + case 'l': case 'L': case 'q': case 'Q': + case 'f': case 'd': case 'g': + case 'O': + if (ctx->enc_type == *ts && got_Z == ctx->is_complex) { + + ctx->enc_count += ctx->new_count; + } else { + + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_count = ctx->new_count; + ctx->enc_type = *ts; + ctx->is_complex = got_Z; + } + ++ts; + ctx->new_count = 1; + got_Z = 0; + break; + default: + { + ctx->new_count = __Pyx_BufFmt_ParseNumber(&ts); + if (ctx->new_count == -1) { + char msg[2] = { *ts, 0 }; + PyErr_Format(PyExc_ValueError, + "Does not understand character buffer dtype format string ('%s')", msg); + return NULL; + } + } + + } + } +} + +static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) { + buf->buf = NULL; + buf->obj = NULL; + buf->strides = __Pyx_zeros; + buf->shape = __Pyx_zeros; + buf->suboffsets = __Pyx_minusones; +} + +static int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) { + if (obj == Py_None) { + __Pyx_ZeroBuffer(buf); + return 0; + } + buf->buf = NULL; + if (__Pyx_GetBuffer(obj, buf, flags) == -1) goto fail; + if (buf->ndim != nd) { + PyErr_Format(PyExc_ValueError, + "Buffer has wrong number of dimensions (expected %d, got %d)", + nd, buf->ndim); + goto fail; + } + if (!cast) { + __Pyx_BufFmt_Context ctx; + __Pyx_BufFmt_Init(&ctx, stack, dtype); + if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; + } + if ((unsigned)buf->itemsize != dtype->size) { + PyErr_Format(PyExc_ValueError, + "Item size of buffer (%"PY_FORMAT_SIZE_T"d byte%s) does not match size of '%s' (%"PY_FORMAT_SIZE_T"d byte%s)", + buf->itemsize, (buf->itemsize > 1) ? "s" : "", + dtype->name, + dtype->size, (dtype->size > 1) ? "s" : ""); + goto fail; + } + if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; + return 0; +fail:; + __Pyx_ZeroBuffer(buf); + return -1; +} + +static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { + if (info->buf == NULL) return; + if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; + __Pyx_ReleaseBuffer(info); +} + +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + if (unlikely(!type)) { + PyErr_Format(PyExc_SystemError, "Missing type object"); + return 0; + } + if (likely(PyObject_TypeCheck(obj, type))) + return 1; + PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", + Py_TYPE(obj)->tp_name, type->tp_name); + return 0; +} + +static void __Pyx_RaiseBufferFallbackError(void) { + PyErr_Format(PyExc_ValueError, + "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!"); +} + + +static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyThreadState *tstate = PyThreadState_GET(); + + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} + +static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) { + PyThreadState *tstate = PyThreadState_GET(); + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} + + +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { + PyErr_Format(PyExc_ValueError, + #if PY_VERSION_HEX < 0x02050000 + "need more than %d value%s to unpack", (int)index, + #else + "need more than %zd value%s to unpack", index, + #endif + (index == 1) ? "" : "s"); +} + +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void) { + PyErr_SetString(PyExc_ValueError, "too many values to unpack"); +} + +static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) { + PyObject *item; + if (!(item = PyIter_Next(iter))) { + if (!PyErr_Occurred()) { + __Pyx_RaiseNeedMoreValuesError(index); + } + } + return item; +} + +static int __Pyx_EndUnpack(PyObject *iter) { + PyObject *item; + if ((item = PyIter_Next(iter))) { + Py_DECREF(item); + __Pyx_RaiseTooManyValuesError(); + return -1; + } + else if (!PyErr_Occurred()) + return 0; + else + return -1; +} + +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); +} + +static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) { + if (t == Py_None) { + __Pyx_RaiseNoneNotIterableError(); + } else if (PyTuple_GET_SIZE(t) < index) { + __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t)); + } else { + __Pyx_RaiseTooManyValuesError(); + } +} + +static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, + const char *name, int exact) +{ + if (!type) { + PyErr_Format(PyExc_SystemError, "Missing type object"); + return 0; + } + if (none_allowed && obj == Py_None) return 1; + else if (exact) { + if (Py_TYPE(obj) == type) return 1; + } + else { + if (PyObject_TypeCheck(obj, type)) return 1; + } + PyErr_Format(PyExc_TypeError, + "Argument '%s' has incorrect type (expected %s, got %s)", + name, type->tp_name, Py_TYPE(obj)->tp_name); + return 0; +} + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return ::std::complex< double >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return x + y*(__pyx_t_double_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + __pyx_t_double_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +#if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eq(__pyx_t_double_complex a, __pyx_t_double_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + double denom = b.real * b.real + b.imag * b.imag; + z.real = (a.real * b.real + a.imag * b.imag) / denom; + z.imag = (a.imag * b.real - a.real * b.imag) / denom; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero(__pyx_t_double_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + +#endif + +#if PY_MAJOR_VERSION < 3 +static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { + #if PY_VERSION_HEX >= 0x02060000 + if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER) + return PyObject_GetBuffer(obj, view, flags); + #endif + if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pf_5numpy_7ndarray___getbuffer__(obj, view, flags); + else { + PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name); + return -1; + } +} + +static void __Pyx_ReleaseBuffer(Py_buffer *view) { + PyObject* obj = view->obj; + if (obj) { +if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) __pyx_pf_5numpy_7ndarray___releasebuffer__(obj, view); + Py_DECREF(obj); + view->obj = NULL; + } +} + +#endif + +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) { + PyObject *__import__ = 0; + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + __import__ = __Pyx_GetAttrString(__pyx_b, "__import__"); + if (!__import__) + goto bad; + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(__pyx_m); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + module = PyObject_CallFunctionObjArgs(__import__, + name, global_dict, empty_dict, list, NULL); +bad: + Py_XDECREF(empty_list); + Py_XDECREF(__import__); + Py_XDECREF(empty_dict); + return module; +} + +static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) { + PyObject *result; + result = PyObject_GetAttr(dict, name); + if (!result) + PyErr_SetObject(PyExc_NameError, name); + return result; +} + +static PyObject *__Pyx_CreateClass( + PyObject *bases, PyObject *dict, PyObject *name, const char *modname) +{ + PyObject *py_modname; + PyObject *result = 0; + + #if PY_MAJOR_VERSION < 3 + py_modname = PyString_FromString(modname); + #else + py_modname = PyUnicode_FromString(modname); + #endif + if (!py_modname) + goto bad; + if (PyDict_SetItemString(dict, "__module__", py_modname) < 0) + goto bad; + #if PY_MAJOR_VERSION < 3 + result = PyClass_New(bases, dict, name); + #else + result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL); + #endif +bad: + Py_XDECREF(py_modname); + return result; +} + +#if PY_MAJOR_VERSION < 3 +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { + Py_XINCREF(type); + Py_XINCREF(value); + Py_XINCREF(tb); + + if (tb == Py_None) { + Py_DECREF(tb); + tb = 0; + } + else if (tb != NULL && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + + if (value == NULL) { + value = Py_None; + Py_INCREF(value); + } + #if PY_VERSION_HEX < 0x02050000 + if (!PyClass_Check(type)) + #else + if (!PyType_Check(type)) + #endif + { + + if (value != Py_None) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + + Py_DECREF(value); + value = type; + #if PY_VERSION_HEX < 0x02050000 + if (PyInstance_Check(type)) { + type = (PyObject*) ((PyInstanceObject*)type)->in_class; + Py_INCREF(type); + } + else { + type = 0; + PyErr_SetString(PyExc_TypeError, + "raise: exception must be an old-style class or instance"); + goto raise_error; + } + #else + type = (PyObject*) Py_TYPE(type); + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + #endif + } + + __Pyx_ErrRestore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} + +#else + +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (!PyExceptionClass_Check(type)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + + PyErr_SetObject(type, value); + + if (tb) { + PyThreadState *tstate = PyThreadState_GET(); + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } + } + +bad: + return; +} +#endif + +static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_npy_intp(npy_intp val) { + const npy_intp neg_one = (npy_intp)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(npy_intp) < sizeof(long)) { + return PyInt_FromLong((long)val); + } else if (sizeof(npy_intp) == sizeof(long)) { + if (is_unsigned) + return PyLong_FromUnsignedLong((unsigned long)val); + else + return PyInt_FromLong((long)val); + } else { + if (is_unsigned) + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val); + else + return PyLong_FromLongLong((PY_LONG_LONG)val); + } +} + +static __pyx_t_double_complex __Pyx_PyComplex_As___pyx_t_double_complex(PyObject* o) { + Py_complex cval; + if (PyComplex_CheckExact(o)) + cval = ((PyComplexObject *)o)->cval; + else + cval = PyComplex_AsCComplex(o); + return __pyx_t_double_complex_from_parts( + (double)cval.real, + (double)cval.imag); +} + +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return ::std::complex< float >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return x + y*(__pyx_t_float_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + __pyx_t_float_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +#if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eqf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sumf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_difff(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prodf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quotf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + float denom = b.real * b.real + b.imag * b.imag; + z.real = (a.real * b.real + a.imag * b.imag) / denom; + z.imag = (a.imag * b.real - a.real * b.imag) / denom; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_negf(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zerof(__pyx_t_float_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conjf(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + +#endif + +static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject* x) { + const unsigned char neg_one = (unsigned char)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(unsigned char) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(unsigned char)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to unsigned char" : + "value too large to convert to unsigned char"); + } + return (unsigned char)-1; + } + return (unsigned char)val; + } + return (unsigned char)__Pyx_PyInt_AsUnsignedLong(x); +} + +static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject* x) { + const unsigned short neg_one = (unsigned short)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(unsigned short) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(unsigned short)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to unsigned short" : + "value too large to convert to unsigned short"); + } + return (unsigned short)-1; + } + return (unsigned short)val; + } + return (unsigned short)__Pyx_PyInt_AsUnsignedLong(x); +} + +static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject* x) { + const unsigned int neg_one = (unsigned int)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(unsigned int) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(unsigned int)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to unsigned int" : + "value too large to convert to unsigned int"); + } + return (unsigned int)-1; + } + return (unsigned int)val; + } + return (unsigned int)__Pyx_PyInt_AsUnsignedLong(x); +} + +static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject* x) { + const char neg_one = (char)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(char) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(char)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to char" : + "value too large to convert to char"); + } + return (char)-1; + } + return (char)val; + } + return (char)__Pyx_PyInt_AsLong(x); +} + +static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject* x) { + const short neg_one = (short)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(short) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(short)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to short" : + "value too large to convert to short"); + } + return (short)-1; + } + return (short)val; + } + return (short)__Pyx_PyInt_AsLong(x); +} + +static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject* x) { + const int neg_one = (int)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(int) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(int)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to int" : + "value too large to convert to int"); + } + return (int)-1; + } + return (int)val; + } + return (int)__Pyx_PyInt_AsLong(x); +} + +static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject* x) { + const signed char neg_one = (signed char)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(signed char) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(signed char)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to signed char" : + "value too large to convert to signed char"); + } + return (signed char)-1; + } + return (signed char)val; + } + return (signed char)__Pyx_PyInt_AsSignedLong(x); +} + +static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject* x) { + const signed short neg_one = (signed short)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(signed short) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(signed short)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to signed short" : + "value too large to convert to signed short"); + } + return (signed short)-1; + } + return (signed short)val; + } + return (signed short)__Pyx_PyInt_AsSignedLong(x); +} + +static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject* x) { + const signed int neg_one = (signed int)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; + if (sizeof(signed int) < sizeof(long)) { + long val = __Pyx_PyInt_AsLong(x); + if (unlikely(val != (long)(signed int)val)) { + if (!unlikely(val == -1 && PyErr_Occurred())) { + PyErr_SetString(PyExc_OverflowError, + (is_unsigned && unlikely(val < 0)) ? + "can't convert negative value to signed int" : + "value too large to convert to signed int"); + } + return (signed int)-1; + } + return (signed int)val; + } + return (signed int)__Pyx_PyInt_AsSignedLong(x); +} + +static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) { + const unsigned long neg_one = (unsigned long)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to unsigned long"); + return (unsigned long)-1; + } + return (unsigned long)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to unsigned long"); + return (unsigned long)-1; + } + return PyLong_AsUnsignedLong(x); + } else { + return PyLong_AsLong(x); + } + } else { + unsigned long val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (unsigned long)-1; + val = __Pyx_PyInt_AsUnsignedLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject* x) { + const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to unsigned PY_LONG_LONG"); + return (unsigned PY_LONG_LONG)-1; + } + return (unsigned PY_LONG_LONG)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to unsigned PY_LONG_LONG"); + return (unsigned PY_LONG_LONG)-1; + } + return PyLong_AsUnsignedLongLong(x); + } else { + return PyLong_AsLongLong(x); + } + } else { + unsigned PY_LONG_LONG val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (unsigned PY_LONG_LONG)-1; + val = __Pyx_PyInt_AsUnsignedLongLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) { + const long neg_one = (long)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long)-1; + } + return (long)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long)-1; + } + return PyLong_AsUnsignedLong(x); + } else { + return PyLong_AsLong(x); + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (long)-1; + val = __Pyx_PyInt_AsLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) { + const PY_LONG_LONG neg_one = (PY_LONG_LONG)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to PY_LONG_LONG"); + return (PY_LONG_LONG)-1; + } + return (PY_LONG_LONG)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to PY_LONG_LONG"); + return (PY_LONG_LONG)-1; + } + return PyLong_AsUnsignedLongLong(x); + } else { + return PyLong_AsLongLong(x); + } + } else { + PY_LONG_LONG val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (PY_LONG_LONG)-1; + val = __Pyx_PyInt_AsLongLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) { + const signed long neg_one = (signed long)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to signed long"); + return (signed long)-1; + } + return (signed long)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to signed long"); + return (signed long)-1; + } + return PyLong_AsUnsignedLong(x); + } else { + return PyLong_AsLong(x); + } + } else { + signed long val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (signed long)-1; + val = __Pyx_PyInt_AsSignedLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject* x) { + const signed PY_LONG_LONG neg_one = (signed PY_LONG_LONG)-1, const_zero = 0; + const int is_unsigned = neg_one > const_zero; +#if PY_VERSION_HEX < 0x03000000 + if (likely(PyInt_Check(x))) { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to signed PY_LONG_LONG"); + return (signed PY_LONG_LONG)-1; + } + return (signed PY_LONG_LONG)val; + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { + if (unlikely(Py_SIZE(x) < 0)) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to signed PY_LONG_LONG"); + return (signed PY_LONG_LONG)-1; + } + return PyLong_AsUnsignedLongLong(x); + } else { + return PyLong_AsLongLong(x); + } + } else { + signed PY_LONG_LONG val; + PyObject *tmp = __Pyx_PyNumber_Int(x); + if (!tmp) return (signed PY_LONG_LONG)-1; + val = __Pyx_PyInt_AsSignedLongLong(tmp); + Py_DECREF(tmp); + return val; + } +} + +#ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, + long size, int strict) +{ + PyObject *py_module = 0; + PyObject *result = 0; + PyObject *py_name = 0; + char warning[200]; + + py_module = __Pyx_ImportModule(module_name); + if (!py_module) + goto bad; + #if PY_MAJOR_VERSION < 3 + py_name = PyString_FromString(class_name); + #else + py_name = PyUnicode_FromString(class_name); + #endif + if (!py_name) + goto bad; + result = PyObject_GetAttr(py_module, py_name); + Py_DECREF(py_name); + py_name = 0; + Py_DECREF(py_module); + py_module = 0; + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%s.%s is not a type object", + module_name, class_name); + goto bad; + } + if (!strict && ((PyTypeObject *)result)->tp_basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility", + module_name, class_name); + PyErr_WarnEx(NULL, warning, 0); + } + else if (((PyTypeObject *)result)->tp_basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%s.%s has the wrong size, try recompiling", + module_name, class_name); + goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(py_module); + Py_XDECREF(result); + return 0; +} +#endif + +#ifndef __PYX_HAVE_RT_ImportModule +#define __PYX_HAVE_RT_ImportModule +static PyObject *__Pyx_ImportModule(const char *name) { + PyObject *py_name = 0; + PyObject *py_module = 0; + + #if PY_MAJOR_VERSION < 3 + py_name = PyString_FromString(name); + #else + py_name = PyUnicode_FromString(name); + #endif + if (!py_name) + goto bad; + py_module = PyImport_Import(py_name); + Py_DECREF(py_name); + return py_module; +bad: + Py_XDECREF(py_name); + return 0; +} +#endif + +#ifndef __PYX_HAVE_RT_ImportFunction +#define __PYX_HAVE_RT_ImportFunction +static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig) { + PyObject *d = 0; + PyObject *cobj = 0; + union { + void (*fp)(void); + void *p; + } tmp; +#if PY_VERSION_HEX < 0x03010000 + const char *desc, *s1, *s2; +#endif + + d = PyObject_GetAttrString(module, (char *)"__pyx_capi__"); + if (!d) + goto bad; + cobj = PyDict_GetItemString(d, funcname); + if (!cobj) { + PyErr_Format(PyExc_ImportError, + "%s does not export expected C function %s", + PyModule_GetName(module), funcname); + goto bad; + } +#if PY_VERSION_HEX < 0x03010000 + desc = (const char *)PyCObject_GetDesc(cobj); + if (!desc) + goto bad; + s1 = desc; s2 = sig; + while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } + if (*s1 != *s2) { + PyErr_Format(PyExc_TypeError, + "C function %s.%s has wrong signature (expected %s, got %s)", + PyModule_GetName(module), funcname, sig, desc); + goto bad; + } + tmp.p = PyCObject_AsVoidPtr(cobj); +#else + if (!PyCapsule_IsValid(cobj, sig)) { + PyErr_Format(PyExc_TypeError, + "C function %s.%s has wrong signature (expected %s, got %s)", + PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj)); + goto bad; + } + tmp.p = PyCapsule_GetPointer(cobj, sig); +#endif + *f = tmp.fp; + if (!(*f)) + goto bad; + Py_DECREF(d); + return 0; +bad: + Py_XDECREF(d); + return -1; +} +#endif + +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" + +static void __Pyx_AddTraceback(const char *funcname) { + PyObject *py_srcfile = 0; + PyObject *py_funcname = 0; + PyObject *py_globals = 0; + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + + #if PY_MAJOR_VERSION < 3 + py_srcfile = PyString_FromString(__pyx_filename); + #else + py_srcfile = PyUnicode_FromString(__pyx_filename); + #endif + if (!py_srcfile) goto bad; + if (__pyx_clineno) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + #else + py_funcname = PyUnicode_FromString(funcname); + #endif + } + if (!py_funcname) goto bad; + py_globals = PyModule_GetDict(__pyx_m); + if (!py_globals) goto bad; + py_code = PyCode_New( + 0, + #if PY_MAJOR_VERSION >= 3 + 0, + #endif + 0, + 0, + 0, + __pyx_empty_bytes, + __pyx_empty_tuple, + __pyx_empty_tuple, + __pyx_empty_tuple, + __pyx_empty_tuple, + __pyx_empty_tuple, + py_srcfile, + py_funcname, + __pyx_lineno, + __pyx_empty_bytes + ); + if (!py_code) goto bad; + py_frame = PyFrame_New( + PyThreadState_GET(), + py_code, + py_globals, + 0 + ); + if (!py_frame) goto bad; + py_frame->f_lineno = __pyx_lineno; + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_srcfile); + Py_XDECREF(py_funcname); + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { + while (t->p) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + ++t; + } + return 0; +} + + + +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + if (x == Py_True) return 1; + else if ((x == Py_False) | (x == Py_None)) return 0; + else return PyObject_IsTrue(x); +} + +static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) { + PyNumberMethods *m; + const char *name = NULL; + PyObject *res = NULL; +#if PY_VERSION_HEX < 0x03000000 + if (PyInt_Check(x) || PyLong_Check(x)) +#else + if (PyLong_Check(x)) +#endif + return Py_INCREF(x), x; + m = Py_TYPE(x)->tp_as_number; +#if PY_VERSION_HEX < 0x03000000 + if (m && m->nb_int) { + name = "int"; + res = PyNumber_Int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = PyNumber_Long(x); + } +#else + if (m && m->nb_int) { + name = "int"; + res = PyNumber_Long(x); + } +#endif + if (res) { +#if PY_VERSION_HEX < 0x03000000 + if (!PyInt_Check(res) && !PyLong_Check(res)) { +#else + if (!PyLong_Check(res)) { +#endif + PyErr_Format(PyExc_TypeError, + "__%s__ returned non-%s (type %.200s)", + name, name, Py_TYPE(res)->tp_name); + Py_DECREF(res); + return NULL; + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} + +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject* x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} + +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { +#if PY_VERSION_HEX < 0x02050000 + if (ival <= LONG_MAX) + return PyInt_FromLong((long)ival); + else { + unsigned char *bytes = (unsigned char *) &ival; + int one = 1; int little = (int)*(unsigned char*)&one; + return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0); + } +#else + return PyInt_FromSize_t(ival); +#endif +} + +static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) { + unsigned PY_LONG_LONG val = __Pyx_PyInt_AsUnsignedLongLong(x); + if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) { + return (size_t)-1; + } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) { + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to size_t"); + return (size_t)-1; + } + return (size_t)val; +} + + +#endif From scipy-svn at scipy.org Tue Aug 31 17:58:55 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 16:58:55 -0500 (CDT) Subject: [Scipy-svn] r6657 - in trunk/scipy/interpolate: . tests Message-ID: <20100831215855.3948E39CD25@scipy.org> Author: ptvirtan Date: 2010-08-31 16:58:55 -0500 (Tue, 31 Aug 2010) New Revision: 6657 Added: trunk/scipy/interpolate/griddatand.py trunk/scipy/interpolate/tests/test_griddatand.py Modified: trunk/scipy/interpolate/__init__.py Log: interpolate: add griddata, convenience function for N-d interpolation Add a convenience function for easy N-d interpolation. Modified: trunk/scipy/interpolate/__init__.py =================================================================== --- trunk/scipy/interpolate/__init__.py 2010-08-31 21:58:25 UTC (rev 6656) +++ trunk/scipy/interpolate/__init__.py 2010-08-31 21:58:55 UTC (rev 6657) @@ -14,6 +14,8 @@ from polyint import * +from griddatand import * + __all__ = filter(lambda s:not s.startswith('_'),dir()) from numpy.testing import Tester test = Tester().test Added: trunk/scipy/interpolate/griddatand.py =================================================================== --- trunk/scipy/interpolate/griddatand.py (rev 0) +++ trunk/scipy/interpolate/griddatand.py 2010-08-31 21:58:55 UTC (rev 6657) @@ -0,0 +1,172 @@ +""" +Convenience interface to N-D interpolation + +.. versionadded:: 0.9 + +""" + +import numpy as np +from interpnd import LinearNDInterpolator, NDInterpolatorBase, \ + CloughTocher2DInterpolator, _ndim_coords_from_arrays +from scipy.spatial import cKDTree + +__all__ = ['griddata', 'NearestNDInterpolator', 'LinearNDInterpolator', + 'CloughTocher2DInterpolator'] + +#------------------------------------------------------------------------------ +# Nearest-neighbour interpolation +#------------------------------------------------------------------------------ + +class NearestNDInterpolator(NDInterpolatorBase): + """ + NearestNDInterpolator(points, values) + + Nearest-neighbour interpolation in N dimensions. + + .. versionadded:: 0.9 + + Parameters + ---------- + points : ndarray of floats, shape (npoints, ndims) + Data point coordinates. + values : ndarray of float or complex, shape (npoints, ...) + Data values. + + Notes + ----- + Uses ``scipy.spatial.cKDTree`` + + """ + + def __init__(self, x, y): + x = _ndim_coords_from_arrays(x) + self._check_init_shape(x, y) + self.tree = cKDTree(x) + self.points = x + self.values = y + + def __call__(self, xi): + """ + Evaluate interpolator at given points. + + Parameters + ---------- + xi : ndarray of float, shape (..., ndim) + Points where to interpolate data at. + + """ + xi = self._check_call_shape(xi) + dist, i = self.tree.query(xi) + return self.values[i] + + +#------------------------------------------------------------------------------ +# Convenience interface function +#------------------------------------------------------------------------------ + +def griddata(points, values, xi, method='linear'): + """ + griddata(points, values, xi, method='linear') + + Interpolate unstructured N-dimensional data. + + .. versionadded:: 0.9 + + Parameters + ---------- + points : ndarray of floats, shape (npoints, ndims) + Data point coordinates. Can either be a ndarray of + size (npoints, ndim), or a tuple of `ndim` arrays. + values : ndarray of float or complex, shape (npoints, ...) + Data values. + xi : ndarray of float, shape (..., ndim) + Points where to interpolate data at. + + method : {'linear', 'nearest', 'cubic'} + Method of interpolation. One of + + - ``nearest``: return the value at the data point closest to + the point of interpolation. See `NearestNDInterpolator` for + more details. + + - ``linear``: tesselate the input point set to n-dimensional + simplices, and interpolate linearly on each simplex. See + `LinearNDInterpolator` for more details. + + - ``cubic`` (1-D): return the value detemined from a cubic + spline. + + - ``cubic`` (2-D): return the value determined from a + piecewise cubic, continuously differentiable (C1), and + approximately curvature-minimizing polynomial surface. See + `CloughTocher2DInterpolator` for more details. + + + Examples + -------- + + Suppose we want to interpolate the 2-D function + + >>> def func(x, y): + >>> return x*(1-x)*np.cos(4*np.pi*x) * np.sin(4*np.pi*y**2)**2 + + on a grid in [0, 1]x[0, 1] + + >>> grid_x, grid_y = np.mgrid[0:1:100j, 0:1:200j] + + but we only know its values at 1000 data points: + + >>> points = np.random.rand(1000, 2) + >>> values = func(points[:,0], points[:,1]) + + This can be done with `griddata` -- below we try out all of the + interpolation methods: + + >>> from scipy.interpolate import griddata + >>> grid_z0 = griddata(points, values, (grid_x, grid_y), method='nearest') + >>> grid_z1 = griddata(points, values, (grid_x, grid_y), method='linear') + >>> grid_z2 = griddata(points, values, (grid_x, grid_y), method='cubic') + + One can see that the exact result is reproduced by all of the + methods to some degree, but for this smooth function the piecewise + cubic interpolant gives the best results: + + >>> import matplotlib.pyplot as plt + >>> plt.subplot(221) + >>> plt.imshow(func(grid_x, grid_y).T, extent=(0,1,0,1), origin='lower') + >>> plt.plot(points[:,0], points[:,1], 'k.', ms=1) + >>> plt.title('Original') + >>> plt.subplot(222) + >>> plt.imshow(grid_z0.T, extent=(0,1,0,1), origin='lower') + >>> plt.title('Nearest') + >>> plt.subplot(223) + >>> plt.imshow(grid_z1.T, extent=(0,1,0,1), origin='lower') + >>> plt.title('Linear') + >>> plt.subplot(224) + >>> plt.imshow(grid_z2.T, extent=(0,1,0,1), origin='lower') + >>> plt.title('Cubic') + >>> plt.gcf().set_size_inches(6, 6) + >>> plt.show() + + """ + + points = _ndim_coords_from_arrays(points) + xi = _ndim_coords_from_arrays(xi) + + ndim = points.shape[-1] + + if ndim == 1 and method in ('nearest', 'linear', 'cubic'): + ip = interp1d(points, values, kind=method, axis=0, bounds_error=False) + return ip(xi) + elif method == 'nearest': + ip = NearestNDInterpolator(points, values) + return ip(xi) + elif method == 'linear': + ip = LinearNDInterpolator(points, values) + return ip(xi) + elif method == 'cubic' and ndim == 2: + ip = CloughTocher2DInterpolator(points, values) + return ip(xi) + else: + raise ValueError("Unknown interpolation method %r for " + "%d dimensional data" % (method, ndim)) Added: trunk/scipy/interpolate/tests/test_griddatand.py =================================================================== --- trunk/scipy/interpolate/tests/test_griddatand.py (rev 0) +++ trunk/scipy/interpolate/tests/test_griddatand.py 2010-08-31 21:58:55 UTC (rev 6657) @@ -0,0 +1,57 @@ +import numpy as np +from numpy.testing import * + +from scipy.interpolate.griddatand import griddata + + +class TestGriddata(object): + + def test_alternative_call(self): + x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)], + dtype=np.double) + y = (np.arange(x.shape[0], dtype=np.double)[:,None] + + np.array([0,1])[None,:]) + + for method in ('nearest', 'linear', 'cubic'): + yi = griddata((x[:,0], x[:,1]), y, (x[:,0], x[:,1]), method=method) + assert_almost_equal(y, yi, err_msg=method) + + def test_multivalue_2d(self): + x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)], + dtype=np.double) + y = (np.arange(x.shape[0], dtype=np.double)[:,None] + + np.array([0,1])[None,:]) + + for method in ('nearest', 'linear', 'cubic'): + yi = griddata(x, y, x, method=method) + assert_almost_equal(y, yi, err_msg=method) + + def test_multipoint_2d(self): + x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)], + dtype=np.double) + y = np.arange(x.shape[0], dtype=np.double) + + xi = x[:,None,:] + np.array([0,0,0])[None,:,None] + + for method in ('nearest', 'linear', 'cubic'): + yi = griddata(x, y, xi, method=method) + + assert_equal(yi.shape, (5, 3), err_msg=method) + assert_almost_equal(yi, np.tile(y[:,None], (1, 3)), err_msg=method) + + def test_complex_2d(self): + x = np.array([(0,0), (-0.5,-0.5), (-0.5,0.5), (0.5, 0.5), (0.25, 0.3)], + dtype=np.double) + y = np.arange(x.shape[0], dtype=np.double) + y = y - 2j*y[::-1] + + xi = x[:,None,:] + np.array([0,0,0])[None,:,None] + + for method in ('nearest', 'linear', 'cubic'): + yi = griddata(x, y, xi, method=method) + + assert_equal(yi.shape, (5, 3), err_msg=method) + assert_almost_equal(yi, np.tile(y[:,None], (1, 3)), err_msg=method) + +if __name__ == "__main__": + run_module_suite() From scipy-svn at scipy.org Tue Aug 31 17:59:25 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 16:59:25 -0500 (CDT) Subject: [Scipy-svn] r6658 - in trunk: doc/source scipy/spatial Message-ID: <20100831215925.9B7B839CD2B@scipy.org> Author: ptvirtan Date: 2010-08-31 16:59:25 -0500 (Tue, 31 Aug 2010) New Revision: 6658 Modified: trunk/doc/source/spatial.distance.rst trunk/doc/source/spatial.rst trunk/scipy/spatial/distance.py trunk/scipy/spatial/info.py Log: DOC: spatial: move scipy.spatial docs to the module docstrings Modified: trunk/doc/source/spatial.distance.rst =================================================================== --- trunk/doc/source/spatial.distance.rst 2010-08-31 21:58:55 UTC (rev 6657) +++ trunk/doc/source/spatial.distance.rst 2010-08-31 21:59:25 UTC (rev 6658) @@ -1,6 +1 @@ -===================================================== -Distance computations (:mod:`scipy.spatial.distance`) -===================================================== - .. automodule:: scipy.spatial.distance - :members: Modified: trunk/doc/source/spatial.rst =================================================================== --- trunk/doc/source/spatial.rst 2010-08-31 21:58:55 UTC (rev 6657) +++ trunk/doc/source/spatial.rst 2010-08-31 21:59:25 UTC (rev 6658) @@ -1,14 +1,6 @@ -============================================================= -Spatial algorithms and data structures (:mod:`scipy.spatial`) -============================================================= +.. automodule:: scipy.spatial -.. warning:: - - This documentation is work-in-progress and unorganized. - .. toctree:: + :hidden: spatial.distance - -.. automodule:: scipy.spatial - :members: Modified: trunk/scipy/spatial/distance.py =================================================================== --- trunk/scipy/spatial/distance.py 2010-08-31 21:58:55 UTC (rev 6657) +++ trunk/scipy/spatial/distance.py 2010-08-31 21:59:25 UTC (rev 6658) @@ -1,90 +1,65 @@ """ +===================================================== +Distance computations (:mod:`scipy.spatial.distance`) +===================================================== + +.. sectionauthor:: Damian Eads + Function Reference ------------------ Distance matrix computation from a collection of raw observation vectors stored in a rectangular array. -+------------------+-------------------------------------------------+ -|*Function* | *Description* | -+------------------+-------------------------------------------------+ -|pdist | pairwise distances between observation | -| | vectors. | -+------------------+-------------------------------------------------+ -|cdist | distances between between two collections of | -| | observation vectors. | -+------------------+-------------------------------------------------+ -|squareform | converts a square distance matrix to a | -| | condensed one and vice versa. | -+------------------+-------------------------------------------------+ +.. autosummary:: + :toctree: generated/ + pdist -- pairwise distances between observation vectors. + cdist -- distances between between two collections of observation vectors + squareform -- convert distance matrix to a condensed one and vice versa + Predicates for checking the validity of distance matrices, both condensed and redundant. Also contained in this module are functions for computing the number of observations in a distance matrix. -+------------------+-------------------------------------------------+ -|*Function* | *Description* | -+------------------+-------------------------------------------------+ -|is_valid_dm | checks for a valid distance matrix. | -+------------------+-------------------------------------------------+ -|is_valid_y | checks for a valid condensed distance matrix. | -+------------------+-------------------------------------------------+ -|num_obs_dm | # of observations in a distance matrix. | -+------------------+-------------------------------------------------+ -|num_obs_y | # of observations in a condensed distance | -| | matrix. | -+------------------+-------------------------------------------------+ +.. autosummary:: + :toctree: generated/ + is_valid_dm -- checks for a valid distance matrix + is_valid_y -- checks for a valid condensed distance matrix + num_obs_dm -- # of observations in a distance matrix + num_obs_y -- # of observations in a 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. -+------------------+-------------------------------------------------+ -|*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). | -+------------------+-------------------------------------------------+ +.. autosummary:: + :toctree: generated/ + 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 ---------- Modified: trunk/scipy/spatial/info.py =================================================================== --- trunk/scipy/spatial/info.py 2010-08-31 21:58:55 UTC (rev 6657) +++ trunk/scipy/spatial/info.py 2010-08-31 21:59:25 UTC (rev 6658) @@ -1,12 +1,25 @@ """ -Spatial data structures and algorithms -====================================== +============================================================= +Spatial algorithms and data structures (:mod:`scipy.spatial`) +============================================================= Nearest-neighbor queries: - KDTree -- class for efficient nearest-neighbor queries - distance -- module containing many different distance measures +.. autosummary:: + :toctree: generated/ + KDTree -- class for efficient nearest-neighbor queries + cKDTree -- class for efficient nearest-neighbor queries (faster impl.) + distance -- module containing many different distance measures + +Delaunay triangulation: + +.. autosummary:: + :toctree: generated/ + + Delaunay + tsearch + """ postpone_import = 1 From scipy-svn at scipy.org Tue Aug 31 17:59:46 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 16:59:46 -0500 (CDT) Subject: [Scipy-svn] r6659 - trunk Message-ID: <20100831215946.1865739CD2F@scipy.org> Author: ptvirtan Date: 2010-08-31 16:59:46 -0500 (Tue, 31 Aug 2010) New Revision: 6659 Modified: trunk/.gitignore Log: Add additional items to ignore to .gitignore Modified: trunk/.gitignore =================================================================== --- trunk/.gitignore 2010-08-31 21:59:25 UTC (rev 6658) +++ trunk/.gitignore 2010-08-31 21:59:46 UTC (rev 6659) @@ -2,6 +2,15 @@ *.swp *.pyd *.so +*.o +*.lo +*.la +*~ +*.bak +*.swp +.\#* +.deps +.libs /build /dist /scipy.egg-info From scipy-svn at scipy.org Tue Aug 31 18:00:01 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 17:00:01 -0500 (CDT) Subject: [Scipy-svn] r6660 - trunk/doc/source Message-ID: <20100831220001.993E539CD30@scipy.org> Author: ptvirtan Date: 2010-08-31 17:00:01 -0500 (Tue, 31 Aug 2010) New Revision: 6660 Modified: trunk/doc/source/conf.py Log: DOC: generate plots Modified: trunk/doc/source/conf.py =================================================================== --- trunk/doc/source/conf.py 2010-08-31 21:59:46 UTC (rev 6659) +++ trunk/doc/source/conf.py 2010-08-31 22:00:01 UTC (rev 6660) @@ -226,8 +226,8 @@ # If we want to do a phantom import from an XML file for all autodocs phantom_import_file = 'dump.xml' -# Edit links -#numpydoc_edit_link = '`Edit `__' +# Generate plots for example sections +numpydoc_use_plots = True # ----------------------------------------------------------------------------- # Autosummary @@ -264,6 +264,7 @@ """ plot_include_source = True plot_formats = [('png', 100), 'pdf'] +plot_html_show_formats = False import math phi = (math.sqrt(5) + 1)/2 From scipy-svn at scipy.org Tue Aug 31 18:00:19 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 17:00:19 -0500 (CDT) Subject: [Scipy-svn] r6661 - trunk/doc Message-ID: <20100831220019.1372139CD34@scipy.org> Author: ptvirtan Date: 2010-08-31 17:00:18 -0500 (Tue, 31 Aug 2010) New Revision: 6661 Modified: trunk/doc/Makefile Log: DOC: Makefile: add FILES option for partial rebuilds Modified: trunk/doc/Makefile =================================================================== --- trunk/doc/Makefile 2010-08-31 22:00:01 UTC (rev 6660) +++ trunk/doc/Makefile 2010-08-31 22:00:18 UTC (rev 6661) @@ -9,6 +9,8 @@ SPHINXBUILD = LANG=C sphinx-build PAPER = +FILES= + NEED_AUTOSUMMARY = $(shell $(PYTHON) -c 'import sphinx; print sphinx.__version__ < "0.7" and "1" or ""') # Internal variables. @@ -108,14 +110,14 @@ html: generate mkdir -p build/html build/doctrees - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html $(FILES) $(PYTHON) postprocess.py html build/html/*.html @echo @echo "Build finished. The HTML pages are in build/html." pickle: generate mkdir -p build/pickle build/doctrees - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle $(FILES) @echo @echo "Build finished; now you can process the pickle files or run" @echo " sphinx-web build/pickle" @@ -125,7 +127,7 @@ htmlhelp: generate mkdir -p build/htmlhelp build/doctrees - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp $(FILES) @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in build/htmlhelp." @@ -136,7 +138,7 @@ latex: generate mkdir -p build/latex build/doctrees - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex $(FILES) $(PYTHON) postprocess.py tex build/latex/*.tex perl -pi -e 's/\t(latex.*|pdflatex) (.*)/\t-$$1 -interaction batchmode $$2/' build/latex/Makefile @echo @@ -146,18 +148,18 @@ coverage: build mkdir -p build/coverage build/doctrees - $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) build/coverage + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) build/coverage $(FILES) @echo "Coverage finished; see c.txt and python.txt in build/coverage" changes: generate mkdir -p build/changes build/doctrees - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes $(FILES) @echo @echo "The overview file is in build/changes." linkcheck: generate mkdir -p build/linkcheck build/doctrees - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck $(FILES) @echo @echo "Link check complete; look for any errors in the above output " \ "or in build/linkcheck/output.txt." From scipy-svn at scipy.org Tue Aug 31 18:00:43 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 17:00:43 -0500 (CDT) Subject: [Scipy-svn] r6662 - in trunk/doc/source: . tutorial Message-ID: <20100831220043.B47B039CD35@scipy.org> Author: ptvirtan Date: 2010-08-31 17:00:43 -0500 (Tue, 31 Aug 2010) New Revision: 6662 Modified: trunk/doc/source/interpolate.rst trunk/doc/source/tutorial/interpolate.rst Log: DOC: add documentation for griddata and the other N-dimensional interpolation utilities Modified: trunk/doc/source/interpolate.rst =================================================================== --- trunk/doc/source/interpolate.rst 2010-08-31 22:00:18 UTC (rev 6661) +++ trunk/doc/source/interpolate.rst 2010-08-31 22:00:43 UTC (rev 6662) @@ -22,13 +22,25 @@ Multivariate interpolation ========================== +Unstructured data: + .. autosummary:: :toctree: generated/ - interp2d + griddata + LinearNDInterpolator + NearestNDInterpolator + CloughTocher2DInterpolator Rbf +Data given on a regular grid: +.. autosummary:: + :toctree: generated/ + + interp2d + + 1-D Splines =========== Modified: trunk/doc/source/tutorial/interpolate.rst =================================================================== --- trunk/doc/source/tutorial/interpolate.rst 2010-08-31 22:00:18 UTC (rev 6661) +++ trunk/doc/source/tutorial/interpolate.rst 2010-08-31 22:00:43 UTC (rev 6662) @@ -1,3 +1,4 @@ +======================================== Interpolation (:mod:`scipy.interpolate`) ======================================== @@ -3,19 +4,31 @@ .. sectionauthor:: Travis E. Oliphant +.. sectionauthor:: Pauli Virtanen + .. currentmodule:: scipy.interpolate .. contents:: -There are two general interpolation facilities available in SciPy. The -first facility is an interpolation class which performs linear -1-dimensional interpolation. The second facility is based on the -FORTRAN library FITPACK and provides functions for 1- and -2-dimensional (smoothed) cubic-spline interpolation. There are both -procedural and object-oriented interfaces for the FITPACK library. +There are several general interpolation facilities available in SciPy, +for data in 1, 2, and higher dimensions: +- A class representing an interpolant (:class:`interp1d`) in 1-D, + offering several interpolation methods. -Linear 1-d interpolation (:class:`interp1d`) --------------------------------------------- +- Convenience function :func:`griddata` offering a simple interface to + interpolation in N dimensions (N = 1, 2, 3, 4, ...). + Object-oriented interface for the underlying routines is also + available. +- Functions for 1- and 2-dimensional (smoothed) cubic-spline + interpolation, based on the FORTRAN library FITPACK. There are both + procedural and object-oriented interfaces for the FITPACK library. + +- Interpolation using Radial Basis Functions. + + +1-D interpolation (:class:`interp1d`) +===================================== + The interp1d class in scipy.interpolate is a convenient method to create a function based on fixed data points which can be evaluated @@ -27,25 +40,83 @@ interpolates between known data values to obtain unknown values (it also has a docstring for help). Behavior at the boundary can be specified at instantiation time. The following example demonstrates -it's use. +its use, for linear and cubic spline interpolation: .. plot:: - >>> import numpy as np - >>> from scipy import interpolate + >>> from scipy.interpolate import interp1d - >>> x = np.arange(0,10) + >>> x = np.linspace(0, 10, 10) >>> y = np.exp(-x/3.0) - >>> f = interpolate.interp1d(x, y) + >>> f = interp1d(x, y) + >>> f2 = interp1d(x, y, kind='cubic') - >>> xnew = np.arange(0,9,0.1) + >>> xnew = np.linspace(0, 10, 40) >>> import matplotlib.pyplot as plt - >>> plt.plot(x,y,'o',xnew,f(xnew),'-') + >>> plt.plot(x,y,'o',xnew,f(xnew),'-', xnew, f2(xnew),'--') + >>> plt.legend(['data', 'linear', 'cubic'], loc='best') + >>> plt.show() .. :caption: One-dimensional interpolation using the .. class :obj:`interpolate.interp1d` +Multivariate data interpolation (:func:`griddata`) +================================================== + +Suppose you have multidimensional data, for instance for an underlying +function *f(x, y)* you only know the values at points *(x[i], y[i])* +that do not form a regular grid. + +.. plot:: + + Suppose we want to interpolate the 2-D function + + >>> def func(x, y): + >>> return x*(1-x)*np.cos(4*np.pi*x) * np.sin(4*np.pi*y**2)**2 + + on a grid in [0, 1]x[0, 1] + + >>> grid_x, grid_y = np.mgrid[0:1:100j, 0:1:200j] + + but we only know its values at 1000 data points: + + >>> points = np.random.rand(1000, 2) + >>> values = func(points[:,0], points[:,1]) + + This can be done with `griddata` -- below we try out all of the + interpolation methods: + + >>> from scipy.interpolate import griddata + >>> grid_z0 = griddata(points, values, (grid_x, grid_y), method='nearest') + >>> grid_z1 = griddata(points, values, (grid_x, grid_y), method='linear') + >>> grid_z2 = griddata(points, values, (grid_x, grid_y), method='cubic') + + One can see that the exact result is reproduced by all of the + methods to some degree, but for this smooth function the piecewise + cubic interpolant gives the best results: + + >>> import matplotlib.pyplot as plt + >>> plt.subplot(221) + >>> plt.imshow(func(grid_x, grid_y).T, extent=(0,1,0,1), origin='lower') + >>> plt.plot(points[:,0], points[:,1], 'k.', ms=1) + >>> plt.title('Original') + >>> plt.subplot(222) + >>> plt.imshow(grid_z0.T, extent=(0,1,0,1), origin='lower') + >>> plt.title('Nearest') + >>> plt.subplot(223) + >>> plt.imshow(grid_z1.T, extent=(0,1,0,1), origin='lower') + >>> plt.title('Linear') + >>> plt.subplot(224) + >>> plt.imshow(grid_z2.T, extent=(0,1,0,1), origin='lower') + >>> plt.title('Cubic') + >>> plt.gcf().set_size_inches(6, 6) + >>> plt.show() + + +Spline interpolation +==================== + Spline interpolation in 1-d: Procedural (interpolate.splXXX) ------------------------------------------------------------ @@ -220,8 +291,8 @@ LSQUnivarateSpline with non-uniform knots - >>> t = [np.pi/2-.1,np.pi/2-.1,3*np.pi/2-.1,3*np.pi/2+.1] - >>> s = interpolate.LSQUnivariateSpline(x,y,t) + >>> t = [np.pi/2-.1,np.pi/2+.1,3*np.pi/2-.1,3*np.pi/2+.1] + >>> s = interpolate.LSQUnivariateSpline(x,y,t,k=2) >>> ynew = s(xnew) >>> plt.figure() @@ -232,7 +303,6 @@ >>> plt.show() - Two-dimensional spline representation: Procedural (:func:`bisplrep`) -------------------------------------------------------------------- @@ -319,14 +389,14 @@ Using radial basis functions for smoothing/interpolation ---------------------------------------------------------- +======================================================== Radial basis functions can be used for smoothing/interpolating scattered data in n-dimensions, but should be used with caution for extrapolation outside of the observed data range. 1-d Example -^^^^^^^^^^^ +----------- This example compares the usage of the Rbf and UnivariateSpline classes from the scipy.interpolate module. @@ -366,7 +436,7 @@ .. :caption: Example of one-dimensional RBF interpolation. 2-d Example -^^^^^^^^^^^ +----------- This example shows how to interpolate scattered 2d data. From scipy-svn at scipy.org Tue Aug 31 17:54:55 2010 From: scipy-svn at scipy.org (scipy-svn at scipy.org) Date: Tue, 31 Aug 2010 16:54:55 -0500 (CDT) Subject: [Scipy-svn] r6652 - in trunk/scipy/spatial: . qhull qhull/src Message-ID: <20100831215455.D289539CC7C@scipy.org> Author: ptvirtan Date: 2010-08-31 16:54:55 -0500 (Tue, 31 Aug 2010) New Revision: 6652 Added: trunk/scipy/spatial/qhull/ trunk/scipy/spatial/qhull/Announce.txt trunk/scipy/spatial/qhull/COPYING.txt trunk/scipy/spatial/qhull/README.txt trunk/scipy/spatial/qhull/REGISTER.txt trunk/scipy/spatial/qhull/index.htm trunk/scipy/spatial/qhull/src/ trunk/scipy/spatial/qhull/src/Changes.txt trunk/scipy/spatial/qhull/src/geom.c trunk/scipy/spatial/qhull/src/geom.h trunk/scipy/spatial/qhull/src/geom2.c trunk/scipy/spatial/qhull/src/global.c trunk/scipy/spatial/qhull/src/io.c trunk/scipy/spatial/qhull/src/io.h trunk/scipy/spatial/qhull/src/mem.c trunk/scipy/spatial/qhull/src/mem.h trunk/scipy/spatial/qhull/src/merge.c trunk/scipy/spatial/qhull/src/merge.h trunk/scipy/spatial/qhull/src/poly.c trunk/scipy/spatial/qhull/src/poly.h trunk/scipy/spatial/qhull/src/poly2.c trunk/scipy/spatial/qhull/src/qconvex.c trunk/scipy/spatial/qhull/src/qdelaun.c trunk/scipy/spatial/qhull/src/qhalf.c trunk/scipy/spatial/qhull/src/qhull.c trunk/scipy/spatial/qhull/src/qhull.h trunk/scipy/spatial/qhull/src/qhull_a.h trunk/scipy/spatial/qhull/src/qhull_interface.cpp trunk/scipy/spatial/qhull/src/qset.c trunk/scipy/spatial/qhull/src/qset.h trunk/scipy/spatial/qhull/src/qvoronoi.c trunk/scipy/spatial/qhull/src/rbox.c trunk/scipy/spatial/qhull/src/stat.c trunk/scipy/spatial/qhull/src/stat.h trunk/scipy/spatial/qhull/src/unix.c trunk/scipy/spatial/qhull/src/user.c trunk/scipy/spatial/qhull/src/user.h trunk/scipy/spatial/qhull/src/user_eg.c trunk/scipy/spatial/qhull/src/user_eg2.c Log: spatial: Import qhull 2003.1 source code Added: trunk/scipy/spatial/qhull/Announce.txt =================================================================== --- trunk/scipy/spatial/qhull/Announce.txt (rev 0) +++ trunk/scipy/spatial/qhull/Announce.txt 2010-08-31 21:54:55 UTC (rev 6652) @@ -0,0 +1,50 @@ + + Qhull 2003.1 2003/12/30 + + http://www.qhull.org + http://savannah.nongnu.org/projects/qhull/ + http://www6.uniovi.es/ftp/pub/mirrors/geom.umn.edu/software/ghindex.html + http://www.geomview.org + http://www.geom.uiuc.edu + +Qhull computes convex hulls, Delaunay triangulations, Voronoi diagrams, +furthest-site Voronoi diagrams, and halfspace intersections about a point. +It runs in 2-d, 3-d, 4-d, or higher. It implements the Quickhull algorithm +for computing convex hulls. Qhull handles round-off errors from floating +point arithmetic. It can approximate a convex hull. + +The program includes options for hull volume, facet area, partial hulls, +input transformations, randomization, tracing, multiple output formats, and +execution statistics. The program can be called from within your application. +You can view the results in 2-d, 3-d and 4-d with Geomview. + +To download Qhull: + http://www.qhull.org/download + http://savannah.nongnu.org/files/?group=qhull + +Download qhull-96.ps for: + + Barber, C. B., D.P. Dobkin, and H.T. Huhdanpaa, "The + Quickhull Algorithm for Convex Hulls," ACM Trans. on + Mathematical Software, 22(4):469-483, Dec. 1996. + http://www.acm.org/pubs/citations/journals/toms/1996-22-4/p469-barber/ + http://citeseer.nj.nec.com/83502.html + +Abstract: + +The convex hull of a set of points is the smallest convex set that contains +the points. This article presents a practical convex hull algorithm that +combines the two-dimensional Quickhull Algorithm with the general dimension +Beneath-Beyond Algorithm. It is similar to the randomized, incremental +algorithms for convex hull and Delaunay triangulation. We provide empirical +evidence that the algorithm runs faster when the input contains non-extreme +points, and that it uses less memory. + +Computational geometry algorithms have traditionally assumed that input sets +are well behaved. When an algorithm is implemented with floating point +arithmetic, this assumption can lead to serious errors. We briefly describe +a solution to this problem when computing the convex hull in two, three, or +four dimensions. The output is a set of "thick" facets that contain all +possible exact convex hulls of the input. A variation is effective in five +or more dimensions. + Added: trunk/scipy/spatial/qhull/COPYING.txt =================================================================== --- trunk/scipy/spatial/qhull/COPYING.txt (rev 0) +++ trunk/scipy/spatial/qhull/COPYING.txt 2010-08-31 21:54:55 UTC (rev 6652) @@ -0,0 +1,34 @@ + Qhull, Copyright (c) 1993-2003 + + The National Science and Technology Research Center for + Computation and Visualization of Geometric Structures + (The Geometry Center) + University of Minnesota + + email: qhull at qhull.org + +This software includes Qhull from The Geometry Center. Qhull is +copyrighted as noted above. Qhull is free software and may be obtained +via http from www.qhull.org. It may be freely copied, modified, +and redistributed under the following conditions: + +1. All copyright notices must remain intact in all files. + +2. A copy of this text file must be distributed along with any copies + of Qhull that you redistribute; this includes copies that you have + modified, or copies of programs or other software products that + include Qhull. + +3. If you modify Qhull, you must include a notice giving the + name of the person performing the modification, the date of + modification, and the reason for such modification. + +4. When distributing modified versions of Qhull, or other software + products that include Qhull, you must provide notice that the original + source code may be obtained as noted above. + +5. There is no warranty or other guarantee of fitness for Qhull, it is + provided solely "as is". Bug reports or fixes may be sent to + qhull_bug at qhull.org; the authors may or may not act on them as + they desire. + Added: trunk/scipy/spatial/qhull/README.txt =================================================================== --- trunk/scipy/spatial/qhull/README.txt (rev 0) +++ trunk/scipy/spatial/qhull/README.txt 2010-08-31 21:54:55 UTC (rev 6652) @@ -0,0 +1,328 @@ +Name + + qhull, rbox 2003.1 2003/12/30 + +Convex hull, Delaunay triangulation, Voronoi diagrams, Halfspace intersection + + Documentation: + html/index.htm + + Available from: + + + + Version 1 (simplicial only): + + + + News and a paper: + + + +Purpose + + Qhull is a general dimension convex hull program that reads a set + of points from stdin, and outputs the smallest convex set that contains + the points to stdout. It also generates Delaunay triangulations, Voronoi + diagrams, furthest-site Voronoi diagrams, and halfspace intersections + about a point. + + Rbox is a useful tool in generating input for Qhull; it generates + hypercubes, diamonds, cones, circles, simplices, spirals, + lattices, and random points. + + Qhull produces graphical output for Geomview. This helps with + understanding the output. + + +Environment requirements + + Qhull and rbox should run on all 32-bit and 64-bit computers. Use + an ANSI C or C++ compiler to compile the program. The software is + self-contained. + + Qhull is copyrighted software. Please read COPYING.txt and REGISTER.txt + before using or distributing Qhull. + +To cite Qhull, please use + + Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull + algorithm for convex hulls," ACM Trans. on Mathematical Software, + 22(4):469-483, Dec 1996, http://www.qhull.org. + +To contribute to Qhull + + Qhull is on Savannah at http://savannah.nongnu.org/projects/qhull/ + +Qhull on Windows 95, 98, ME, NT, 2000, XP + + The zip file contains rbox.exe, qhull.exe, qconvex.exe, qdelaunay.exe, + qhalf.exe, qvoronoi.exe, documentation files, and source files. + + To install Qhull: + - Unzip the files into a directory. You may use WinZip32 + - Click on QHULL-GO + + - In Windows 95, the DOS window needs improvement. + - Increase the size of the screen font to 8x12. + - If the text is too dim, fix the screen colors with shareware (e.g., crt.exe) + - If you use qhull a lot, consider using the Cygwin Unix shell (www.cygwin.com), + + To learn about Qhull: + - Execute 'qconvex' for a synopsis and examples. + - Execute 'rbox 10 | qconvex' to compute the convex hull of 10 random points. + - Execute 'rbox 10 | qconvex i TO file' to write results to 'file'. + - If an error occurs, Windows 95 sends the error to stdout instead of stderr + - use 'TO xxx' to send normal output to xxx and error output to stdout + - Browse the documentation: qhull\html\index.htm + +Compiling with cygwin on Windows NT, 2000, XP + - install cygwin [www.cygwin.com] with gcc, make, ar, and ln + - cd qhull/src + - make -f Makefile.txt + +Qhull on Unix (Debian) + + The gzip file, qhull.tar.gz, contains documentation and source files for + qhull and rbox. It should compile on all Unix systems, including Debian. + You may also use the source instructions below. + + To unpack the gzip file + - tar zxf qhull.tar.gz + - cd qhull + + Compile with the configure Makefile [R. Laboissiere]: + - ./configure + - make + +Compiling the source distribution + + The gzip file, qhull-src.tgz, contains documentation and source files for + qhull and rbox. + + To unpack the gzip file + - tar zxf qhull-src.tgz + - cd qhull + + Compiling with Makefile (i.e., Makefile.txt) + - cd src + - in Makefile, check the CC, CCOPTS1, PRINTMAN, and PRINTC defines + - the defaults are gcc and enscript + - CCOPTS1 should include the ANSI flag. It defines __STDC__ + - in user.h, check the definitions of qh_SECticks and qh_CPUclock. + - use '#define qh_CLOCKtype 2' for timing runs longer than 1 hour + - type: make + - this builds: qhull qconvex qdelaunay qhalf qvoronoi rbox libqhull.a + - type: make doc + - this prints the man page + - See also qhull/html/index.htm + - if your compiler reports many errors, it is probably not a ANSI C compiler + - you will need to set the -ansi switch or find another compiler + - if your compiler warns about missing prototypes for fprintf() etc. + - this is ok, your compiler should have these in stdio.h + - if your compiler warns about missing prototypes for memset() etc. + - include memory.h in qhull_a.h + - if your compiler is gcc-2.95.1, you need to set flag -fno-strict-aliasing. + - This flag is set by default for other versions [Karas, Krishnaswami] + - if your compiler reports "global.c: storage size of 'qh_qh' isn't known" + - delete the initializer "={0}" in global.c, stat.c and mem.c + - if your compiler warns about "stat.c: improper initializer" + - this is ok, the initializer is not used + - if you have trouble building libqhull.a with 'ar' + - try 'make -f Makefile.txt qhullx' + - if the code compiles, the qhull test case will automatically execute + - if an error occurs, there's an incompatibility between machines + - For gcc-2.95.1, you need to set flag -fno-strict-aliasing. + It is set by default for other versions of gcc [Karas, Krishnaswami] + - If you can, try a different compiler + - You can turn off the Qhull memory manager with qh_NOmem in mem.h + - You can turn off compiler optimization (-O2 in Makefile) + - If you find the source of the problem, please let us know + - if you have Geomview (www.geomview.org) + - try 'rbox 100 | qconvex G >a' and load 'a' into Geomview + - run 'q_eg' for Geomview examples of Qhull output (see qh-eg.htm) + - to install the programs and their man pages: + - define MANDIR and BINDIR + - type 'make install' + +Compiling on Windows 95, 98, NT, 2000, XP + + Qhull compiles as a console application in Visual C++ 5.0 at warning + level 3. + + Visual C++ quickstart for qhull.exe only: + - create a "Win32 console application" called "qhull" + - add the following files: + geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhull.c + qset.c stat.c unix.c user.c + - create a "Win32 console application" called "rbox" + - add rbox.c + + Visual C++ quickstart for qhull library, qhull.exe, qconvex.exe, etc. + - To simplify setting up lots of projects, + - create a temporary "Win32 console application" called "source" + - add all .c files from .../src/... + - In Tools::Options::Tab + Set tab size to 8 and indent size to 2 + + - create a "Win32 console application" called "rbox" + - move rbox.c from "qhull source" + - for Project:Settings..., Link + you only need the default libraries + - build the project + + - create a "Win32 static library" called "library" + - move these files from "qhull source" + geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhull.c + qset.c stat.c user.c + - set the library file (use the same for debug and release) + - build the project + + - create a "Win32 console application" called "qhull" + - Move unix.c from "qhull source" + - Add the library file created by "library" + - Qhull does not use other libraries + + - create a "Win32 console application" called "qconvex" + - Move qconvex.c from "qhull source" + - Copy the library file from "qhull" + + - do the same for qdelaun.c, qhalf, qvoronoi.c, user_eg.c, user_eg2.c + - delete "qhull sources" since it is no longer needed + - use Project:Settings to make any changes + - use batch build to rebuild everything + + Qhull compiles with Borland C++ 5.0 bcc32. A Makefile is included. + Execute 'make -f Mborland'. If you use the Borland IDE, set the ANSI + option in Options:Project:Compiler:Source:Language-compliance. + + Qhull compiles with Borland C++ 4.02 for Win32 and DOS Power Pack. + Use 'make -f Mborland -D_DPMI'. Qhull 1.0 compiles with Borland + C++ 4.02. For rbox 1.0, use "bcc32 -WX -w- -O2-e -erbox -lc rbox.c". + Use the same options for Qhull 1.0. [D. Zwick] + + Qhull compiles with Metrowerks C++ 1.7 with the ANSI option. + + If you turn on full warnings, the compiler will report a number of + unused variables, variables set but not used, and dead code. These are + intentional. For example, variables may be initialized (unnecessarily) + to prevent warnings about possible use of uninitialized variables. + +Compiling on the Power Macintosh + + Qhull compiles on the Power Macintosh with Metrowerk's C compiler. + It uses the SIOUX interface to read point coordinates and return output. + There is no graphical output. For project files, see 'Compiling for + Windows 95'. Instead of using SIOUX, Qhull may be embedded within an + application. + + Version 1 is available for Macintosh computers by download of qhull.sit.hqx + It reads point coordinates from a standard file and returns output + to a standard file. There is no graphical output. + + +Compiling on other machines + + Some users have reported problems with compiling Qhull under Irix 5.1. It + compiles under other versions of Irix. + + If you have troubles with the memory manager, you can turn it off by + defining qh_NOmem in mem.h. + + You may compile Qhull with a C++ compiler. + + +Distributed files + + README.txt // instructions for installing Qhull + REGISTER.txt // Qhull registration + COPYING.txt // copyright notice + QHULL-GO.pif // Windows icon for qhull-go.bat + Announce.txt // announcement + Changes.txt // change history for Qhull and rbox + File_id.diz // package descriptor + index.htm // Home page + html/qh-faq.htm // Frequently asked questions + html/qh-get.htm // Download page + html/index.htm // Manual + src/Makefile.txt // Makefile for Unix or cygwin 'make' + src/Mborland // Makefile for Borland C++/Win32 + src/Make-config.sh // Create Debian configure and automake + +src/ + rbox consists of: + rbox.exe // Win32 executable (.zip only) + rbox.htm // html manual + rbox.man // Unix man page + rbox.txt + rbox.c // source program + + qhull consists of: + qhull.exe // Win32 executables (.zip only) + qconvex.exe + qdelaunay.exe + qhalf.exe + qvoronoi.exe + qhull-go.bat // DOS window + qconvex.htm // html manuals + qdelaun.htm + qdelau_f.htm + qhalf.htm + qvoronoi.htm + qvoron_f.htm + qh-eg.htm + qh-impre.htm + qh-in.htm + index.htm + qh-opt*.htm + qh-quick.htm + qh--4d.gif,etc. // images for manual + qhull.man // Unix man page + qhull.txt + q_eg // shell script for Geomview examples + q_egtest // shell script for Geomview test examples + q_test // shell script to test qhull + + top-level source files: + src/index.htm // index to source files + qh-...htm // specific files + user.h // header file of user definable constants + qhull.h // header file for qhull + unix.c // Unix front end to qhull + qhull.c // Quickhull algorithm with partitioning + user.c // user re-definable functions + user_eg.c // example of incorporating qhull into a user program + user_eg2.c // more complex example + qhull_interface.cpp // call Qhull from C++ + + other source files: + qhull_a.h // include file for *.c + geom.c // geometric routines + geom2.c + geom.h + global.c // global variables + io.c // input-output routines + io.h + mem.c // memory routines, this is stand-alone code + mem.h + merge.c // merging of non-convex facets + merge.h + poly.c // polyhedron routines + poly2.c + poly.h + qset.c // set routines, this only depends on mem.c + qset.h + stat.c // statistics + stat.h + +Authors: + + C. Bradford Barber Hannu Huhdanpaa + bradb at qhull.org hannu at qhull.org + + The Geometry Center + University of Minnesota + + Qhull 1.0 and 2.0 were developed under NSF grants NSF/DMS-8920161 + and NSF-CCR-91-15793 750-7504 at the Geometry Center and Harvard + University. If you find Qhull useful, please let us know. Added: trunk/scipy/spatial/qhull/REGISTER.txt =================================================================== --- trunk/scipy/spatial/qhull/REGISTER.txt (rev 0) +++ trunk/scipy/spatial/qhull/REGISTER.txt 2010-08-31 21:54:55 UTC (rev 6652) @@ -0,0 +1,37 @@ +Dear User of Geometry Center Software: + +We would like to find out how you are using our software. Think of +Geometry Center software as a new kind of shareware: you share your +science and successes with us, and we share our software and support +with you. + +If you use Geometry Center software, please send us a note telling +us what you are doing with it. + +We need to know: + + (1) What you are working on - an abstract of your work would be + fine. + + (2) What Geometry Center software you use. + + (3) How that software has helped you, for example, by increasing + your productivity or allowing you to do things you could not do + before. In particular, if you feel that Geometry Center + software has had a direct bearing on your work, please tell us + about this. + +We encourage you to cite the use of any Geometry Center software you +have used in your publications. + +To cite Qhull, please use + + Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull + algorithm for convex hulls," ACM Trans. on Mathematical Software, + 22(4):469-483, Dec 1996, http://www.qhull.org. + +Please send e-mail to + + qhull at qhull.org + +Thank you! Added: trunk/scipy/spatial/qhull/index.htm =================================================================== --- trunk/scipy/spatial/qhull/index.htm (rev 0) +++ trunk/scipy/spatial/qhull/index.htm 2010-08-31 21:54:55 UTC (rev 6652) @@ -0,0 +1,252 @@ + + + + +Qhull for Convex Hull, Delaunay Triangulation, Voronoi Diagram, and Halfspace Intersection about a Point + + + + +URL: http://www.qhull.org +
To: +News +• Download +• CiteSeer +• Images +• Manual +• FAQ +• Programs +• Options +

+ +
+ + +
+

Qhull

+ [CONE] +
+Qhull computes convex hulls, Delaunay triangulations, +halfspace intersections about a point, Voronoi diagrams, furthest-site Delaunay +triangulations, and furthest-site Voronoi diagrams. It runs in +2-d, 3-d, 4-d, and higher dimensions. It implements the Quickhull +algorithm for computing the convex hull. Qhull handles roundoff +errors from floating point arithmetic. It computes volumes, +surface areas, and approximations to the convex hull.

+ + +

Qhull does not support constrained Delaunay +triangulations, triangulation of non-convex surfaces, mesh +generation of non-convex objects, or medium-sized inputs in 9-D +and higher.

+
+ +
+
+ + + +
+ +

Introduction +

+ +

Qhull Documentation and Support +

+ +

Related URLs +

+ +

FAQs and Newsgroups +

+ +
+ +

The program includes options for input transformations, +randomization, tracing, multiple output formats, and execution +statistics. The program can be called from within your +application.

+ +

You can view the results in 2-d, 3-d and 4-d with Geomview. An alternative +is VTK.

+ +

For an article about Qhull, download from CiteSeer or www.acm.org: +

+ +
+

Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The + Quickhull algorithm for convex hulls," ACM Trans. on + Mathematical Software, 22(4):469-483, Dec 1996, http://www.qhull.org.

+
+ +

Abstract:

+ +
+

The convex hull of a set of points is the smallest convex + set that contains the points. This article presents a + practical convex hull algorithm that combines the + two-dimensional Quickhull Algorithm with the general + dimension Beneath-Beyond Algorithm. It is similar to the + randomized, incremental algorithms for convex hull and + Delaunay triangulation. We provide empirical evidence that + the algorithm runs faster when the input contains non-extreme + points, and that it uses less memory.

+

Computational geometry algorithms have traditionally + assumed that input sets are well behaved. When an algorithm + is implemented with floating point arithmetic, this + assumption can lead to serious errors. We briefly describe a + solution to this problem when computing the convex hull in + two, three, or four dimensions. The output is a set of + "thick" facets that contain all possible exact convex hulls + of the input. A variation is effective in five or more + dimensions.

+
+ +
+ +

Up: Past Software +Projects of the Geometry Center
+URL: http://www.qhull.org +
To: +News +• Download +• CiteSeer +• Images +• Manual +• FAQ +• Programs +• Options +

+ +
+ +

[HOME] The Geometry Center Home Page

+ +

Comments to: qhull at qhull.org +
+Created: May 17 1995 --- + + Added: trunk/scipy/spatial/qhull/src/Changes.txt =================================================================== --- trunk/scipy/spatial/qhull/src/Changes.txt (rev 0) +++ trunk/scipy/spatial/qhull/src/Changes.txt 2010-08-31 21:54:55 UTC (rev 6652) @@ -0,0 +1,1071 @@ + +.............This file lists all changes to qhull and rbox..................... + + - Updated Qhull citation with page numbers. + - Project: constructing Voronoi diagram + - Project: computing Voronoi volumes + - identity function may drop points. The following lens distribution drops 52 of 102 points of its points + rbox 100 L1e5 | tee r | qconvex FV n | qhalf Fp | cat - r | /bin/sort -n > x + - offsetted points will add intersection points + rbox 1000 s O2 t | tee r | qconvex FV n | qhalf Fp | cat - r | /bin/sort -n | tail + +qhull 2003.1 2003/12/30 + +New Features: + - Add Maple output ('FM') for 2-d and 3-d convex hulls [T. Abraham] + +Bug Fixes and Code Changes: + - Fixed qh_findbest() for upperdelaunay facets w/o better, lower neighbors + For library users and some qhull users [A. Cutti, E. Milloti, K. Sun] + - Preserved qhmem.ferr in qh_memfreeshort() for library users + - Removed 'static' from qh_compare... for io.h and merge.h [V. Brumberg] + +Documentation: + - Add warning to findDelaunay() and qh_in.htm about tricoplanar facets + - Noted Edelsbrunner's Geometry & Topology for Mesh Generation [qh-impre.htm] + - Noted Gartner's Miniball algorithm [qh_impre.htm] + - Noted Veron and Leon's shape preserving simplification [qh_impre.htm] + +qhull 2003.1 2003/12/19 + +Bug Fixes: + - Reversed coordinate order for qh.ATinfinity in qh_projectinput [V. Brumberg] + This effects: + Qhull library 'd' or 'v' users with 'Qz' and unequal coordinate ranges. + qdelaunay/qvoronoi users with 'Qbk:0Bk:0', 'Qz', and unequal coordinate ranges + +Changes to code: + - Replaced qh_VERSION with qh_version in global.c [B. Pearlmutter] + The previous techniques were either clumsy or caused compiler errors + - Removed unused variables from qh_findbest and qh_findbestnew [B. Pearlmutter] + - Note that qh.TESTpoints was added in 2002.1 for tsearch implementation + +Changes to distribution: + - Added Unix distribution including Debian files [R. Laboissiere] + The previous Unix distribution is now the source distribution + - Added rpm distribution [L. Mazet] + - Investigated generation of Win32 dll. Need to define a C++ interface. + +Changes to documentation: + - Moved Qhull to www.qhull.org (geom.umn.edu is not available) + - The Geometry Center is archived at http://www.geom.uiuc.edu + - Reviewed introduction to each program + Triangulated output ('Qt') is more accurate than joggled input ('QJ') + qdelaunay is 'qhull d Qbb' [C. Ulbrich] + qvoronoi is 'qhull v Qbb' + Added example of non-simplicial intersection to halfspace intersections + - Added warning about using the Qhull library. + - Added qhull timings to When to use Qhull [C. Ulbrich] + - Reorganized the home page index and the manual index + - Moved qh-home.htm to index.htm + +Changes to examples + - Fixed options for eg/eg.t23.voronoi.imprecise [B. Pearlmutter] + + +qhull 2002.1 2002/8/20 + +Changes to distribution: + - Set up savannah.nongnu.org/projects/qhull/ [R. Laboissiere] + - Set up www.thesa.com as a backup + - Added qh-get.htm, a local copy of the download page + - Added Visual C++ interface to Qhull, qhull_interface.cpp [K. Erleben] + - Use HTTP instead of FTP for downloading Qhull + - Renamed qhull-1.0.sit.hqx + +Bug fixes: + - Fixed sign of coefficients for cdd halfspaces ('FD','Fd') [T. Abraham] + +Changes to code: + - Replace qh_version with qh_VERSION in qhull.h. + Allows shared libraries and single point of definition + - Added qh.TESTpoints for future implementation of tsearch + +Changes to build + - Makefile.txt works under cygwin + - Added Make-config.sh to create a Debian build [R. Laboissiere] + - Added .exe to Makefile.txt#clean. + - In README, use -fno-strict-aliasing with gcc-2.95.1 [Karas, Krishnaswami] + - Fixed chmod in Makefile.txt [B. Karas] + +Documentation updates + - Documented input options for each program [A. Montesinos] + - FAQ: "How to get the radii of the empty spheres for Voronoi vertices" + +URL updates: + - Changed official URL from locate/qhull to software/qhull + - Changed URLs from relative to absolute in qh-home.htm and qh-get.htm + - Added URL for Newsgroup: comp.soft-sys.matlab + - Added URL for GNU Octave + - Added URLs for Google and Google Groups + - Replaced qhull_mail.html and qhull_bug.html with mailto links. + - Removed URL for Computational Geometry Tribune + - Changed URL for locate/cglist to software/cglist + - Used site relative links for qh-home.htm + +qhull 3.1 2001/10/04 + +New features + - Added option 'Qt' to triangulate non-simplicial facets + - Added option 'TI file' to input data from file + - Added option 'Q10' to prevent special processing for narrow distributions + e.g., RBOX 1000 L100000 s G1e-6 t1001803691 | QHULL Tv Q10 + - Tried to compute Voronoi volumes ('Pv'). Requires dual face graph--not easy + See Clarkson's hull program for code. + +Changes to options + - Added numtricoplanars to 'Fs'. Number of good, triangulated facets for 'Qt' + - Added Zdelvertextot to 'Fs'. If non-zero and Delaunay, input is degenerate + - Qhull command ('FQ') may be repeated. + - If 'TPn' and 'TWn' defined, trace the addition of point 'n' + otherwise continue tracing (previously it stopped in 4-d) + - Removed 'Ft' from qdelaunay. Use 'Qt o' or 'qhull d QJ Qt' instead. + For non-simplicial regions, 'Ft' does not satisify the Delaunay property. + - If 'Po' or 'TVn', qhull checks outer planes. Use 'Q5' to turn off. + - If 'T4', print facet lists and check polygon after adding each point + +Corrections to code + - rbox: allow 'c' and 'd' with 's r', meshes, etc. + - qh_findbest: redesigned as directed search. qh_findbesthorizon for coplanar + qh_findbest is faster for many distributions + - qh_findbestnew: redesigned to search horizon of coplanar best newfacets + needed for distributions with a sharp edge, + e.g., rbox 1000 s Z1 G1e-13 | qhull Tv + - qh_findbest/qh_findbestnew: search neighbors of better horizon facets + was needed for RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv + and RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv + - qh_findbest with noupper: could return an upperdelaunay facet if dist>qh.MINoutside. + - qh_findbestnew: allow facet->upperdelaunay if dist > qh.MINoutside + - qh_partitioncoplanar: call qh_partitionpoint if outside and perpendicular + for distributions with a sharp edge + - qh_partitionvisible: report precision error if all newfacets degenerate. + was needed for RBOX 1000 s W1e-13 t995138628 | QHULL d + - qh_createsimplex: clears qh.num_visible, may be non-zero with 'TRn QJ' + +Changes to prompts, warnings, and statistics + - For Delaunay & Voronoi, 's' reports deleted vertices due to facet merging. + They were incorrectly reported as nearly incident points. + - Warn if recompute centrum after constructing hull + - Simplified narrow hull warning and print all digits of cosine. + A narrow hull may lead to a point outside of the hull. + - Print total vertices deleted instead of ave. per iteration (Zdelvertextot) + - Improved tracing for qh_partitionpoint and qh_partitioncoplanar + - Added number of distance tests for checking outer planes (qh_check_maxout) + - Simplified "qhull precision error: Only n facets remain." + - Included 'TRn' in the causes of a premature exit + +Changes to documentation + - README.txt: Added quickstart instructions for Visual C++ + - rbox: Added example of edge of narrow lens, rbox 1000 L100000 s G1e-6 + - Added cross references between options 'o' and 'p'. + - qh-eg.html: added examples comparing 'Qt', 'QJ', and neither 'Qt' nor 'QJ' + eg.15a.surface, eg.15b.triangle, eg.17a.delaunay.2, etc. + - Reorganized and enhanced discussion of precision problems in qh_impre.htm + - Fixed spelling errors [K. Briggs] + - Fixed link errors, validated HTML, and spell checked [HomeSite] + - Removed unnecessary #TOP links + - Added source links to the qh-quick.htm's header and footer + - qh-geom.htm, qh-poly.htm: add links to Voronoi functions in io.c + - src/index.htm: Added how to search qhull.h for qhull options + - qvoronoi.htm/qdelaun.htm: 'Fc' and 'FN' includes deleted vertices + +Changes to URLs + - Added http://www.voronoi.com and http://www.magic-software.com + +Changes to code + - qh_qhull: if 'TVn' or 'TCn' do not call qh_check_maxout and qh_nearcoplanar + - reviewed time profile. Qhull is slower. Optimized qh_findbestnew() + - qh_addpoint: Added warning note about avoiding a local minimum + - qh_checkpolygon: report qh.facet_next error if NARROWhull & dist>MINoutside + - qh_findbest: renamed "newfacets" parameter to "isnewfacets" since it is boolT + - qh_findbest/qh_findbestnew: testhorizon even if !MERGING + Otherwise qhull c D6 | qhull Q0 Tv assigns coplanar points + - qh_resetlists: add qh_RESETvisible for qh_triangulate + - qh_findbest: search better facets first. Rewritten. + - qh_findbest: increased minminsearch, always check coplanar facets. + See: RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv + - qh_findbestnew: report precision error for deleted cones [rare event] + e.g.: RBOX 1000 s W1e-13 P0 t1001034076 | QHULL d Qbb Qc Tv + - qh_findbesthorizon: search horizon of qh.coplanarset. New. + - qh_findbestsharp: replaced with qh_sharpnewfacets followed by qh_findbestnew + - qh_partitionpoint, Delaunay sites can not be inside. Otherwise points may + be outside upperDelaunay facets yet not near-inside Delaunay facets + See: RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Tv + - qh_partitioncoplanar: call qh_findbest/qh_findbestnew with qh DELAUNAY + - qh_printlists: format long lines + - qh_printvertex: format long lines + - user.h: tightened qh_WARNnarrow and qh_MAXnarrow. Do not see problems + until they are -1.0. + - user.h: defined qh_DISToutside, qh_SEARCHdist, and qh_USEfindbestnew + - qh_checkfacet: in 3-d, allow #ridges > #vertices. Can get a vertex twice + in a ridge list, e.g, RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv + +Changes to FAQ + - Recommended use of triangulated output ('Qt') + +Changes to distribution + - Recompiled in Visual C++ 5.0 with optimization (as was version 2.6) + - q_test: Added bad cases for Qhull and tests for new features + +Changes to Qhull library + - Added qh_triangulate() to poly2.c. It triangulates the output. + - Added option 'Q11' to copy normals and recompute centrums for tricoplanar facets + 'FP' may not print the nearest vertex for coplanar points + Use option 'Q11' when adding points after qh_triangulate() + +qhull 3.0 2001/02/11 + +Changes to distribution + - added qconvex, qdelaunay, qhalf, and qvoronoi + - added qhull-interface.cpp on calling Qhull from C++ [K. Erleben] + - renamed to qhull3.0/. + - added eg/, html/, and src/ directories + +Changes to URLs + - MathLab6 qhull: convhulln, delaunayn, griddatan, tsearchn, vororoin [Z. You] + - Wolfram Research wrote a Mathematica interface for qdelaunay [Hinton] + - Geomview moved from www.geom.umn.edu to www.geomview.org [M. Phillips} + - added URLs for tcsh and cygwin to README.txt + +Changes to documentation + - reorganized table of contents and renamed qh-man.htm to index.htm + - wrote program documentation, dropped qh-opt.htm and qh-optv.htm + - added quick reference, qh-quick.htm + - reorganized qh-rbox.htm and renamed it to rbox.htm + - split up qh-c.htm for quick navigation + +Corrections to code + - fixed type of arg for error message in qh_initqhull_globals [N. Max] + - fixed incorrect initialization of qh MINdenom_1 for scalepoints + - fixed drop dim for 'H Qbk:0Bk:0'. Added qh.feasible_point to qh_projectinput + - qh_WARNnarrow is angle between facet normals. Negate for warning message. + - statistics for Wangle/etc. concerns facet normals. Reworded [E. Voth] + - fixed error message for 'FC v' + - report cospherical points if Delaunay and error in qh_scalelast() + +Changes to code + - turn on Pg if (QVn or QGn) and not (Qg or PG) + - turn on Qc if format option 'Fc', 'FP', or 'Gp' (removes warning) + - removed last good facet unless ONLYgood ('Qg'). + - added count of non-simplicial or merged facets to 'FS' + - added count of non-simplicial facets to 's' (OK if #vertices==dim) + - added Znonsimplicial and Znowsimplicial to 'Ts' + - allow Mathematica output of dual polytope for halfspace intersection + - added qh_checkflags to globals.c for multiple front ends + - qh_initqhull_globals sets qh.MERGING if qh.MERGEexact + - removed hashentryT. It is no longer used. + +Changes to prompts and warnings + - reorganized prompts + - reorganized synopsis for rbox.c + - print warning if 'Fc' or 'FP' with 'd QJ'. Coincident points are unlikely. + - ignore warning if options 'v i Pp'. qvoronoi users may need Delaunay tri. + - reworded warning if 'Pg' and 'QVn' is not a vertex. + - reworded warning for 'Qx Tv', qh_check_points() in poly2.c + - if 'Pp', turn off warning for 'Qbb' without 'd' or 'v' + - in qh_printsummary() of Voronoi and Delaunay, distinguish QVn, QGn, Pdn, PDn + +Changes to FAQ + - added FAQ item for nearly flat Delaunay triangles [Z. You] + - added FAQ item for area and volume [R. Konatham] + - added FAQ item for Voronoi diagram of a square [J. Yong] + - edited FAQ item on point location in Delaunay triangles [Z. You] + - added FAQ item on nearly flat Delaunay triangles [Dehghani] + - added FAQ item about halfspace intersection [V. Tyberghein] + - added FAQ item for missing ridges [M. Schmidt] + - added FAQ item about qh_call_qhull [R. Snyder] + - added FAQ item about memory statistics [Masi] + - added FAQ item on meshing non-convex objects + - added FAQ item on MATLAB and Mathematica interface + +qhull 2.6 1999/04/19 + - fixed memory overwrite (no effect) in qh_initstatistics() [K. Ford] + - added zdoc11 to qh-stat.h#ZZdef for !qh_KEEPstatistics [K. Ford] + - enhanced qh_initqhull_globals() test of qh_RANDOMint and qh_RANDOMmax + - added debugging option to always return qh_RANDOMmax from qh_rand() + - fixed option 'Qr', qh_initialvertices(), to allow a broken qh_rand() + fixed option 'Qr', qh_nextfurthest(), to allow narrow hulls + Option 'Qr' simulates the random incremental algorithm for convex hulls + - added note that qh.num_outside includes coplanar points for narrow hulls + - added FAQ items for triangles/ridges of 3-d Delaunay triangulation[P. Kumar] + - added FAQ item about on-line processing with the Qhull library [O. Skare] + - changed name of option 'Error-roundoff' to 'Distance-roundoff' + +qhull 2.6 1998/12/30 + - for the unbounded rays of the Voronoi diagram, use a large box [Schmidt] + e.g., 'rbox P4,4,4 P4,2,4 P2,4,4 P4,4,2 10 | qhull v Fv' fails for point 0 + while 'rbox P4,4,4 P4,2,4 P2,4,4 P4,4,2 10 c G5 | qhull v Fv' is OK. + - fixed qh_new_qhull() to use outfile/errfile instead of stdout/stderr [Ford] + - clarified COPYING.txt for use in other programs [Archer] + - improved qh_readpoints() error message for incorrect point count. + - added FAQ item for closest triangle to a point [Sminchisescu & Heijting] + - added FAQ item for is a point outside of a facet [Beardsley] + - added FAQ item for visiting facets of the Delaunay triangulation [Heijting] + - added link to Erickson's Computational Geometry Software + - added link to Sharman's HTML version of the comp.graphics.algorithms FAQ + - added link to Owen's Meshing Research Corner + - added note to 'd' about quadratic size of 'rbox 100 l | qhull d' [Kumar] + - added 'about a point' to mentions of halfspace intersection + - added request to qh-in.htm to compute largest empty circle [Hase] + - the DOS window in Windows NT is better than the DOS window in Windows 95 + - removed obsolete qh_findfacet() from qh-c.htm [Sminchisescu] + +qhull 2.6 1998/8/12 + new and modified features + - rbox: added option Mn,m,r to generate a rotated lattice or mesh + - rbox: report error if more than one of 'l', 'x', 'L', 's', or 'M' + + Qhull library changes + - added qh_new_qhull() to user.c for calling qhull() from a program [D. Zwick] + rewrote user_eg.c to use qh_new_qhull(). Added qh_QHpointer example. + - added qh_CLOCKtype 2 in user.h to call times() for CPU time [B. Hemkemeier] + - renamed set.c/set.h to avoid conflict with STL's set.h [G. van den Bergen] + can also use '#include ' for Qhull library + + fixed errors + - fixed qh_init_B() to call qh_initqhull_mem() once only [D. Zwick] + This only effects Qhull library users of qh_QHpointer. + - fixed qh_mergecycle_all() to check for redundant vertices [J. Nagle] + e.g., 'rbox M3,4 64 | qhull Qc' should report 8 vertices & 48 coplanars + - fixed gmcoord initialization in qh_setfacetplane() for qh.RANDOMdist + - turn off qh.RANDOMdist during qh_printfacetheader() + - fixed error messages for unknown option flags + + documentation changes + - added note to FAQ on the Voronoi diagram of cospherical points [H. Hase] + - added note to 'Qu' on furthest-site Delaunay triangulation via convex hull + - added note to 'QJ' about coplanar points on the convex hull of the input + - added note that 'o' and 'FN' list Voronoi regions in site id order [Arvind] + - added links to Fukuda's introduction to convex hulls, etc. [H. Hase] + - added .c and .h source files to web distribution and qh-c.htm [J. Sands] + - documented qh_ZEROdelaunay. Delaunay and Voronoi diagrams do not include + facets that are coplanar with the convex hull of the input sites. + + modified code + - replaced computed minnorm in qh_sethyperplane_det with distance test + - removed 'qh rand_seed' since random number generator is independent of qhull + - dropt 'qhull-PPC.sit.bin' from the distribution (out-of-date) [M. Harris] + +qhull 2.5 1998/5/4 + + fixed errors + - removed zero-area Delaunay triangles and furthest-site triangles [I. Beichl] + Zero-area triangles occur for points coplanar with the input's convex hull. + - replaced qh.MINnorm with computed minnorm in qh_sethyperplane_det [J. Nagle] + qh.MINnorm was incorrect for the convex hull of the "teapot" example. + Qhull runs 0-20% slower in 3-d and 4-d. + - allow 'Qg' with furthest-site Delaunay triangulation (may be faster) + - removed extra space in definition of FOREACHmerge_() for Alpha cc [R. LeRoy] + - fixed innerouter type in qh_printvdiagram2 [does not effect code, R. Adams] + + documentation changes + - to browse qh-c.htm, set MIME type of .c and .h files to text/html + - added example of 3-d Delaunay triangulation to q-faq.htm + - added Delaunay and Voronoi examples to qh-optv.htm + +qhull 2.5 1998/2/4 + - added option 'v Fi' for separating hyperplanes of bounded Voronoi regions + - added option 'v Fo' for separating hyperplanes of unbounded Voronoi regions + - option 'Pp' turns off the warning, "initial hull is narrow" + - fixed partial, 3-d Voronoi diagrams (i.e., 'v Fv QVn Tc') + - fixed missing statistics in qh_allstat* [T. Johnson] + - rearranged qh_printvdiagram. Use qh_eachvoronoi to iterate Voronoi ridges. + - added qh_check_points to qh-math.c + +qhull 2.5 1998/1/28 + - added option 'Fv' to print the Voronoi diagram + - added rbox option 'x' to generate random points in a simplex + - added rbox option 'y' to generate a simplex and random points + - added rbox option 'On' to offset the output + - add unpacking instructions to README.txt + - updated discussion of forced output, 'Po' + - sorted the options alphabetically + - removed __STDC__ check from qhull.h for VisualC++ + - moved qh_markvoronoi from qh_printvoronoi and cleared facet->seen flags + - added facet->seen2 flag for 'Fv' + +qhull 2.5 1998/1/16 + - fixed initialization of qh.last_low on restart of 'd QJ' + - renamed qh_JOGGLEmax to qh_JOGGLEmaxincrease + - updated URL for Fukuda's cdd program + +qhull 2.5 1998/1/12 + +New or modified features + - added option 'Fx' to print vertices by point id [G. Harris, T. McClendon] + in 2-d, the vertices are printed in counter-clockwise order + for Delaunay triangl., 'Fx' lists the extreme points of the input sites + - added option 'QJ' to randomly joggle input instead of merging facets + - added option 'TO file' to output results to a file. Needed for Windows95. + - added option 'TRn' to rerun Qhull n times. Use to collect joggle statistics + +Corrections + - fixed 2-d facet orientation for 'i' and 'o' outputs + - for Mathematica 2.2 ('m') changed %10.8g to %16.8f [A. Zhaxybayev] + - fixed incorrect warning for 'QV0 Qg' in qh_initbuild [B. Wythoff] + - fixed unaccessible statistic if !qh_KEEPstatistics for Wnewvertexmax + - fixed overestimate of qh ONEmerge for point sets outside of + first quadrant and far from the origin + - fixed overestimate of 'Qbb' for point sets far from the origin + - fixed potential overestimate of qh DISTround under 'Qbb' + - fixed 'p' printing coplanar points of unselected facets + - fixed 'Ft' printing centrums unnecessarily in 2-d + +Changes to documentation + - wrote internal design documentation (qh-c.htm) + - started frequently asked questions (qh-faq.htm) + - added a section on joggled input to qh-impre.htm + - added joggle example to qh-eg.htm (eg.15.joggle) + - changed q_eg to use 'QJ' instead of 'Q0' were appropriate + - added an example to each of the main options + - added examples to rbox.htm + - added examples to the synopsis + - added a reference to Mucke, et al ['96], Fast randomized point location ... + - added code for printing Delaunay triangles to qh-in.htm [A. Tsui] + - options 'Pdk' and 'PDk' do not drop on equality + +Improvements to the code + - reviewed warning messages for Qhull options in qh_initflags + - added warning to 's' if premature exit from 'TCn' or 'TVn' + - 's' prints max distance above/below only if qh.MERGING + - reduced maxoutside in qh_check_bestdist/qh_check_points for 'Rn' + - in post-merging, rebuild centrums of large facets that become small + - lowered cutoff for coplanar facets for ischeckmax/qh_findbest + - removed qh_check_maxout for 'Wn Q0' + - reset tracing after 'TPn' adds point in 4-d and higher + +Changes for the Qhull library + - changed qh_setdelaunay to call qh_scalelast if used with 'Qbb' or 'QJ' + Delaunay callers to qh_findbestfacet, qh_addpoint, or qh_findfacet_all + should always use qh_setdelaunay as in user_eg.c + - defined qh.outside_err to check points against a given epsilon [E. Voth] + - added header to user_eg.c to avoid its incorporation into qhull [C. Begnis] + - added qh_nearcoplanar() calls to user_eg.c + only needed if use 'QJ' + - expanded __STDC__ warning message in qhull.h [C. Begnis] + - renamed qh maxmaxcoord to qh MAXabs_coord + - replaced qh MAXlowcoord with qh MAXabs_coord + - random seed ('QR-n') is reset in qh_initqhull_globals after testing + - replaced 'FO' options "_max-coord/_min-coord" with "_max-width"/qh.MAXwidth + +Other changes to Qhull functions + - report error for !bestfacet in qh_findbest (it shouldn't happen) [H. Meuret] + - set newbest in qh_findbest only if bestfacet updated + - renamed facet parameter for qh_findbest + - added maxdist argument to qh_checkpoint + - moved 'FO' output after qh_partitionall + - separated qh_initbuild from qh_qhull + - reinitialize globals modified by qh_buildhull + - moved initialization of qh.GOODvertexp & qh.GOODpointp to qh_initbuild + - separated qh_nearcoplanar from qh_check_maxout + - separated qh_geomplanes from qh_printfacet2geom, etc. + - separated qh_freebuild from qh_freeqhull + - separated qh_outerinner from io.c to return outer and inner planes + - separated qh_distround and qh_detroundoff from qh_maxmin + + +qhull 2.4 97/4/2 + +New or modified features + - made 'C-0' and 'Qx' default options. Use 'Q0' to not handle roundoff errors + - removed point-at-infinity from Delaunay/Voronoi. + you no longer need to use 'Qu PDk' + - added 'Qz' to add a point-at-infinity to Delaunay and Voronoi constructions + - added published version of qhull article in ACM Trans Math Software + - ported qhull to Windows95 under Visual C++ and Borland C++ + - added 'Ft' for triangulation by adding the centrums of non-simplicial facets + - added 'Gt' to display 3-d Delaunay triangulations with a transparent hull + - changed definition of coplanar point in output to qh min_vertex (see 'Qc') + it was qh MAXcoplanar ('Un') [could make vertices non-coplanar] + - automatically set 'Qi' for options 'd Qc' and 'v Qc'. + - reworded summary ('s') for Delaunay/Voronoi/halfspace. + use 'Fs' and 'FS' for summary statistics. + - for summary 's' of Delaunay/Voronoi, display number of coplanars for facets + if none, display total number of coplanars (i.e., non-vertices) + - input comment is first non-numeric text (previously limited to header) + - added input warning if use 'Qbb' without 'd' or 'v' + - 'Q3' can not be followed with a numeric option + +Corrections + - fixed qh_partitioncoplanar() to not drop interior points if 'Qi' is used + - fixed 'FP d' to report distance in point set instead of paraboloid + - fixed qh_findbest() to search all coplanar facets for qh_check_maxout() + +Changes to documentation + - added example eg.17f.delaunay.3 to show a triangulation of cospherical sites + - split up qh-opt.htm into multiple pieces + - split off qh-in.htm for Qhull internals + - renamed .html files to .htm for Windows95 + - rewrote qh-optv.htm on Delaunay triangulation and Voronoi vertices + - added 'man' pages qhull.txt and rbox.txt. These list all the options + - removed 'txt' versions of html files + - added note to 'PDk' about avoiding a 'd' option immediately after a float + - under option 'd', display the triangulation with 'GrD3', not 'GnrD3' + +Changes to the Qhull library + - added 'format' argument to qh_printfacetNvertex_nonsimplicial() in io.c + - removed C++ type errors [J. Stern, S. Marino] + - created SETelemt, SETfirstt, etc. for specifying data types. + - use SETelem,etc. for assignments. + - changed setT.maxsize to 'int' to prevent type conversion warnings + - changed FOREACH.. to a comma expression for better code and less warning + - changed qh.vertex_visit and .visit_id to unsigned int to prevent warnings + - changed clock() to qh_CPUclock (user.h) + - qh_init_B() and qh_readpoints() do not set qh.ATinfinity for Delaunay tri. + - qh_setvoronoi_all() sets upper Delaunay facets if qh.UPPERdelaunay is set + - qh_nearvertex() returns distance in dim-1 for qh.DELAUNAY + - removed MSDOS path from qhull_command. Spaces in Win95 tripped qh_setflags + - removed memory.h from qhull_a.h. memset,etc. should be in strings.h + - split qh_prompt into pieces for Visual C++ + - added note to qh_addpoint that coordinates can not be deallocated + - added Baker '89 to constrained Delaunay diagrams under Enhancements + please let me know if you try this + - added request for unbounded Voronoi rays to Enhancements + please let me know if you try this + +qhull V2.3 96/6/5 + - fixed total area of Delaunay triangulation. [A. Enge] + It should ignore facets on the upper-envelope. + - if 'd Qu FA', the total area is summed over the upper-Delaunay triangles + - fixed sign of area for Delaunay triangulations. + - fixed cdd input format for Delaunay triangulation. [A. Enge] + - for cdd input, allow feasible point for halfspaces. + - warning if cdd output format for centrums, halfspace intersections, or OFF. + - print '0' for area ('Fa') if area is not computed for a facet + - option 'QR-n' sets random number seed to n without rotating input + - fixed qh_findbest() to retest coplanar and flipped facets after a restart + - for 'd Qu Ts' collects angle statistics for upper Delaunay facets + + Changes to the Qhull library + - expanded user_eg.c for incremental constructions and Delaunay triangulation + - added discussion of incremental construction to qh_man.html#library + - WARNING: The default value of qh ATinfinity was changed from True to False. + A new flag, qh UPPERdelaunay, was defined for 'Qu'. + Please set qh ATinfinity if you explicitly add the point "at-infinity" + Please set qh ATinfinity if you explicitly call qh_projectinput. + Please set qh UPPERdelaunay if you explicitly cleared qh ATinfinity. + Other users do not need to change their code. + Now you can build a Delaunay triangulation without creating a point + "at-infinity". This removes a potential, hard-to-understand error. + qh_readpoints sets qh ATinfinity for options 'd' or 'v' without 'Qu'. + qh_initB sets qh ATinfinity for qh PROJECTdelaunay w/o qh UPPERdelaunay. + qh_projectinput adds a point "at-infinity" only if qh ATinfinity is set. + - added qh_setdelaunay to geom2.c to project points to paraboloid + - added qh_findbestfacet() to poly2.c to replace qh_findfacet() + - removed procedure qh_findfacet(). It does not always work. + - removed NULL option for facet in qh_addpoint(). It does not always work. + - added noupper parameter to qh_findbest. + - added search of upperdelaunay facets to qh_findbest() + - allowed qh_findbest() to start with a flipped or upperdelaunay facet + - removed qh_nonupper() -- it is no longer needed + - allow space at end of options + - fixed qh_projectinput for furthest-site Delaunay (qh PROJECTdelaunay 'd Qu') + - added voids to procedure declarations with empty parameter lists + +qhull V2.3 96/3/25 + - fixed missing qh_check_maxout when coplanar points and no merged facets. + - fixed qh_freeqhull/allmem (e.g., if qh_NOmem) [only custom code] [E. Voth] + - fixed qh_freeqhull to free qh interior_point [E. Voth] + - fixed main() to free all of memory if qh_NOmem. Include "mem.h" [E. Voth] + - reset f.newcycle link in qh_mergecycle_all [E. Voth] + - fixed false error if 'Tc', coplanar points, and a narrow hull + - turn off 'Rn' when computing statistics, checking code, or tracing code + - removed ={0} from global.c and stat.c to reduce compiler warnings + - changed Makefile dependences to $(HFILES) for all but unix.o, set.o, mem.o + - pulled out qh_printpointid and reordered qh_pointid [E. Voth] + - removed some compiler warnings + - moved 'FO' print of options to just before qh_buildhull + - changed 'FO' to list difference from -1 for _narrow-hull + +qhull V2.2 96/2/15 + - detect narrow initial hulls (cosine of min angle < qh_MAXnarrow in user.h). + Write warning if cosine < qh_WARNnarrow in user.h. If narrow (qh NARROWhull), + partition coplanar points as outside points and delay coplanar test to end. + Needed for RBOX 1000 L100000 s G1e-6 t995127886 | QHULL Tv + See 'limitations' in qh-impre.html for further discussion. + - corrected some confusions between 'FV' and 'Fv' in qh-opt.html + - fixed initialization error for small Voronoi diagrams (e.g., [0,0], [1,0], [0,1]) [J. Velez] + - fixed bad return from qh_mindiff in geom2.c + - for initial hull, first process facet with furthest outside point (qh_furthestnext) + - added facet->notfurthest flag for recomputing furthest point + - added check for __STDC__ (needs ANSI C) [E. Voth] + - reduced warning messages from [E. Voth]. e[1] in setT still reports a warning. + - added a cube to the discussion of option 'v' (Voronoi) in qh-opt.html [J. Velez] + - added notes about adjacent vertices to "Calling Qhull" in qh-man.html [R. Lewis & J. Velez] + - added note about 'lines closer' when viewing 3-d Delaunay triangulations [P. Kallberg] + - added option 'Q9' to always process furthest of furthest outside points. + - removed option 'Pp' from q_eg and qh-eg.html. + +qhull V2.2 95/12/28 + - added option 'Qbb' to scale the last coordinate to [0,m] (max prev coord). + This reduces roundoff errors for Delaunay triangulations with integer coordinates. + - changed option 'Qu d' to print out the furthest-site Delaunay triangulation + Use options 'Qu d PD2' to compute the normal 2-d Delaunay triangulation without + the point at infinity. + - added notes to the documentation of option 'd' + - added notes to limitations of how Qhull handles imprecision + - added warning if options 'FP', 'Fc', or 'Gp' without option 'Qc' or 'Qi' + - added note to options 'PDk:n' and 'Pdk:n' that closest facet is returned if none match + - added check that 'Qbk' and 'QBk' does not invert paraboloid for 'd' + - added notes that qh_findfacet and qh_addpoint require lifted points for Delaunay triangulations + - fixed 'rbox s 5000 W1e-13 D2 | qhull d Qcu C-0 Qbb' + - fixed option 'QbB' (qh SCALEpoints was not set) + - fixed minor confusion between 'Gc' (print centrums) and 'Gp' (print points) + - rewrote qh_findbestnew for upper convex hull, Delaunay facets + - changed option name for 'Gp' from 'Gcoplanar' to 'Gpoints' + - changed "nearest" facet for 'Pdk' to threshold - normal + - reworked qh GOODclosest for 'Qg' + - added note that 'Qg' does not always work + - recorded option 'C-0' as "_zero-merge" in option 'FO' + - refined qh DISTround in qh_maxmin/geom2.c for Delaunay triangulations + +qhull V2.2 95/12/4 + - Version 2.2 fixes an important bug in computing Delaunay triangulations + and convex hulls with edges sharper than ninety degrees. The problem + occurs when processing a point at a sharp edge. A directed search can + not be used for partitioning because one side may hide facets from the + other side. The new lens-shaped distribution for rbox demonstrates the + problem. For example, 'rbox 100 L3 G0.5 s | qhull Tv' fails for Version 2.1. + O. Schramm found the bug when computing the Delaunay triangulation of points + near an outside edge. + + I rewrote qh_findbest and related functions. Qh_findbest + uses an exhaustive test for sharp edges (qh_findbest_sharp). + Qh_findbest avoids the upper convex hull of Delaunay triangulations. + + Options 'd' and 'v' no longer assign coplanar points to the upper convex hull. + + Qh_check_maxout tests near-inside points. It ignores fully inside points. + When done, it removes near-inside points from the coplanar sets. + + If you use qh_addpoint or qh_findbest, please review the function headers. + They do not work for lens-shaped hulls for arbitrary facets. They do work for + Delaunay triangulations. + + Changes to options for V2.2 + - added 'Qu' for computing the furthest-site Delaunay triangulation (upper hull) + and furthest-site Voronoi vertices. + - added 'FP' to print nearest vertex for coplanar points + - added coplanar count to 'Fs' and 's' + - added number of similar points to summary for Delaunay/Voronoi + - Option 'Qc' is no longer necessary when merging. + - 'o' format for Voronoi vertices ('v') generates "0" lines for similar points + - 'QRn' for Delaunay ('d' or 'v') now rotates about the Z axis (see qh_init_B). + Otherwise Qhull does not identify the upper hull + - removed option 'Qa' for "all points outside". In V2.1 it was automatically + set for 'd'. Even though it was a bad idea, it revealed the above bug. + - for option list ('FO'), added version, values for one-merge, maxpos, maxneg, + and near-inside, and flags for zero-centrum + - optimized 'C-0' and 'Qx'. These options ("zero-centrum") test vertices + instead of centrums for adjacent simplicial facets. + - if 'Tv', report number of points that are not verified due to qh_findbest + - Option 'Q8' ignores near-inside points. + + rbox 95/12/3 + - added lens distribution ('Ln') It may be used with 's', 'r', 'Wn', and 'Gn' + - removed default point count except for the test case, 'Dn' + - divided main() of rbox.c into sections + + Documentation changes for V2.2 + - added examples for lens distribution and furthest-site Delaunay triangulation + and renumbered the examples for q_eg + - described facet orientation in 'data structure' section [P. Soikkonen] + - added notes to qh-man.html/"What to do if something goes wrong" + - added note about using 'Tv' to verify the results [O. Schramm] + - expanded definition of f_r in Performance section [S. Grundmann] + - noted that Geomview display of a Voronoi diagram adds extra edges + for unbounded Voronoi cells + - rewrote error "convexity constraints may be too strong" [D. Newland] + - added limitations section to "Imprecision in Qhull" + - added note about zero-area facets to 'Imprecise convex hulls' in qh-impre.html + - added note to 'Qi' that it does not retain coplanar points + - added note that option 'Q5' may be used if outer planes are not needed + - added note to README.txt about Irix 5.1 [C. Goudeseune] + - added code fragment for visiting Voronoi vertices to "Calling Qhull" [M. Downes] + - added note about qh_addpoint() to "Calling Qhull" [M. Downes] + + Errors fixed for V2.2 + - use qh_sethyperplane_gauss if 3-d or 4-d norm is less than qh MINnorm + - count Zcentrumtests if qh_NOstat + - reversed sign convention for qh_sethyperplane_gauss + it was opposite to qh_sethyperplane_det + this effects qh_determinant and qh_detsimplex + - fixed error in qh_findgood_all with multiple restrictions, e.g., 'QVn Pdk' + - fixed call to qh_clearcenters for qh_produce_output + - in qh_errexit, report p0 if last furthest point + + Changes for users of the Qhull library + - user code needs to define qh_version (see user_eg.c) + - merged initialization code into qh_init_A and qh_init_B [M. Mazzario] + old code works as before. + qh_initflags also sets qh qhull_command for qh_initthresholds + redid initialization for user_eg.c + - simplified user_eg.c. It computes the convex hull of a cube. + - added qh_setvoronoi_all in poly2.c to compute Voronoi centers + added related note to call_qhull + - added qh_findfacet to use in place of qh_findbest + - added qh_nearvertex to return nearest vertex in facet to point + - redid notes on multiple, concurrent calls in call_qhull/user.c + - changed BoolT to unsigned int (prevent implicit enum conversion warnings) + - added upperdelaunay to facetT. It indicates a facet of the upper convex hull. + - converted qhull-PPC.sit for CodeWarrior 7 + + Code changes for V2.2 + - simplified calls to setjmp() for Cray J916 [Salazar & Velez] + - replaced fprintf(fp,string) with fputs in io.c + - 'qh num_coplanar' removed (too expensive and not used). + - added numcoplanars to qh_countfacets() + - added min norm to qh_normalize2(). qh_normalize() wasn't changed + - removed type casts from qh_point and qh_pointid [Salazar & Velez] + - account for roundoff error in detecting upper convex hull (qh ANGLEround). + - post merging uses qh_findbestnew for partitioning + - qh_findbestnew for qh_partitioncoplanar goes to best facet + - 'Qm' always processes points above the upper hull of a Delaunay triangulation + - GOODvertex initialized with qh_findbestnew instead of qh_findbest + - for 'v', qh_facetcenter returns furthest-neighbor vertex if 'Qu' + - added test for qh feasible_point if use 'Fp' and qh_sethalfspace_all + - reviewed Sugihara's algorithm for topologically robust beneath-beyond + - on error, report if qhull in post-merging or has completed + - if tracing, option 'FO' and qhull command always printed + - added current furthest point ("during p%d") to 'T-1' events + - added 'TWn' tracing for vertices of new facets (qh_setfacetplane) + - added 'TWn' tracing for vertices in an output facet (qh_check_maxout) + - reorganized split between poly/poly2.c and geom/geom2.c + - reordered object files in Makefile + +qhull V2.1 95/9/25 + - converted qhull.man to html format, many edits + - referenced Shewchuk's triangle program and Schneiders' Mesh Generation page + - added option 'Qa' to force all points outside + automatically set for "precise" Delaunay or Voronoi [Salazar & Velez] + it is turned off by merging, 'Wn', 'Qc' or 'Qi' + - added coplanar points to option 'FN' + - moved option 'FO' to include default precision options + - changed default random number generator to qh_rand in geom2.c (user.h) + + other code changes + - fixed option comment Pdrop-facets-dim-less, Qbound-dim-low, QbBound-unit-box + - defined ptr_intT for converting 64-bit ptrs to 'unsigned long' [D. Bremner] + - defined setelemT to distinguish actual size from pointers [D. Bremner] + use either e[...].p or e[...].i (user-level code should use set.h macros) + - changed %x to %p in format statements for pointers [D. Bremner] + - added test of REALmax,etc. to qh_maxmin [H. Poulard] + - added type parameter to qh_memalloc_() macro for type conversion + - added type conversion to qh_memalloc() calls where missing + - added type conversion to calls into set.c that return void* + + other documentation changes: + - new URLs for graphics images + - fixed comment for facetT.neighbors in qhull.h [P. Soikkonen] + - changed recommendations for precision errors in qh_printhelp_degenerate() + - added recommendation for 'V0' (facet is visible if distance >= 0) + - added note about 'long double' to user.h [S. Grundmann] + - added note about zero area Delaunay triangles for the 'v' option + - added note about locating Delaunay triangles to option 'd' [A. Curtis] + - added note that coplanar vertices correspond to duplicate points for 'd' + - added note about option 'd' automatically setting 'PDk' (lower convex hull) + - added note about precision errors to option 'd' [many users] + - added note about qh_findbest() to the Qhull library section [L. Lai] + - 'make install' renames qhull.man to qhull.1 for Unix [M. Phillips] + - renamed README, etc. to *.txt to match WWW conventions [D. Cervone] + +qhull V2.1 7/10/95 + - in 2-d, 'v o' lists the vertex at infinity in order [R. Critchlow] + - it used to always list the vertex at infinity ("0") first + - rewrote description of 'v' option (Voronoi vertices and 2-d diagrams) + - added 'PFn' for printing facets whose area is at least 'n' [D. Holland] + - prefixed 'Q',etc. to the 'Q',etc. options in the long help prompt + - fixed references to 'Fv' and 'FV' options under option 'Hn,n,n' + - updated reference to cdd, + - in set.c, added some missing type coercions for qhmem.tempstack + +qhull V2.1 6/12/95 + - replaced qhull.ps with qhull-2.ps (paper submitted to ACM TOMS) + - use BUFSIZ for setvbuf for Power Macintosh + - number of good facets printed if QVn, QGn, Pd, or PD + - added Makefile for Borland C++ 4.02 with Win32 [D. Zwick] + - added note to Enhancements section of qhull.1 about constrained + Delaunay triangulations [T. Rasanen] + +qhull V2.1 6/7/95 + - fixed qh_facetarea_simplex() for non-simplicial facets [L. Schramm] + - fixed cast in qh_point and qh_pointid for 64-bit architectures + - fixed URL for Amenta's list of computational geometry software + - fixed cast in qh_meminitbuffers for qhmem.freelists + - added test for !qh half_space in qh readpoints + - clarified options for qh_printhelp_singular() + - discussed non-simplicial facet area under option 'Fa' in qhull.1 + +qhull V2.1 6/3/95 + - home page for Qhull and new descriptions for the Qhull examples + http://www.qhull.org + - changed SIOUX buffering for Power Macintosh. It runs fast now. + added a project file for Metrowerk's C + - note in README about compiling qhull on the PC + +qhull V2.1 beta 5/15/95 + + ======= main changes ======== + - added halfspace intersection ('Hn,n,n') + - facet merging is better, especially for high dimensions + - added 'Qx' for exact merges of coplanar points and precision faults + - facet merging is faster, especially for high dimensions. + e.g., convex hull of the 8-d hypercube is seven times faster + - added 'F' output formats for printing each aspect of the convex hull + - format 'Fa' computes facet areas, total area, and total volume + - format 'FO' writes a descriptive list of selected options to stderr + - moved all customization options to user.h + - changed the default precision to 'double' since it's needed for Delaunay. + using 'float' is faster and takes less space (REALfloat in user.h) + - option 'Qm' is no longer important for facet merging + - removed need for 'Qs' by selecting initial simplex with pos. determinants + - renamed 'Qv' to 'Q7' since virtual memory does not work well for qhull + - Qhull is available for the Power Mac (no graphical output) + + ====== other new and modified options =========== + - changed default MINvisible ('Vn') to a multiple of premerge_centrum ('C-n') + - added 'Un' option to set width of facet for coplanar points. + This replaces the previous rules for determining coplanar points. + - changed default MINoutside ('Wn') to twice MINvisible ('Vn') + - Geomview output adjusts point radii for MINvisible 'Vn' + - the input format allows the number of points to precede the dimension + - options 'v' 'd' 'FAn' and 'FMn' record good facets ('Pg') + - added 'Fd' and 'FD' options for homogeneous coordinates in cdd format + - in rbox, added 'h' flag to generate homogeneous coordinates in cdd format + - option 'PAn' prints out the n facets with the largest area + - option 'PMn' prints out the n facets with the most merges + - option 'Po' under tracing ('Tn') no longer tries to write erroneous facets + - option 'TCn' only prints the old 'visible' facets for 'f' + - 'TFn' reports intermediate results when post-merging + - option 'Ts' with option 'TFn' prints intermediate statistics + - the message for 'Tv' reports if it is checking outer planes + - 'Tz' sends stderr output to stdout + - added 'Q1' to ignore angle when sorting merges (merges are worse) + - added 'Q2' to not perform merges in independent sets (merges are worse) + - added 'Q3' to not remove redundant vertices (faster) + - added 'Q4' to avoid merges of old facets into new facets (does worse) + - added 'Q5' to skip qh_check_maxout (faster, but less accurate) + - added 'Q6' to skip pre-merge of concave and coplanar facets + - added 'Qv' for testing vertex neighbors for convexity (needs merge option) + - added warning if mix Geomview output with other outputs ('Po' turns off) + - options 'o v' for 3-d and higher sort the Voronoi vertices by index + + ======= documentation ======= + - rewrote the introduction and precision sections + - added a section on performance + - added an example on halfspace intersection + - installed examples of Qhull in + + + ======= Makefile, user.h, and messages ======= + - Makefile calls ./qhull, ./rbox, and prints short prompt for qhull + - added new statistics, e.g., for buildhull + - changed default qh_RANDOMtype to RAND_MAX with rand() + - added comment about numeric overflow to printhelp_singular + - reorganized the code to improve locality of reference + - option in mem.h (qh_NOmem) to turn off memory management in qhull + - option in user.h (qh_NOtrace) to turn off tracing in qhull + - option in user.h (qh_NOmerge) to turn off merging in qhull. + - use this instead of redefining qh_merge_nonconvex in user.c + - simplified user_eg.c. See qh_call_qhull() in user.c for the full version + + ======== bug fixes ============ + - fixed error in number of points for 'rbox 100 r' (odd distribution) + - fixed performance error in qh_degen_redundant_neighbors + - qh_partitionpoint now sets facet->maxoutside for first outside point + - fixed performance error in partitioning when merging a large, regular cone + - removed memory leak in qh_appendmergeset + - removed double free of qh line under errors in qh_readinput() + - forcing output on error ('Po') fixed for options 'n' 'o' 'i' 's' + - fixed optimization error on HP machines [fprintf(... *p++)] + + ======== changes to qhull.h for user code ======= + - qh_collectstatistics and qh_printstatistics removed from qhull.h. + should use qh_printallstatistics instead + - qh_findbest uses boolT for newfacets + - added qh_findbestnew for non-simplicial facets. qh_findbest is + too slow in this case since it needs to look at many nearly coplanar + facets. + - renamed qh_voronoi/qh_centrum to qh_ASvoronoi, qh_AScentrum + - changed facet->id to 32-bits, added new flags for merging + - added facet->f for facet pointers while merging and for facet area + - added dfacet/dvertex for printing facets/vertices while debugging + - added qh_produce_output and qh_printsummary + + ======== changes to code ========== + - moved qh_setfacetplane from qh_makenewfacets to qh_makenewplanes + - added qh_setfree2, qh_setcompact, and qh_setduplicate to set.c + - qh_findgooddist returns list of visible facets instead of setting global + - in qh_check_maxout, inside points may be added to coplanar list. + - qh_findbestnew used for qh_partitionall. It is faster. + - in qh_findbest, changed searchdist to MINvisible+max_outside+DISTround. + MINvisible is the default MAXcoplanar. + - cleaned up list management via qh_resetlists + - uses facet->dupridge to indicate duplicated ridges instead of ->seen + - qh_buildtracing records CPU time relative to qh hulltime instead of 0 + + ========== changes to merging ======= + - many performance improvements, especially in high-d. + - when merging, qh_findbest and qh_findbestnew stops search at qh_DISToutside + - vertex neighbors delayed until first merge + - post merges reported every TFn/2 merges + - vertex merging turned off in 7-d and higher (lots of work, no benefit). + vertex merging moved to qh_qhull_postmerging in 6-d. + - replaced qh min_vertex with MAXcoplanar for determining coplanarity + - pick closest facets to merge in duplicate ridge instead of flip/flip + (see qh_matchduplicates in poly2.c) + - optimize merge of simplex into a facet + - optimize merge of a "samecycle" of facets into a coplanar horizon facet + - cleaned up qh_forcedmerges/qh_flippedmerges and removed facet->newmerge + - rewrote qh_merge_degenredundant with separate queue + - qh_facetdegen replaced by facet->degenredun + - flipped neighbors no longer merged in preference to flip/non-flip pairs + - removed angle argument from qh_merge_degenredundant and qh_mergefacet + only used for tracing + - getmergeset_initial had extra test of neighbor->simplicial + - ridge->nonconvex is now set on only one ridge between non-convex facets + - moved centrum deletion to qh_updatetested + - qh_isnewmerge(facet) changed to facet->newmerge (removed NEWmerges) + - qh_findbestneighbor reports correct distance even if testcentrum + - added hull_dim factor to qh_BESTcentrum + - removed horizon preference in qh_merge_nonconvex (qh AVOIDold) + - facet->keepcentrum if qh WIDEfacet or qh_MAXnewcentrum extra vertices + +qhull V2.02 1/25/95 + - rbox 'z' prints integer coordinates, use 'Bn' to change range + - fixed rare bug in qh_check_maxout when qh_bestfacet returns NULL + - fixed performance bug in findbestneighbor, should be + BESTnonconvex + - renamed 'notgood' flag in 'f' option to 'notG' flag (caused confusion) + - changed qh.hulltime to (unsigned) to prevent negative CPU times + - added random perturbations to qh_getangle under the 'Rn' option + - reviewed the documentation and enhancement list + - added discussion of how to intersect halfspaces using qhull + - replaced expression that caused incorrect code under an old version of gcc + - added buffer after qh.errexit in case 'jmp_buf' has the wrong size + - rewrote qh_printhelp_singular for lower-dimensional inputs + - rewrote qh_printhelp_degenerate + - added options for qh_RANDOMint in qhull_a.h + - changed time format for 'TFn' to %02d + +qhull V2.01 6/20/94 + - fixed bug in qh_matchnewfacets that occured when memory alignment makes + facet->neighbors larger than necessary. + - fixed bug in computing worst-case simplicial merge of angle coplanar + facets (ONEmerge). This decreases (...x) in printsummary. + +qhull V2.01 6/17/94 + - added recommendation for 'Qcm' to documentation and help prompts + - added an input warning to qh_check_points ('Tv') if coplanars and no 'Qc' + - qh_partitionpoint: always counts coplanar partitions (Zcoplanarpart) + - rewrote qh_printhelp_degenerate to emphasize option 'C-0' + - For Geomview output, roundoff is not needed when printing the inner and + outer planes. This improves Geomview output for the 'Rn' option. + - For Geomview output without coplanar points or vertices, qh_GEOMepislon + is not needed. This removes the edge gap when displaying a Voronoi cell. + - For Geomview output 'Gp', direct vertices to the interior point + instead of the arithmetic center of the displayed vertices. + +qhull V2.01 6/11/94 + - if pre-merge, 'Qf' is automatically set. Otherwise an outside point may + be dropt by qh_findbest(). This slows down partitioning. + - always use 'Qc' if merging and all facet->maxoutside's must be right. + Otherwise distributions with many coplanar points may occassionally + miss a coplanar point for a facet. This is because qh_findbest, when + called by qh_check_maxout, can become stuck at a local maximum if + the search is started at an arbitrary facet. With 'Qc', the search + is started from a coplanar facet. For example, + rbox 1000 W8e-6 t | qhull C-0 Tv + will (rarely) report that a facet->minoutside is incorrect + - option 'Pp' turns off "Verifying" message for 'Tv' + - added qh_copynonconvex to qh_renameridgevertex (fixes rare error) + - 'rbox tn' sets random seed to n + - 'rbox t' reports random seed in comment line + - qh_errexit reports rbox_command | qhull_command and 'QR' random seed + - added additional tracing to bestdist and setfacetplane + - in qh_checkconvex, need to test coplanar against 0 instead of -DISTround + - in qh_checkconvex, always test centrums if merging. The opposite + vertex of a simplicial facet may be coplanar since a vertex of + a simplicial facet may be above the facet's hyperplane. + - fixed error handling in qh_checkconvex when merging + - in qh_printsummary, one merge ratio not printed if less than 'Wn' + - documented that 'Tv' verifies all facet->maxoutside + +qhull V2.01 6/2/94 + - 's' prints summary to stderr + - multiple output formats printed in order to stdout + - added statistic for worst-case distance for merging simplicial facets + can not hope for a better "max distance above/below facet" + print factor for "max distance.."/"merge simplicial" in printsummary + - fixed error in scaling input with min/max reversed ('Qb0:1B0:-1') + - fixed error in scaling if project & Delaunay & scale ('d Qb0:0B1:0b2:0') + - user_eg.c: qh_delpoint removed since it does not always work + - user_eg.c now works for either convex hull or Delaunay triangulation + - added PROJECTdelaunay for Delaunay triangulations and Voronoi diagrams + with libqhull.a and user_eg.c + - user_eg.c: if project or scale input, need to copy points + - user_eg.c: default just defines main, added fprintf's for qh_errprint etc. + - qh_gausselim: a 0 pivot no longer zeros the rest of the array, + need the remaining elements for area computation + - qh_qhull: restore cos_max, centrum_radius at end of POSTmerging + - qh_checkflipped with !allerror is >=0.0 instead of >0.0 + - removed -Wall from gcc due to unnecesssary "warning: implicit declaration" + - renamed 'new' variables and fields to allow compilation by g++ + - added README notes on C++, and "size isn't known" + - updated manual on 'Qg' with coplanar facets and no merging ('rbox c D7') + 'Qg Pg' and 'Pg' produce different results because of precision problems + +Converting from qhull 1.01 to qhull 2.00 + - 'qhull An' is now 'qhull Wn' + option 'Wn Po' is faster but it doesn't check coplanars + - 'qhull g' is now 'qhull G', and the output formats are different + - 'qhull c' is now 'qhull Tc' + - 'qhull f' is now 'qhull Qf' + - 'qhull o' is now 'qhull Po' + - 'qhull b' is now always done + - qhull and rbox now use floats, change REALfloat in qhull.h for doubles + - qhull 2.00 fixes several initialization errors and performanace errors + e.g., "singular input" on data with lots of 0 coordinates + - 'rbox b' is now 'rbox c G0.48' + - all rbox distributions are now scaled to a 0.5 box (use 'Bn' to change) + - rbox now adds a comment line. This may be removed by 'rbox n' + - 'rbox r s Z G' no longer includes the positive pole + - no changes to the Macintosh version + +qhull V2.00 5/23/94 + - if force output ('Po'), facet->maxoutside= 'Wn' since coplanars not updated + convexity checked if precision problems or verify ('Tv') + - if merging, new facets always checked for flipped orientation + - a facet is visible (findhorizon) under 'Qm' if distance > max_vertex + - if using 'Qm' then min. outside is max_vertex instead of max_outside + - default is random()/srandom() in qhull_a.h, checked in initqhull_globals + - created internal strtod since strtod may skip spacing after number + - removed lower bound (1.0) for qh maxmaxcoord + - divzero needs to handle 0/0 and large/small + - decreased size of precise vertices + - need to initialize qh MINdenom_1 for scalepoints + - added factor of qh maxmaxcoord into DISTround (needed for offset) + - 'Rn' perturbs distance computations by random +/-n + - check_points needs an extra DISTround to get from precise point to computed + - rewrote some of the IMPRECISION section in qhull.man + - added the input format to the qhull prompt + - moved include files to qhull_a.h since some compilers do not use float.h + - added qhull.1 and rbox.1 since SGI does not ship nroff + - reduced cutoff for printpointvect + - use time for qhull random seed only if QR0 or QR-1 + - radius of vertices and coplanar points determined by pre-merge values + +qhull V2.00 5/12/94 + - facet2point (io.c) used vertex0 instead of vertex1 + - can't print visible facets after cone is attached + - shouldn't check output after STOPcone (TCn) + - statistic 'Wminvertex' and 'Wmaxoutside' only if MERGING or APPROXhull + - 'make doc' uses lineprinter format for paging + - warning if Gpv in 4-d + +qhull V2.b05 5/9/94 + - decreased size of precise vertices + - precise facets in 2-d print hyperplanes + - accounted for GOODpoint in printsummary + - added IMPRECISION section to qhull.man + - 'Qg' does work in 7-d unless there's many coplanar facets + Added: trunk/scipy/spatial/qhull/src/geom.c =================================================================== --- trunk/scipy/spatial/qhull/src/geom.c (rev 0) +++ trunk/scipy/spatial/qhull/src/geom.c 2010-08-31 21:54:55 UTC (rev 6652) @@ -0,0 +1,1229 @@ +/*

  ---------------------------------
+
+   geom.c 
+   geometric routines of qhull
+
+   see qh-geom.htm and geom.h
+
+   copyright (c) 1993-2003 The Geometry Center        
+
+   infrequent code goes into geom2.c
+*/
+   
+#include "qhull_a.h"
+   
+/*---------------------------------
+  
+  qh_distplane( point, facet, dist )
+    return distance from point to facet
+
+  returns:
+    dist
+    if qh.RANDOMdist, joggles result
+  
+  notes:  
+    dist > 0 if point is above facet (i.e., outside)
+    does not error (for sortfacets)
+    
+  see:
+    qh_distnorm in geom2.c
+*/
+void qh_distplane (pointT *point, facetT *facet, realT *dist) {
+  coordT *normal= facet->normal, *coordp, randr;
+  int k;
+  
+  switch(qh hull_dim){
+  case 2:
+    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
+    break;
+  case 3:
+    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
+    break;
+  case 4:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
+    break;
+  case 5:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
+    break;
+  case 6:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
+    break;
+  case 7:  
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
+    break;
+  case 8:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
+    break;
+  default:
+    *dist= facet->offset;
+    coordp= point;
+    for (k= qh hull_dim; k--; )
+      *dist += *coordp++ * *normal++;
+    break;
+  }
+  zinc_(Zdistplane);
+  if (!qh RANDOMdist && qh IStracing < 4)
+    return;
+  if (qh RANDOMdist) {
+    randr= qh_RANDOMint;
+    *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
+      qh RANDOMfactor * qh MAXabs_coord;
+  }
+  if (qh IStracing >= 4) {
+    fprintf (qh ferr, "qh_distplane: ");
+    fprintf (qh ferr, qh_REAL_1, *dist);
+    fprintf (qh ferr, "from p%d to f%d\n", qh_pointid(point), facet->id);
+  }
+  return;
+} /* distplane */
+
+
+/*---------------------------------
+  
+  qh_findbest( point, startfacet, bestoutside, qh_ISnewfacets, qh_NOupper, dist, isoutside, numpart )
+    find facet that is furthest below a point 
+    for upperDelaunay facets
+      returns facet only if !qh_NOupper and clearly above
+
+  input:
+    starts search at 'startfacet' (can not be flipped)
+    if !bestoutside (qh_ALL), stops at qh.MINoutside
+
+  returns:
+    best facet (reports error if NULL)
+    early out if isoutside defined and bestdist > qh.MINoutside
+    dist is distance to facet
+    isoutside is true if point is outside of facet
+    numpart counts the number of distance tests
+
+  see also:
+    qh_findbestnew()
+    
+  notes:
+    If merging (testhorizon), searches horizon facets of coplanar best facets because
+    after qh_distplane, this and qh_partitionpoint are the most expensive in 3-d
+      avoid calls to distplane, function calls, and real number operations.
+    caller traces result
+    Optimized for outside points.   Tried recording a search set for qh_findhorizon.
+    Made code more complicated.
+
+  when called by qh_partitionvisible():
+    indicated by qh_ISnewfacets
+    qh.newfacet_list is list of simplicial, new facets
+    qh_findbestnew set if qh_sharpnewfacets returns True (to use qh_findbestnew)
+    qh.bestfacet_notsharp set if qh_sharpnewfacets returns False
+
+  when called by qh_findfacet(), qh_partitionpoint(), qh_partitioncoplanar(), 
+                 qh_check_bestdist(), qh_addpoint()
+    indicated by !qh_ISnewfacets
+    returns best facet in neighborhood of given facet
+      this is best facet overall if dist > -   qh.MAXcoplanar 
+        or hull has at least a "spherical" curvature
+
+  design:
+    initialize and test for early exit
+    repeat while there are better facets
+      for each neighbor of facet
+        exit if outside facet found
+	test for better facet
+    if point is inside and partitioning
+      test for new facets with a "sharp" intersection
+      if so, future calls go to qh_findbestnew()
+    test horizon facets
+*/
+facetT *qh_findbest (pointT *point, facetT *startfacet, 
+		     boolT bestoutside, boolT isnewfacets, boolT noupper,
+		     realT *dist, boolT *isoutside, int *numpart) {
+  realT bestdist= -REALmax/2 /* avoid underflow */;
+  facetT *facet, *neighbor, **neighborp;
+  facetT *bestfacet= NULL, *lastfacet= NULL;
+  int oldtrace= qh IStracing;
+  unsigned int visitid= ++qh visit_id;
+  int numpartnew=0;
+  boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+  zinc_(Zfindbest);
+  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
+    if (qh TRACElevel > qh IStracing)
+      qh IStracing= qh TRACElevel;
+    fprintf (qh ferr, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g\n",
+	     qh_pointid(point), startfacet->id, isnewfacets, bestoutside, qh MINoutside);
+    fprintf(qh ferr, "  testhorizon? %d noupper? %d", testhorizon, noupper);
+    fprintf (qh ferr, "  Last point added was p%d.", qh furthest_id);
+    fprintf(qh ferr, "  Last merge was #%d.  max_outside %2.2g\n", zzval_(Ztotmerge), qh max_outside);
+  }
+  if (isoutside)
+    *isoutside= True;
+  if (!startfacet->flipped) {  /* test startfacet */
+    *numpart= 1;
+    qh_distplane (point, startfacet, dist);  /* this code is duplicated below */
+    if (!bestoutside && *dist >= qh MINoutside 
+    && (!startfacet->upperdelaunay || !noupper)) {
+      bestfacet= startfacet;
+      goto LABELreturn_best;
+    }
+    bestdist= *dist;
+    if (!startfacet->upperdelaunay) {
+      bestfacet= startfacet;
+    } 
+  }else 
+    *numpart= 0;
+  startfacet->visitid= visitid;
+  facet= startfacet;
+  while (facet) {
+    trace4((qh ferr, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n", 
+                facet->id, bestdist, getid_(bestfacet)));
+    lastfacet= facet;
+    FOREACHneighbor_(facet) {
+      if (!neighbor->newfacet && isnewfacets)
+        continue;
+      if (neighbor->visitid == visitid)
+	continue;
+      neighbor->visitid= visitid;
+      if (!neighbor->flipped) {  /* code duplicated above */
+	(*numpart)++;
+	qh_distplane (point, neighbor, dist);
+	if (*dist > bestdist) {
+	  if (!bestoutside && *dist >= qh MINoutside 
+	  && (!neighbor->upperdelaunay || !noupper)) {
+	    bestfacet= neighbor;
+	    goto LABELreturn_best;
+	  }
+	  if (!neighbor->upperdelaunay) {
+	    bestfacet= neighbor;
+	    bestdist= *dist;
+	    break; /* switch to neighbor */
+	  }else if (!bestfacet) { 
+	    bestdist= *dist;
+	    break; /* switch to neighbor */
+	  }
+	} /* end of *dist>bestdist */
+      } /* end of !flipped */
+    } /* end of FOREACHneighbor */
+    facet= neighbor;  /* non-NULL only if *dist>bestdist */
+  } /* end of while facet (directed search) */
+  if (isnewfacets) { 
+    if (!bestfacet) {
+      bestdist= -REALmax/2; 
+      bestfacet= qh_findbestnew (point, startfacet->next, &bestdist, bestoutside, isoutside, &numpartnew);
+      testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+    }else if (!qh findbest_notsharp && bestdist < - qh DISTround) {
+      if (qh_sharpnewfacets()) { 
+	/* seldom used, qh_findbestnew will retest all facets */
+	zinc_(Zfindnewsharp);
+	bestfacet= qh_findbestnew (point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
+	testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+	qh findbestnew= True;
+      }else
+	qh findbest_notsharp= True;
+    }
+  }
+  if (!bestfacet) 
+    bestfacet= qh_findbestlower (lastfacet, point, &bestdist, numpart);
+  if (testhorizon) 
+    bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
+  *dist= bestdist;
+  if (isoutside && bestdist < qh MINoutside)
+    *isoutside= False;
+LABELreturn_best:
+  zadd_(Zfindbesttot, *numpart);
+  zmax_(Zfindbestmax, *numpart);
+  (*numpart) += numpartnew;
+  qh IStracing= oldtrace;
+  return bestfacet;
+}  /* findbest */
+
+
+/*---------------------------------
+  
+  qh_findbesthorizon( qh_IScheckmax, point, startfacet, qh_NOupper, &bestdist, &numpart )
+    search coplanar and better horizon facets from startfacet/bestdist
+    ischeckmax turns off statistics and minsearch update
+    all arguments must be initialized
+  returns (ischeckmax):
+    best facet
+  returns (!ischeckmax):
+    best facet that is not upperdelaunay
+    allows upperdelaunay that is clearly outside
+  returns:
+    bestdist is distance to bestfacet
+    numpart -- updates number of distance tests
+
+  notes:
+    no early out -- use qh_findbest() or qh_findbestnew()
+    Searches coplanar or better horizon facets
+
+  when called by qh_check_maxout() (qh_IScheckmax)
+    startfacet must be closest to the point
+      Otherwise, if point is beyond and below startfacet, startfacet may be a local minimum
+      even though other facets are below the point.
+    updates facet->maxoutside for good, visited facets
+    may return NULL
+
+    searchdist is qh.max_outside + 2 * DISTround
+      + max( MINvisible('Vn'), MAXcoplanar('Un'));
+    This setting is a guess.  It must be at least max_outside + 2*DISTround 
+    because a facet may have a geometric neighbor across a vertex
+
+  design:
+    for each horizon facet of coplanar best facets
+      continue if clearly inside
+      unless upperdelaunay or clearly outside
+         update best facet
+*/
+facetT *qh_findbesthorizon (boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
+  facetT *bestfacet= startfacet;
+  realT dist;
+  facetT *neighbor, **neighborp, *facet;
+  facetT *nextfacet= NULL; /* optimize last facet of coplanarset */
+  int numpartinit= *numpart, coplanarset_size;
+  unsigned int visitid= ++qh visit_id;
+  boolT newbest= False; /* for tracing */
+  realT minsearch, searchdist;  /* skip facets that are too far from point */
+
+  if (!ischeckmax) {
+    zinc_(Zfindhorizon);
+  }else {
+#if qh_MAXoutside
+    if ((!qh ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
+      startfacet->maxoutside= *bestdist;
+#endif
+  }
+  searchdist= qh_SEARCHdist; /* multiple of qh.max_outside and precision constants */
+  minsearch= *bestdist - searchdist;
+  if (ischeckmax) {
+    /* Always check coplanar facets.  Needed for RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv */
+    minimize_(minsearch, -searchdist);
+  }
+  coplanarset_size= 0;
+  facet= startfacet;
+  while (True) {
+    trace4((qh ferr, "qh_findbesthorizon: neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g searchdist %2.2g\n", 
+		facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
+		minsearch, searchdist));
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == visitid) 
+	continue;
+      neighbor->visitid= visitid;
+      if (!neighbor->flipped) { 
+	qh_distplane (point, neighbor, &dist);
+	(*numpart)++;
+	if (dist > *bestdist) {
+	  if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh MINoutside)) {
+	    bestfacet= neighbor;
+	    *bestdist= dist;
+	    newbest= True;
+	    if (!ischeckmax) {
+	      minsearch= dist - searchdist;
+	      if (dist > *bestdist + searchdist) {
+		zinc_(Zfindjump);  /* everything in qh.coplanarset at least searchdist below */
+		coplanarset_size= 0;
+	      }
+	    }
+	  }
+	}else if (dist < minsearch) 
+	  continue;  /* if ischeckmax, dist can't be positive */
+#if qh_MAXoutside
+	if (ischeckmax && dist > neighbor->maxoutside)
+	  neighbor->maxoutside= dist;
+#endif      
+      } /* end of !flipped */
+      if (nextfacet) {
+	if (!coplanarset_size++) {
+	  SETfirst_(qh coplanarset)= nextfacet;
+	  SETtruncate_(qh coplanarset, 1);
+	}else
+  	  qh_setappend (&qh coplanarset, nextfacet); /* Was needed for RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
+						 and RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv  */
+      }
+      nextfacet= neighbor;
+    } /* end of EACHneighbor */
+    facet= nextfacet;
+    if (facet) 
+      nextfacet= NULL;
+    else if (!coplanarset_size)
+      break; 
+    else if (!--coplanarset_size) {
+      facet= SETfirst_(qh coplanarset);
+      SETtruncate_(qh coplanarset, 0);
+    }else
+      facet= (facetT*)qh_setdellast (qh coplanarset);
+  } /* while True, for each facet in qh.coplanarset */
+  if (!ischeckmax) {
+    zadd_(Zfindhorizontot, *numpart - numpartinit);
+    zmax_(Zfindhorizonmax, *numpart - numpartinit);
+    if (newbest)
+      zinc_(Zparthorizon);
+  }
+  trace4((qh ferr, "qh_findbesthorizon: newbest? %d bestfacet f%d bestdist %2.2g\n", newbest, getid_(bestfacet), *bestdist));
+  return bestfacet;
+}  /* findbesthorizon */
+
+/*---------------------------------
+  
+  qh_findbestnew( point, startfacet, dist, isoutside, numpart )
+    find best newfacet for point
+    searches all of qh.newfacet_list starting at startfacet
+    searches horizon facets of coplanar best newfacets
+    searches all facets if startfacet == qh.facet_list
+  returns:
+    best new or horizon facet that is not upperdelaunay
+    early out if isoutside and not 'Qf'
+    dist is distance to facet
+    isoutside is true if point is outside of facet
+    numpart is number of distance tests
+
+  notes:
+    Always used for merged new facets (see qh_USEfindbestnew)
+    Avoids upperdelaunay facet unless (isoutside and outside)
+
+    Uses qh.visit_id, qh.coplanarset.  
+    If share visit_id with qh_findbest, coplanarset is incorrect.
+
+    If merging (testhorizon), searches horizon facets of coplanar best facets because
+    a point maybe coplanar to the bestfacet, below its horizon facet,
+    and above a horizon facet of a coplanar newfacet.  For example,
+      rbox 1000 s Z1 G1e-13 | qhull
+      rbox 1000 s W1e-13 P0 t992110337 | QHULL d Qbb Qc
+
+    qh_findbestnew() used if
+       qh_sharpnewfacets -- newfacets contains a sharp angle
+       if many merges, qh_premerge found a merge, or 'Qf' (qh.findbestnew)
+
+  see also:
+    qh_partitionall() and qh_findbest()
+
+  design:
+    for each new facet starting from startfacet
+      test distance from point to facet
+      return facet if clearly outside
+      unless upperdelaunay and a lowerdelaunay exists
+         update best facet
+    test horizon facets
+*/
+facetT *qh_findbestnew (pointT *point, facetT *startfacet,
+	   realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
+  realT bestdist= -REALmax/2;
+  facetT *bestfacet= NULL, *facet;
+  int oldtrace= qh IStracing, i;
+  unsigned int visitid= ++qh visit_id;
+  realT distoutside= 0.0;
+  boolT isdistoutside; /* True if distoutside is defined */
+  boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+  if (!startfacet) {
+    if (qh MERGING)
+      fprintf(qh ferr, "qhull precision error (qh_findbestnew): merging has formed and deleted a cone of new facets.  Can not continue.\n");
+    else
+      fprintf(qh ferr, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
+      	      qh furthest_id);      
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  zinc_(Zfindnew);
+  if (qh BESToutside || bestoutside)
+    isdistoutside= False;
+  else {
+    isdistoutside= True;
+    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
+  }
+  if (isoutside)
+    *isoutside= True;
+  *numpart= 0;
+  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
+    if (qh TRACElevel > qh IStracing)
+      qh IStracing= qh TRACElevel;
+    fprintf(qh ferr, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g\n",
+	     qh_pointid(point), startfacet->id, isdistoutside, distoutside);
+    fprintf(qh ferr, "  Last point added p%d visitid %d.",  qh furthest_id, visitid);
+    fprintf(qh ferr, "  Last merge was #%d.\n", zzval_(Ztotmerge));
+  }
+  /* visit all new facets starting with startfacet, maybe qh facet_list */
+  for (i= 0, facet= startfacet; i < 2; i++, facet= qh newfacet_list) {
+    FORALLfacet_(facet) {
+      if (facet == startfacet && i)
+	break;
+      facet->visitid= visitid;
+      if (!facet->flipped) {
+	qh_distplane (point, facet, dist);
+	(*numpart)++;
+	if (*dist > bestdist) {
+	  if (!facet->upperdelaunay || *dist >= qh MINoutside) {
+	    bestfacet= facet;
+	    if (isdistoutside && *dist >= distoutside)
+	      goto LABELreturn_bestnew;
+	    bestdist= *dist;
+  	  }
+	}
+      } /* end of !flipped */
+    } /* FORALLfacet from startfacet or qh newfacet_list */
+  }
+  if (testhorizon || !bestfacet)
+    bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet ? bestfacet : startfacet, 
+	                                !qh_NOupper, &bestdist, numpart);  
+  *dist= bestdist;
+  if (isoutside && *dist < qh MINoutside)
+    *isoutside= False;
+LABELreturn_bestnew:
+  zadd_(Zfindnewtot, *numpart);
+  zmax_(Zfindnewmax, *numpart);
+  trace4((qh ferr, "qh_findbestnew: bestfacet f%d bestdist %2.2g\n", getid_(bestfacet), *dist));
+  qh IStracing= oldtrace;
+  return bestfacet;
+}  /* findbestnew */
+
+/* ============ hyperplane functions -- keep code together [?] ============ */
+
+/*---------------------------------
+  
+  qh_backnormal( rows, numrow, numcol, sign, normal, nearzero )
+    given an upper-triangular rows array and a sign,
+    solve for normal equation x using back substitution over rows U
+
+  returns:
+     normal= x
+      
+     if will not be able to divzero() when normalized (qh.MINdenom_2 and qh.MINdenom_1_2),
+       if fails on last row
+         this means that the hyperplane intersects [0,..,1]
+         sets last coordinate of normal to sign
+       otherwise
+         sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...0]
+         sets nearzero
+
+  notes:
+     assumes numrow == numcol-1
+
+     see Golub & van Loan 4.4-9 for back substitution
+
+     solves Ux=b where Ax=b and PA=LU
+     b= [0,...,0,sign or 0]  (sign is either -1 or +1)
+     last row of A= [0,...,0,1]
+
+     1) Ly=Pb == y=b since P only permutes the 0's of   b
+     
+  design:
+    for each row from end
+      perform back substitution
+      if near zero
+        use qh_divzero for division
+        if zero divide and not last row
+          set tail of normal to 0
+*/
+void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign,
+  	coordT *normal, boolT *nearzero) {
+  int i, j;
+  coordT *normalp, *normal_tail, *ai, *ak;
+  realT diagonal;
+  boolT waszero;
+  int zerocol= -1;
+  
+  normalp= normal + numcol - 1;
+  *normalp--= (sign ? -1.0 : 1.0);
+  for(i= numrow; i--; ) {
+    *normalp= 0.0;
+    ai= rows[i] + i + 1;
+    ak= normalp+1;
+    for(j= i+1; j < numcol; j++)
+      *normalp -= *ai++ * *ak++;
+    diagonal= (rows[i])[i];
+    if (fabs_(diagonal) > qh MINdenom_2)
+      *(normalp--) /= diagonal;
+    else {
+      waszero= False;
+      *normalp= qh_divzero (*normalp, diagonal, qh MINdenom_1_2, &waszero);
+      if (waszero) {
+        zerocol= i;
+	*(normalp--)= (sign ? -1.0 : 1.0);
+	for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
+	  *normal_tail= 0.0;
+      }else
+	normalp--;
+    }
+  }
+  if (zerocol != -1) {
+    zzinc_(Zback0);
+    *nearzero= True;
+    trace4((qh ferr, "qh_backnormal: zero diagonal at column %d.\n", i));
+    qh_precision ("zero diagonal on back substitution");
+  }
+} /* backnormal */
+
+/*---------------------------------
+  
+  qh_gausselim( rows, numrow, numcol, sign )
+    Gaussian elimination with partial pivoting
+
+  returns:
+    rows is upper triangular (includes row exchanges)
+    flips sign for each row exchange
+    sets nearzero if pivot[k] < qh.NEARzero[k], else clears it
+
+  notes:
+    if nearzero, the determinant's sign may be incorrect.
+    assumes numrow <= numcol
+
+  design:
+    for each row
+      determine pivot and exchange rows if necessary
+      test for near zero
+      perform gaussian elimination step
+*/
+void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
+  realT *ai, *ak, *rowp, *pivotrow;
+  realT n, pivot, pivot_abs= 0.0, temp;
+  int i, j, k, pivoti, flip=0;
+  
+  *nearzero= False;
+  for(k= 0; k < numrow; k++) {
+    pivot_abs= fabs_((rows[k])[k]);
+    pivoti= k;
+    for(i= k+1; i < numrow; i++) {
+      if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
+	pivot_abs= temp;
+	pivoti= i;
+      }
+    }
+    if (pivoti != k) {
+      rowp= rows[pivoti]; 
+      rows[pivoti]= rows[k]; 
+      rows[k]= rowp; 
+      *sign ^= 1;
+      flip ^= 1;
+    }
+    if (pivot_abs <= qh NEARzero[k]) {
+      *nearzero= True;
+      if (pivot_abs == 0.0) {   /* remainder of column == 0 */
+	if (qh IStracing >= 4) {
+	  fprintf (qh ferr, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
+	  qh_printmatrix (qh ferr, "Matrix:", rows, numrow, numcol);
+	}
+	zzinc_(Zgauss0);
+        qh_precision ("zero pivot for Gaussian elimination");
+	goto LABELnextcol;
+      }
+    }
+    pivotrow= rows[k] + k;
+    pivot= *pivotrow++;  /* signed value of pivot, and remainder of row */
+    for(i= k+1; i < numrow; i++) {
+      ai= rows[i] + k;
+      ak= pivotrow;
+      n= (*ai++)/pivot;   /* divzero() not needed since |pivot| >= |*ai| */
+      for(j= numcol - (k+1); j--; )
+	*ai++ -= n * *ak++;
+    }
+  LABELnextcol:
+    ;
+  }
+  wmin_(Wmindenom, pivot_abs);  /* last pivot element */
+  if (qh IStracing >= 5)
+    qh_printmatrix (qh ferr, "qh_gausselem: result", rows, numrow, numcol);
+} /* gausselim */
+
+
+/*---------------------------------
+  
+  qh_getangle( vect1, vect2 )
+    returns the dot product of two vectors
+    if qh.RANDOMdist, joggles result
+
+  notes:
+    the angle may be > 1.0 or < -1.0 because of roundoff errors
+
+*/
+realT qh_getangle(pointT *vect1, pointT *vect2) {
+  realT angle= 0, randr;
+  int k;
+
+  for(k= qh hull_dim; k--; )
+    angle += *vect1++ * *vect2++;
+  if (qh RANDOMdist) {
+    randr= qh_RANDOMint;
+    angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
+      qh RANDOMfactor;
+  }
+  trace4((qh ferr, "qh_getangle: %2.2g\n", angle));
+  return(angle);
+} /* getangle */
+
+
+/*---------------------------------
+  
+  qh_getcenter( vertices )
+    returns arithmetic center of a set of vertices as a new point
+
+  notes:
+    allocates point array for center
+*/
+pointT *qh_getcenter(setT *vertices) {
+  int k;
+  pointT *center, *coord;
+  vertexT *vertex, **vertexp;
+  int count= qh_setsize(vertices);
+
+  if (count < 2) {
+    fprintf (qh ferr, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  center= (pointT *)qh_memalloc(qh normal_size);
+  for (k=0; k < qh hull_dim; k++) {
+    coord= center+k;
+    *coord= 0.0;
+    FOREACHvertex_(vertices)
+      *coord += vertex->point[k];
+    *coord /= count;
+  }
+  return(center);
+} /* getcenter */
+
+
+/*---------------------------------
+  
+  qh_getcentrum( facet )
+    returns the centrum for a facet as a new point
+
+  notes:
+    allocates the centrum
+*/
+pointT *qh_getcentrum(facetT *facet) {
+  realT dist;
+  pointT *centrum, *point;
+
+  point= qh_getcenter(facet->vertices);
+  zzinc_(Zcentrumtests);
+  qh_distplane (point, facet, &dist);
+  centrum= qh_projectpoint(point, facet, dist);
+  qh_memfree(point, qh normal_size);
+  trace4((qh ferr, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
+	  facet->id, qh_setsize(facet->vertices), dist));
+  return centrum;
+} /* getcentrum */
+
+
+/*---------------------------------
+  
+  qh_getdistance( facet, neighbor, mindist, maxdist )
+    returns the maxdist and mindist distance of any vertex from neighbor
+
+  returns:
+    the max absolute value
+
+  design:
+    for each vertex of facet that is not in neighbor
+      test the distance from vertex to neighbor
+*/
+realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
+  vertexT *vertex, **vertexp;
+  realT dist, maxd, mind;
+  
+  FOREACHvertex_(facet->vertices)
+    vertex->seen= False;
+  FOREACHvertex_(neighbor->vertices)
+    vertex->seen= True;
+  mind= 0.0;
+  maxd= 0.0;
+  FOREACHvertex_(facet->vertices) {
+    if (!vertex->seen) {
+      zzinc_(Zbestdist);
+      qh_distplane(vertex->point, neighbor, &dist);
+      if (dist < mind)
+	mind= dist;
+      else if (dist > maxd)
+	maxd= dist;
+    }
+  }
+  *mindist= mind;
+  *maxdist= maxd;
+  mind= -mind;
+  if (maxd > mind)
+    return maxd;
+  else
+    return mind;
+} /* getdistance */
+
+
+/*---------------------------------
+
+  qh_normalize( normal, dim, toporient )
+    normalize a vector and report if too small
+    does not use min norm
+  
+  see:
+    qh_normalize2
+*/
+void qh_normalize (coordT *normal, int dim, boolT toporient) {
+  qh_normalize2( normal, dim, toporient, NULL, NULL);
+} /* normalize */
+
+/*---------------------------------
+  
+  qh_normalize2( normal, dim, toporient, minnorm, ismin )
+    normalize a vector and report if too small
+    qh.MINdenom/MINdenom1 are the upper limits for divide overflow
+
+  returns:
+    normalized vector
+    flips sign if !toporient
+    if minnorm non-NULL, 
+      sets ismin if normal < minnorm
+
+  notes:
+    if zero norm
+       sets all elements to sqrt(1.0/dim)
+    if divide by zero (divzero ())
+       sets largest element to   +/-1
+       bumps Znearlysingular
+      
+  design:
+    computes norm
+    test for minnorm
+    if not near zero
+      normalizes normal
+    else if zero norm
+      sets normal to standard value
+    else
+      uses qh_divzero to normalize
+      if nearzero
+        sets norm to direction of maximum value
+*/
+void qh_normalize2 (coordT *normal, int dim, boolT toporient, 
+            realT *minnorm, boolT *ismin) {
+  int k;
+  realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
+  boolT zerodiv;
+
+  norm1= normal+1;
+  norm2= normal+2;
+  norm3= normal+3;
+  if (dim == 2)
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
+  else if (dim == 3)
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
+  else if (dim == 4) {
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2) 
+               + (*norm3)*(*norm3));
+  }else if (dim > 4) {
+    norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2) 
+               + (*norm3)*(*norm3);
+    for (k= dim-4, colp= normal+4; k--; colp++)
+      norm += (*colp) * (*colp);
+    norm= sqrt(norm);
+  }
+  if (minnorm) {
+    if (norm < *minnorm) 
+      *ismin= True;
+    else
+      *ismin= False;
+  }
+  wmin_(Wmindenom, norm);
+  if (norm > qh MINdenom) {
+    if (!toporient)
+      norm= -norm;
+    *normal /= norm;
+    *norm1 /= norm;
+    if (dim == 2)
+      ; /* all done */
+    else if (dim == 3)
+      *norm2 /= norm;
+    else if (dim == 4) {
+      *norm2 /= norm;
+      *norm3 /= norm;
+    }else if (dim >4) {
+      *norm2 /= norm;
+      *norm3 /= norm;
+      for (k= dim-4, colp= normal+4; k--; )
+        *colp++ /= norm;
+    }
+  }else if (norm == 0.0) {
+    temp= sqrt (1.0/dim);
+    for (k= dim, colp= normal; k--; )
+      *colp++ = temp;
+  }else {
+    if (!toporient)
+      norm= -norm;
+    for (k= dim, colp= normal; k--; colp++) { /* k used below */
+      temp= qh_divzero (*colp, norm, qh MINdenom_1, &zerodiv);
+      if (!zerodiv)
+	*colp= temp;
+      else {
+	maxp= qh_maxabsval(normal, dim);
+	temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
+	for (k= dim, colp= normal; k--; colp++)
+	  *colp= 0.0;
+	*maxp= temp;
+	zzinc_(Znearlysingular);
+	trace0((qh ferr, "qh_normalize: norm=%2.2g too small during p%d\n", 
+	       norm, qh furthest_id));
+	return;
+      }
+    }
+  }
+} /* normalize */
+
+
+/*---------------------------------
+  
+  qh_projectpoint( point, facet, dist )
+    project point onto a facet by dist
+
+  returns:
+    returns a new point
+    
+  notes:
+    if dist= distplane(point,facet)
+      this projects point to hyperplane
+    assumes qh_memfree_() is valid for normal_size
+*/
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
+  pointT *newpoint, *np, *normal;
+  int normsize= qh normal_size,k;
+  void **freelistp; /* used !qh_NOmem */
+  
+  qh_memalloc_(normsize, freelistp, newpoint, pointT);
+  np= newpoint;
+  normal= facet->normal;
+  for(k= qh hull_dim; k--; )
+    *(np++)= *point++ - dist * *normal++;
+  return(newpoint);
+} /* projectpoint */
+
+  
+/*---------------------------------
+  
+  qh_setfacetplane( facet )
+    sets the hyperplane for a facet
+    if qh.RANDOMdist, joggles hyperplane
+
+  notes:
+    uses global buffers qh.gm_matrix and qh.gm_row
+    overwrites facet->normal if already defined
+    updates Wnewvertex if PRINTstatistics
+    sets facet->upperdelaunay if upper envelope of Delaunay triangulation
+
+  design:
+    copy vertex coordinates to qh.gm_matrix/gm_row
+    compute determinate
+    if nearzero
+      recompute determinate with gaussian elimination
+      if nearzero
+        force outside orientation by testing interior point
+*/
+void qh_setfacetplane(facetT *facet) {
+  pointT *point;
+  vertexT *vertex, **vertexp;
+  int k,i, normsize= qh normal_size, oldtrace= 0;
+  realT dist;
+  void **freelistp; /* used !qh_NOmem */
+  coordT *coord, *gmcoord;
+  pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
+  boolT nearzero= False;
+
+  zzinc_(Zsetplane);
+  if (!facet->normal)
+    qh_memalloc_(normsize, freelistp, facet->normal, coordT);
+  if (facet == qh tracefacet) {
+    oldtrace= qh IStracing;
+    qh IStracing= 5;
+    fprintf (qh ferr, "qh_setfacetplane: facet f%d created.\n", facet->id);
+    fprintf (qh ferr, "  Last point added to hull was p%d.", qh furthest_id);
+    if (zzval_(Ztotmerge))
+      fprintf(qh ferr, "  Last merge was #%d.", zzval_(Ztotmerge));
+    fprintf (qh ferr, "\n\nCurrent summary is:\n");
+      qh_printsummary (qh ferr);
+  }
+  if (qh hull_dim <= 4) {
+    i= 0;
+    if (qh RANDOMdist) {
+      gmcoord= qh gm_matrix;
+      FOREACHvertex_(facet->vertices) {
+        qh gm_row[i++]= gmcoord;
+	coord= vertex->point;
+	for (k= qh hull_dim; k--; )
+	  *(gmcoord++)= *coord++ * qh_randomfactor();
+      }	  
+    }else {
+      FOREACHvertex_(facet->vertices)
+       qh gm_row[i++]= vertex->point;
+    }
+    qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, facet->toporient,
+                facet->normal, &facet->offset, &nearzero);
+  }
+  if (qh hull_dim > 4 || nearzero) {
+    i= 0;
+    gmcoord= qh gm_matrix;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->point != point0) {
+	qh gm_row[i++]= gmcoord;
+	coord= vertex->point;
+	point= point0;
+	for(k= qh hull_dim; k--; )
+	  *(gmcoord++)= *coord++ - *point++;
+      }
+    }
+    qh gm_row[i]= gmcoord;  /* for areasimplex */
+    if (qh RANDOMdist) {
+      gmcoord= qh gm_matrix;
+      for (i= qh hull_dim-1; i--; ) {
+	for (k= qh hull_dim; k--; )
+	  *(gmcoord++) *= qh_randomfactor();
+      }
+    }
+    qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, facet->toporient,
+           	facet->normal, &facet->offset, &nearzero);
+    if (nearzero) { 
+      if (qh_orientoutside (facet)) {
+	trace0((qh ferr, "qh_setfacetplane: flipped orientation after testing interior_point during p%d\n", qh furthest_id));
+      /* this is part of using Gaussian Elimination.  For example in 5-d
+	   1 1 1 1 0
+	   1 1 1 1 1
+	   0 0 0 1 0
+	   0 1 0 0 0
+	   1 0 0 0 0
+	   norm= 0.38 0.38 -0.76 0.38 0
+	 has a determinate of 1, but g.e. after subtracting pt. 0 has
+	 0's in the diagonal, even with full pivoting.  It does work
+	 if you subtract pt. 4 instead. */
+      }
+    }
+  }
+  facet->upperdelaunay= False;
+  if (qh DELAUNAY) {
+    if (qh UPPERdelaunay) {     /* matches qh_triangulate_facet and qh.lower_threshold in qh_initbuild */
+      if (facet->normal[qh hull_dim -1] >= qh ANGLEround * qh_ZEROdelaunay)
+        facet->upperdelaunay= True;
+    }else {
+      if (facet->normal[qh hull_dim -1] > -qh ANGLEround * qh_ZEROdelaunay)
+        facet->upperdelaunay= True;
+    }
+  }
+  if (qh PRINTstatistics || qh IStracing || qh TRACElevel || qh JOGGLEmax < REALmax) {
+    qh old_randomdist= qh RANDOMdist;
+    qh RANDOMdist= False;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->point != point0) {
+	boolT istrace= False;
+	zinc_(Zdiststat);
+        qh_distplane(vertex->point, facet, &dist);
+        dist= fabs_(dist);
+        zinc_(Znewvertex);
+        wadd_(Wnewvertex, dist);
+        if (dist > wwval_(Wnewvertexmax)) {
+          wwval_(Wnewvertexmax)= dist;
+	  if (dist > qh max_outside) {
+	    qh max_outside= dist;  /* used by qh_maxouter() */
+	    if (dist > qh TRACEdist) 
+	      istrace= True;
+	  }
+	}else if (-dist > qh TRACEdist)
+	  istrace= True;
+	if (istrace) {
+	  fprintf (qh ferr, "qh_setfacetplane: ====== vertex p%d (v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
+	        qh_pointid(vertex->point), vertex->id, dist, facet->id, qh furthest_id);
+	  qh_errprint ("DISTANT", facet, NULL, NULL, NULL);
+	}
+      }
+    }
+    qh RANDOMdist= qh old_randomdist;
+  }
+  if (qh IStracing >= 3) {
+    fprintf (qh ferr, "qh_setfacetplane: f%d offset %2.2g normal: ",
+	     facet->id, facet->offset);
+    for (k=0; k < qh hull_dim; k++)
+      fprintf (qh ferr, "%2.2g ", facet->normal[k]);
+    fprintf (qh ferr, "\n");
+  }
+  if (facet == qh tracefacet)
+    qh IStracing= oldtrace;
+} /* setfacetplane */
+
+
+/*---------------------------------
+  
+  qh_sethyperplane_det( dim, rows, point0, toporient, normal, offset, nearzero )
+    given dim X dim array indexed by rows[], one row per point, 
+        toporient (flips all signs),
+        and point0 (any row)
+    set normalized hyperplane equation from oriented simplex
+
+  returns:
+    normal (normalized)
+    offset (places point0 on the hyperplane)
+    sets nearzero if hyperplane not through points
+
+  notes:
+    only defined for dim == 2..4
+    rows[] is not modified
+    solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
+    see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
+
+  derivation of 3-d minnorm
+    Goal: all vertices V_i within qh.one_merge of hyperplane
+    Plan: exactly translate the facet so that V_0 is the origin
+          exactly rotate the facet so that V_1 is on the x-axis and y_2=0.
+          exactly rotate the effective perturbation to only effect n_0
+	     this introduces a factor of sqrt(3)
+    n_0 = ((y_2-y_0)*(z_1-z_0) - (z_2-z_0)*(y_1-y_0)) / norm
+    Let M_d be the max coordinate difference
+    Let M_a be the greater of M_d and the max abs. coordinate
+    Let u be machine roundoff and distround be max error for distance computation
+    The max error for n_0 is sqrt(3) u M_a M_d / norm.  n_1 is approx. 1 and n_2 is approx. 0
+    The max error for distance of V_1 is sqrt(3) u M_a M_d M_d / norm.  Offset=0 at origin
+    Then minnorm = 1.8 u M_a M_d M_d / qh.ONEmerge
+    Note that qh.one_merge is approx. 45.5 u M_a and norm is usually about M_d M_d
+
+  derivation of 4-d minnorm
+    same as above except rotate the facet so that V_1 on x-axis and w_2, y_3, w_3=0
+     [if two vertices fixed on x-axis, can rotate the other two in yzw.]
+    n_0 = det3_(...) = y_2 det2_(z_1, w_1, z_3, w_3) = - y_2 w_1 z_3
+     [all other terms contain at least two factors nearly zero.]
+    The max error for n_0 is sqrt(4) u M_a M_d M_d / norm
+    Then minnorm = 2 u M_a M_d M_d M_d / qh.ONEmerge
+    Note that qh.one_merge is approx. 82 u M_a and norm is usually about M_d M_d M_d
+*/
+void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, 
+          boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
+  realT maxround, dist;
+  int i;
+  pointT *point;
+
+
+  if (dim == 2) {
+    normal[0]= dY(1,0);
+    normal[1]= dX(0,1);
+    qh_normalize2 (normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
+    *nearzero= False;  /* since nearzero norm => incident points */
+  }else if (dim == 3) {
+    normal[0]= det2_(dY(2,0), dZ(2,0),
+		     dY(1,0), dZ(1,0));
+    normal[1]= det2_(dX(1,0), dZ(1,0),
+		     dX(2,0), dZ(2,0));
+    normal[2]= det2_(dX(2,0), dY(2,0),
+		     dX(1,0), dY(1,0));
+    qh_normalize2 (normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+	       + point0[2]*normal[2]);
+    maxround= qh DISTround;
+    for (i=dim; i--; ) {
+      point= rows[i];
+      if (point != point0) {
+        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+	       + point[2]*normal[2]);
+        if (dist > maxround || dist < -maxround) {
+  	  *nearzero= True;
+	  break;
+	}
+      }
+    }
+  }else if (dim == 4) {
+    normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
+			dY(1,0), dZ(1,0), dW(1,0),
+			dY(3,0), dZ(3,0), dW(3,0));
+    normal[1]=   det3_(dX(2,0), dZ(2,0), dW(2,0),
+		        dX(1,0), dZ(1,0), dW(1,0),
+		        dX(3,0), dZ(3,0), dW(3,0));
+    normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
+			dX(1,0), dY(1,0), dW(1,0),
+			dX(3,0), dY(3,0), dW(3,0));
+    normal[3]=   det3_(dX(2,0), dY(2,0), dZ(2,0),
+		        dX(1,0), dY(1,0), dZ(1,0),
+		        dX(3,0), dY(3,0), dZ(3,0));
+    qh_normalize2 (normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+	       + point0[2]*normal[2] + point0[3]*normal[3]);
+    maxround= qh DISTround;
+    for (i=dim; i--; ) {
+      point= rows[i];
+      if (point != point0) {
+        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+	       + point[2]*normal[2] + point[3]*normal[3]);
+        if (dist > maxround || dist < -maxround) {
+  	  *nearzero= True;
+	  break;
+	}
+      }
+    }
+  }
+  if (*nearzero) {
+    zzinc_(Zminnorm);
+    trace0((qh ferr, "qh_sethyperplane_det: degenerate norm during p%d.\n", qh furthest_id));
+    zzinc_(Znearlysingular);
+  }
+} /* sethyperplane_det */
+
+
+/*---------------------------------
+  
+  qh_sethyperplane_gauss( dim, rows, point0, toporient, normal, offset, nearzero )
+    given (dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
+    set normalized hyperplane equation from oriented simplex
+
+  returns:
+    normal (normalized)
+    offset (places point0 on the hyperplane)
+
+  notes:
+    if nearzero
+      orientation may be incorrect because of incorrect sign flips in gausselim
+    solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1] 
+        or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0] 
+    i.e., N is normal to the hyperplane, and the unnormalized
+        distance to [0 .. 1] is either 1 or   0
+
+  design:
+    perform gaussian elimination
+    flip sign for negative values
+    perform back substitution 
+    normalize result
+    compute offset
+*/
+void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, 
+		boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
+  coordT *pointcoord, *normalcoef;
+  int k;
+  boolT sign= toporient, nearzero2= False;
+  
+  qh_gausselim(rows, dim-1, dim, &sign, nearzero);
+  for(k= dim-1; k--; ) {
+    if ((rows[k])[k] < 0)
+      sign ^= 1;
+  }
+  if (*nearzero) {
+    zzinc_(Znearlysingular);
+    trace0((qh ferr, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh furthest_id));
+    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
+  }else {
+    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
+    if (nearzero2) {
+      zzinc_(Znearlysingular);
+      trace0((qh ferr, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh furthest_id));
+    }
+  }
+  if (nearzero2)
+    *nearzero= True;
+  qh_normalize2(normal, dim, True, NULL, NULL);
+  pointcoord= point0;
+  normalcoef= normal;
+  *offset= -(*pointcoord++ * *normalcoef++);
+  for(k= dim-1; k--; )
+    *offset -= *pointcoord++ * *normalcoef++;
+} /* sethyperplane_gauss */
+
+  
+

Added: trunk/scipy/spatial/qhull/src/geom.h
===================================================================
--- trunk/scipy/spatial/qhull/src/geom.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/geom.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,177 @@
+/*
  ---------------------------------
+
+  geom.h 
+    header file for geometric routines
+
+   see qh-geom.htm and geom.c
+
+   copyright (c) 1993-2003 The Geometry Center        
+*/
+
+#ifndef qhDEFgeom
+#define qhDEFgeom 1
+
+/* ============ -macros- ======================== */
+
+/*----------------------------------
+   
+  fabs_(a)
+    returns the absolute value of a
+*/
+#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
+               
+/*----------------------------------
+  
+  fmax_(a,b)
+    returns the maximum value of a and b
+*/
+#define fmax_( a,b )  ( ( a ) < ( b ) ? ( b ) : ( a ) )
+
+/*----------------------------------
+
+  fmin_(a,b)
+    returns the minimum value of a and b
+*/
+#define fmin_( a,b )  ( ( a ) > ( b ) ? ( b ) : ( a ) )
+
+/*----------------------------------
+
+  maximize_(maxval, val)
+    set maxval to val if val is greater than maxval
+*/
+#define maximize_( maxval, val ) {if (( maxval ) < ( val )) ( maxval )= ( val );}
+
+/*----------------------------------
+
+  minimize_(minval, val)
+    set minval to val if val is less than minval
+*/
+#define minimize_( minval, val ) {if (( minval ) > ( val )) ( minval )= ( val );}
+
+/*----------------------------------
+
+  det2_(a1, a2,     
+        b1, b2)
+  
+    compute a 2-d determinate
+*/
+#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
+
+/*----------------------------------
+  
+  det3_(a1, a2, a3,    
+       b1, b2, b3,
+       c1, c2, c3)
+  
+    compute a 3-d determinate
+*/
+#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
+                - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
+
+/*----------------------------------
+  
+  dX( p1, p2 )
+  dY( p1, p2 )
+  dZ( p1, p2 )
+  
+    given two indices into rows[],
+
+    compute the difference between X, Y, or Z coordinates
+*/
+#define dX( p1,p2 )  ( *( rows[p1] ) - *( rows[p2] ))
+#define dY( p1,p2 )  ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
+#define dZ( p1,p2 )  ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
+#define dW( p1,p2 )  ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
+
+/*============= prototypes in alphabetical order, infrequent at end ======= */
+
+void    qh_backnormal (realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
+void	qh_distplane (pointT *point, facetT *facet, realT *dist);
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+		     boolT bestoutside, boolT isnewfacets, boolT noupper,
+		     realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbesthorizon (boolT ischeckmax, pointT *point, 
+	             facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
+facetT *qh_findbestnew (pointT *point, facetT *startfacet, realT *dist, 
+		     boolT bestoutside, boolT *isoutside, int *numpart);
+void 	qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
+realT   qh_getangle(pointT *vect1, pointT *vect2);
+pointT *qh_getcenter(setT *vertices);
+pointT *qh_getcentrum(facetT *facet);
+realT   qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
+void    qh_normalize (coordT *normal, int dim, boolT toporient);
+void    qh_normalize2 (coordT *normal, int dim, boolT toporient, 
+            realT *minnorm, boolT *ismin);
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
+
+void    qh_setfacetplane(facetT *newfacets);
+void 	qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, 
+              boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
+void 	qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, 
+	     boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
+boolT   qh_sharpnewfacets (void);
+
+/*========= infrequently used code in geom2.c =============*/
+
+
+coordT *qh_copypoints (coordT *points, int numpoints, int dimension);
+void    qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
+realT 	qh_determinant (realT **rows, int dim, boolT *nearzero);
+realT   qh_detjoggle (pointT *points, int numpoints, int dimension);
+void    qh_detroundoff (void);
+realT   qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
+realT   qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp);
+realT   qh_distround (int dimension, realT maxabs, realT maxsumabs);
+realT   qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
+realT   qh_facetarea (facetT *facet);
+realT   qh_facetarea_simplex (int dim, coordT *apex, setT *vertices, 
+          vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset);
+pointT *qh_facetcenter (setT *vertices);
+facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
+void    qh_getarea (facetT *facetlist);
+boolT   qh_gram_schmidt(int dim, realT **rows);
+boolT   qh_inthresholds (coordT *normal, realT *angle);
+void    qh_joggleinput (void);
+realT  *qh_maxabsval (realT *normal, int dim);
+setT   *qh_maxmin(pointT *points, int numpoints, int dimension);
+realT   qh_maxouter (void);
+void    qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
+realT   qh_minabsval (realT *normal, int dim);
+int     qh_mindiff (realT *vecA, realT *vecB, int dim);
+boolT   qh_orientoutside (facetT *facet);
+void    qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
+coordT  qh_pointdist(pointT *point1, pointT *point2, int dim);
+void    qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol);
+void    qh_printpoints (FILE *fp, char *string, setT *points);
+void    qh_projectinput (void);
+void 	qh_projectpoints (signed char *project, int n, realT *points, 
+             int numpoints, int dim, realT *newpoints, int newdim);
+int     qh_rand( void);
+void    qh_srand( int seed);
+realT   qh_randomfactor (void);
+void    qh_randommatrix (realT *buffer, int dim, realT **row);
+void    qh_rotateinput (realT **rows);
+void    qh_rotatepoints (realT *points, int numpoints, int dim, realT **rows);
+void    qh_scaleinput (void);
+void    qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
+		   coordT high, coordT newhigh);
+void 	qh_scalepoints (pointT *points, int numpoints, int dim,
+  		realT *newlows, realT *newhighs);
+boolT   qh_sethalfspace (int dim, coordT *coords, coordT **nextp, 
+              coordT *normal, coordT *offset, coordT *feasible);
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
+pointT *qh_voronoi_center (int dim, setT *points);
+
+#endif /* qhDEFgeom */
+
+
+

Added: trunk/scipy/spatial/qhull/src/geom2.c
===================================================================
--- trunk/scipy/spatial/qhull/src/geom2.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/geom2.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,2160 @@
+/*
  ---------------------------------
+
+
+   geom2.c 
+   infrequently used geometric routines of qhull
+
+   see qh-geom.htm and geom.h
+
+   copyright (c) 1993-2003 The Geometry Center        
+
+   frequently used code goes into geom.c
+*/
+   
+#include "qhull_a.h"
+   
+/*================== functions in alphabetic order ============*/
+
+/*---------------------------------
+
+  qh_copypoints( points, numpoints, dimension)
+    return malloc'd copy of points
+*/
+coordT *qh_copypoints (coordT *points, int numpoints, int dimension) {
+  int size;
+  coordT *newpoints;
+
+  size= numpoints * dimension * sizeof(coordT);
+  if (!(newpoints=(coordT*)malloc(size))) {
+    fprintf(qh ferr, "qhull error: insufficient memory to copy %d points\n",
+        numpoints);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  memcpy ((char *)newpoints, (char *)points, size);
+  return newpoints;
+} /* copypoints */
+
+/*---------------------------------
+  
+  qh_crossproduct( dim, vecA, vecB, vecC )
+    crossproduct of 2 dim vectors
+    C= A x B
+  
+  notes:
+    from Glasner, Graphics Gems I, p. 639
+    only defined for dim==3
+*/
+void qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
+
+  if (dim == 3) {
+    vecC[0]=   det2_(vecA[1], vecA[2],
+		     vecB[1], vecB[2]);
+    vecC[1]= - det2_(vecA[0], vecA[2],
+		     vecB[0], vecB[2]);
+    vecC[2]=   det2_(vecA[0], vecA[1],
+		     vecB[0], vecB[1]);
+  }
+} /* vcross */
+
+/*---------------------------------
+  
+  qh_determinant( rows, dim, nearzero )
+    compute signed determinant of a square matrix
+    uses qh.NEARzero to test for degenerate matrices
+
+  returns:
+    determinant
+    overwrites rows and the matrix
+    if dim == 2 or 3
+      nearzero iff determinant < qh NEARzero[dim-1]
+      (not quite correct, not critical)
+    if dim >= 4
+      nearzero iff diagonal[k] < qh NEARzero[k]
+*/
+realT qh_determinant (realT **rows, int dim, boolT *nearzero) {
+  realT det=0;
+  int i;
+  boolT sign= False;
+
+  *nearzero= False;
+  if (dim < 2) {
+    fprintf (qh ferr, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }else if (dim == 2) {
+    det= det2_(rows[0][0], rows[0][1],
+		 rows[1][0], rows[1][1]);
+    if (fabs_(det) < qh NEARzero[1])  /* not really correct, what should this be? */
+      *nearzero= True;
+  }else if (dim == 3) {
+    det= det3_(rows[0][0], rows[0][1], rows[0][2],
+		 rows[1][0], rows[1][1], rows[1][2],
+		 rows[2][0], rows[2][1], rows[2][2]);
+    if (fabs_(det) < qh NEARzero[2])  /* not really correct, what should this be? */
+      *nearzero= True;
+  }else {	
+    qh_gausselim(rows, dim, dim, &sign, nearzero);  /* if nearzero, diagonal still ok*/
+    det= 1.0;
+    for (i= dim; i--; )
+      det *= (rows[i])[i];
+    if (sign)
+      det= -det;
+  }
+  return det;
+} /* determinant */
+
+/*---------------------------------
+  
+  qh_detjoggle( points, numpoints, dimension )
+    determine default max joggle for point array
+      as qh_distround * qh_JOGGLEdefault
+
+  returns:
+    initial value for JOGGLEmax from points and REALepsilon
+
+  notes:
+    computes DISTround since qh_maxmin not called yet
+    if qh SCALElast, last dimension will be scaled later to MAXwidth
+
+    loop duplicated from qh_maxmin
+*/
+realT qh_detjoggle (pointT *points, int numpoints, int dimension) {
+  realT abscoord, distround, joggle, maxcoord, mincoord;
+  pointT *point, *pointtemp;
+  realT maxabs= -REALmax;
+  realT sumabs= 0;
+  realT maxwidth= 0;
+  int k;
+
+  for (k= 0; k < dimension; k++) {
+    if (qh SCALElast && k == dimension-1)
+      abscoord= maxwidth;
+    else if (qh DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
+      abscoord= 2 * maxabs * maxabs;  /* may be low by qh hull_dim/2 */
+    else {
+      maxcoord= -REALmax;
+      mincoord= REALmax;
+      FORALLpoint_(points, numpoints) {
+	maximize_(maxcoord, point[k]);
+        minimize_(mincoord, point[k]);
+      }
+      maximize_(maxwidth, maxcoord-mincoord);
+      abscoord= fmax_(maxcoord, -mincoord);
+    }
+    sumabs += abscoord;
+    maximize_(maxabs, abscoord);
+  } /* for k */
+  distround= qh_distround (qh hull_dim, maxabs, sumabs);
+  joggle= distround * qh_JOGGLEdefault;
+  maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
+  trace2((qh ferr, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
+  return joggle;
+} /* detjoggle */
+
+/*---------------------------------
+  
+  qh_detroundoff()
+    determine maximum roundoff errors from
+      REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord, 
+      qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
+
+    accounts for qh.SETroundoff, qh.RANDOMdist, qh MERGEexact
+      qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
+      qh.postmerge_centrum, qh.MINoutside,
+      qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
+
+  returns:
+    sets qh.DISTround, etc. (see below)
+    appends precision constants to qh.qhull_options
+
+  see:
+    qh_maxmin() for qh.NEARzero
+
+  design:
+    determine qh.DISTround for distance computations
+    determine minimum denominators for qh_divzero
+    determine qh.ANGLEround for angle computations
+    adjust qh.premerge_cos,... for roundoff error
+    determine qh.ONEmerge for maximum error due to a single merge
+    determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
+      qh.MINoutside, qh.WIDEfacet
+    initialize qh.max_vertex and qh.minvertex
+*/
+void qh_detroundoff (void) {
+
+  qh_option ("_max-width", NULL, &qh MAXwidth);
+  if (!qh SETroundoff) {
+    qh DISTround= qh_distround (qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
+    if (qh RANDOMdist)
+      qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
+    qh_option ("Error-roundoff", NULL, &qh DISTround);
+  }
+  qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
+  qh MINdenom_1_2= sqrt (qh MINdenom_1 * qh hull_dim) ;  /* if will be normalized */
+  qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
+                                              /* for inner product */
+  qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
+  if (qh RANDOMdist)
+    qh ANGLEround += qh RANDOMfactor;
+  if (qh premerge_cos < REALmax/2) {
+    qh premerge_cos -= qh ANGLEround;
+    if (qh RANDOMdist) 
+      qh_option ("Angle-premerge-with-random", NULL, &qh premerge_cos);
+  }
+  if (qh postmerge_cos < REALmax/2) {
+    qh postmerge_cos -= qh ANGLEround;
+    if (qh RANDOMdist)
+      qh_option ("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
+  }
+  qh premerge_centrum += 2 * qh DISTround;    /*2 for centrum and distplane()*/
+  qh postmerge_centrum += 2 * qh DISTround;
+  if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
+    qh_option ("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
+  if (qh RANDOMdist && qh POSTmerge)
+    qh_option ("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
+  { /* compute ONEmerge, max vertex offset for merging simplicial facets */
+    realT maxangle= 1.0, maxrho;
+    
+    minimize_(maxangle, qh premerge_cos);
+    minimize_(maxangle, qh postmerge_cos);
+    /* max diameter * sin theta + DISTround for vertex to its hyperplane */
+    qh ONEmerge= sqrt (qh hull_dim) * qh MAXwidth *
+      sqrt (1.0 - maxangle * maxangle) + qh DISTround;  
+    maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
+    maximize_(qh ONEmerge, maxrho);
+    maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
+    maximize_(qh ONEmerge, maxrho);
+    if (qh MERGING)
+      qh_option ("_one-merge", NULL, &qh ONEmerge);
+  }
+  qh NEARinside= qh ONEmerge * qh_RATIOnearinside; /* only used if qh KEEPnearinside */
+  if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
+    realT maxdist;	       /* adjust qh.NEARinside for joggle */
+    qh KEEPnearinside= True;   
+    maxdist= sqrt (qh hull_dim) * qh JOGGLEmax + qh DISTround;
+    maxdist= 2*maxdist;        /* vertex and coplanar point can joggle in opposite directions */
+    maximize_(qh NEARinside, maxdist);  /* must agree with qh_nearcoplanar() */
+  }
+  if (qh KEEPnearinside)
+    qh_option ("_near-inside", NULL, &qh NEARinside);
+  if (qh JOGGLEmax < qh DISTround) {
+    fprintf (qh ferr, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
+         qh JOGGLEmax, qh DISTround);
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  if (qh MINvisible > REALmax/2) {
+    if (!qh MERGING)
+      qh MINvisible= qh DISTround;
+    else if (qh hull_dim <= 3)
+      qh MINvisible= qh premerge_centrum;
+    else
+      qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
+    if (qh APPROXhull && qh MINvisible > qh MINoutside)
+      qh MINvisible= qh MINoutside;
+    qh_option ("Visible-distance", NULL, &qh MINvisible);
+  }
+  if (qh MAXcoplanar > REALmax/2) {
+    qh MAXcoplanar= qh MINvisible;
+    qh_option ("U-coplanar-distance", NULL, &qh MAXcoplanar);
+  }
+  if (!qh APPROXhull) {             /* user may specify qh MINoutside */
+    qh MINoutside= 2 * qh MINvisible;
+    if (qh premerge_cos < REALmax/2) 
+      maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
+    qh_option ("Width-outside", NULL, &qh MINoutside);
+  }
+  qh WIDEfacet= qh MINoutside;
+  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar); 
+  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible); 
+  qh_option ("_wide-facet", NULL, &qh WIDEfacet);
+  if (qh MINvisible > qh MINoutside + 3 * REALepsilon 
+  && !qh BESToutside && !qh FORCEoutput)
+    fprintf (qh ferr, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g.  Flipped facets are likely.\n",
+	     qh MINvisible, qh MINoutside);
+  qh max_vertex= qh DISTround;
+  qh min_vertex= -qh DISTround;
+  /* numeric constants reported in printsummary */
+} /* detroundoff */
+
+/*---------------------------------
+  
+  qh_detsimplex( apex, points, dim, nearzero )
+    compute determinant of a simplex with point apex and base points
+
+  returns:
+     signed determinant and nearzero from qh_determinant
+
+  notes:
+     uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
+
+  design:
+    construct qm_matrix by subtracting apex from points
+    compute determinate
+*/
+realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
+  pointT *coorda, *coordp, *gmcoord, *point, **pointp;
+  coordT **rows;
+  int k,  i=0;
+  realT det;
+
+  zinc_(Zdetsimplex);
+  gmcoord= qh gm_matrix;
+  rows= qh gm_row;
+  FOREACHpoint_(points) {
+    if (i == dim)
+      break;
+    rows[i++]= gmcoord;
+    coordp= point;
+    coorda= apex;
+    for (k= dim; k--; )
+      *(gmcoord++)= *coordp++ - *coorda++;
+  }
+  if (i < dim) {
+    fprintf (qh ferr, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n", 
+               i, dim);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  det= qh_determinant (rows, dim, nearzero);
+  trace2((qh ferr, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
+	  det, qh_pointid(apex), dim, *nearzero)); 
+  return det;
+} /* detsimplex */
+
+/*---------------------------------
+  
+  qh_distnorm( dim, point, normal, offset )
+    return distance from point to hyperplane at normal/offset
+
+  returns:
+    dist
+  
+  notes:  
+    dist > 0 if point is outside of hyperplane
+  
+  see:
+    qh_distplane in geom.c
+*/
+realT qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp) {
+  coordT *normalp= normal, *coordp= point;
+  realT dist;
+  int k;
+
+  dist= *offsetp;
+  for (k= dim; k--; )
+    dist += *(coordp++) * *(normalp++);
+  return dist;
+} /* distnorm */
+
+/*---------------------------------
+
+  qh_distround ( dimension, maxabs, maxsumabs )
+    compute maximum round-off error for a distance computation
+      to a normalized hyperplane
+    maxabs is the maximum absolute value of a coordinate
+    maxsumabs is the maximum possible sum of absolute coordinate values
+
+  returns:
+    max dist round for REALepsilon
+
+  notes:
+    calculate roundoff error according to
+    Lemma 3.2-1 of Golub and van Loan "Matrix Computation"
+    use sqrt(dim) since one vector is normalized
+      or use maxsumabs since one vector is < 1
+*/
+realT qh_distround (int dimension, realT maxabs, realT maxsumabs) {
+  realT maxdistsum, maxround;
+
+  maxdistsum= sqrt (dimension) * maxabs;
+  minimize_( maxdistsum, maxsumabs);
+  maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
+              /* adds maxabs for offset */
+  trace4((qh ferr, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
+	         maxround, maxabs, maxsumabs, maxdistsum));
+  return maxround;
+} /* distround */
+
+/*---------------------------------
+  
+  qh_divzero( numer, denom, mindenom1, zerodiv )
+    divide by a number that's nearly zero
+    mindenom1= minimum denominator for dividing into 1.0
+
+  returns:
+    quotient
+    sets zerodiv and returns 0.0 if it would overflow
+  
+  design:
+    if numer is nearly zero and abs(numer) < abs(denom)
+      return numer/denom
+    else if numer is nearly zero
+      return 0 and zerodiv
+    else if denom/numer non-zero
+      return numer/denom
+    else
+      return 0 and zerodiv
+*/
+realT qh_divzero (realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
+  realT temp, numerx, denomx;
+  
+
+  if (numer < mindenom1 && numer > -mindenom1) {
+    numerx= fabs_(numer);
+    denomx= fabs_(denom);
+    if (numerx < denomx) {
+      *zerodiv= False;
+      return numer/denom;
+    }else {
+      *zerodiv= True;
+      return 0.0;
+    }
+  }
+  temp= denom/numer;
+  if (temp > mindenom1 || temp < -mindenom1) {
+    *zerodiv= False;
+    return numer/denom;
+  }else {
+    *zerodiv= True;
+    return 0.0;
+  }
+} /* divzero */
+  
+
+/*---------------------------------
+
+  qh_facetarea( facet )
+    return area for a facet
+  
+  notes:
+    if non-simplicial, 
+      uses centrum to triangulate facet and sums the projected areas.
+    if (qh DELAUNAY),
+      computes projected area instead for last coordinate
+    assumes facet->normal exists
+    projecting tricoplanar facets to the hyperplane does not appear to make a difference
+  
+  design:
+    if simplicial
+      compute area
+    else
+      for each ridge
+        compute area from centrum to ridge
+    negate area if upper Delaunay facet
+*/
+realT qh_facetarea (facetT *facet) {
+  vertexT *apex;
+  pointT *centrum;
+  realT area= 0.0;
+  ridgeT *ridge, **ridgep;
+
+  if (facet->simplicial) {
+    apex= SETfirstt_(facet->vertices, vertexT);
+    area= qh_facetarea_simplex (qh hull_dim, apex->point, facet->vertices, 
+                    apex, facet->toporient, facet->normal, &facet->offset);
+  }else {
+    if (qh CENTERtype == qh_AScentrum)
+      centrum= facet->center;
+    else
+      centrum= qh_getcentrum (facet);
+    FOREACHridge_(facet->ridges) 
+      area += qh_facetarea_simplex (qh hull_dim, centrum, ridge->vertices, 
+                 NULL, (ridge->top == facet),  facet->normal, &facet->offset);
+    if (qh CENTERtype != qh_AScentrum)
+      qh_memfree (centrum, qh normal_size);
+  }
+  if (facet->upperdelaunay && qh DELAUNAY)
+    area= -area;  /* the normal should be [0,...,1] */
+  trace4((qh ferr, "qh_facetarea: f%d area %2.2g\n", facet->id, area)); 
+  return area;
+} /* facetarea */
+
+/*---------------------------------
+
+  qh_facetarea_simplex( dim, apex, vertices, notvertex, toporient, normal, offset )
+    return area for a simplex defined by 
+      an apex, a base of vertices, an orientation, and a unit normal
+    if simplicial or tricoplanar facet, 
+      notvertex is defined and it is skipped in vertices
+  
+  returns:
+    computes area of simplex projected to plane [normal,offset]
+    returns 0 if vertex too far below plane (qh WIDEfacet)
+      vertex can't be apex of tricoplanar facet
+  
+  notes:
+    if (qh DELAUNAY),
+      computes projected area instead for last coordinate
+    uses qh gm_matrix/gm_row and qh hull_dim
+    helper function for qh_facetarea
+  
+  design:
+    if Notvertex
+      translate simplex to apex
+    else
+      project simplex to normal/offset
+      translate simplex to apex
+    if Delaunay
+      set last row/column to 0 with -1 on diagonal 
+    else
+      set last row to Normal
+    compute determinate
+    scale and flip sign for area
+*/
+realT qh_facetarea_simplex (int dim, coordT *apex, setT *vertices, 
+        vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset) {
+  pointT *coorda, *coordp, *gmcoord;
+  coordT **rows, *normalp;
+  int k,  i=0;
+  realT area, dist;
+  vertexT *vertex, **vertexp;
+  boolT nearzero;
+
+  gmcoord= qh gm_matrix;
+  rows= qh gm_row;
+  FOREACHvertex_(vertices) {
+    if (vertex == notvertex)
+      continue;
+    rows[i++]= gmcoord;
+    coorda= apex;
+    coordp= vertex->point;
+    normalp= normal;
+    if (notvertex) {
+      for (k= dim; k--; )
+	*(gmcoord++)= *coordp++ - *coorda++;
+    }else {
+      dist= *offset;
+      for (k= dim; k--; )
+	dist += *coordp++ * *normalp++;
+      if (dist < -qh WIDEfacet) {
+	zinc_(Znoarea);
+	return 0.0;
+      }
+      coordp= vertex->point;
+      normalp= normal;
+      for (k= dim; k--; )
+	*(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
+    }
+  }
+  if (i != dim-1) {
+    fprintf (qh ferr, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n", 
+               i, dim);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  rows[i]= gmcoord;
+  if (qh DELAUNAY) {
+    for (i= 0; i < dim-1; i++)
+      rows[i][dim-1]= 0.0;
+    for (k= dim; k--; )
+      *(gmcoord++)= 0.0;
+    rows[dim-1][dim-1]= -1.0;
+  }else {
+    normalp= normal;
+    for (k= dim; k--; )
+      *(gmcoord++)= *normalp++;
+  }
+  zinc_(Zdetsimplex);
+  area= qh_determinant (rows, dim, &nearzero);
+  if (toporient)
+    area= -area;
+  area *= qh AREAfactor;
+  trace4((qh ferr, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
+	  area, qh_pointid(apex), toporient, nearzero)); 
+  return area;
+} /* facetarea_simplex */
+
+/*---------------------------------
+  
+  qh_facetcenter( vertices )
+    return Voronoi center (Voronoi vertex) for a facet's vertices
+
+  returns:
+    return temporary point equal to the center
+    
+  see:
+    qh_voronoi_center()
+*/
+pointT *qh_facetcenter (setT *vertices) {
+  setT *points= qh_settemp (qh_setsize (vertices));
+  vertexT *vertex, **vertexp;
+  pointT *center;
+  
+  FOREACHvertex_(vertices) 
+    qh_setappend (&points, vertex->point);
+  center= qh_voronoi_center (qh hull_dim-1, points);
+  qh_settempfree (&points);
+  return center;
+} /* facetcenter */
+
+/*---------------------------------
+  
+  qh_findgooddist( point, facetA, dist, facetlist )
+    find best good facet visible for point from facetA
+    assumes facetA is visible from point
+
+  returns:
+    best facet, i.e., good facet that is furthest from point
+      distance to best facet
+      NULL if none
+      
+    moves good, visible facets (and some other visible facets)
+      to end of qh facet_list
+
+  notes:
+    uses qh visit_id
+
+  design:
+    initialize bestfacet if facetA is good
+    move facetA to end of facetlist
+    for each facet on facetlist
+      for each unvisited neighbor of facet
+        move visible neighbors to end of facetlist
+        update best good neighbor
+        if no good neighbors, update best facet
+*/
+facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, 
+               facetT **facetlist) {
+  realT bestdist= -REALmax, dist;
+  facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
+  boolT goodseen= False;  
+
+  if (facetA->good) {
+    zinc_(Zcheckpart);  /* calls from check_bestdist occur after print stats */
+    qh_distplane (point, facetA, &bestdist);
+    bestfacet= facetA;
+    goodseen= True;
+  }
+  qh_removefacet (facetA);
+  qh_appendfacet (facetA);
+  *facetlist= facetA;
+  facetA->visitid= ++qh visit_id;
+  FORALLfacet_(*facetlist) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == qh visit_id)
+        continue;
+      neighbor->visitid= qh visit_id;
+      if (goodseen && !neighbor->good)
+        continue;
+      zinc_(Zcheckpart); 
+      qh_distplane (point, neighbor, &dist);
+      if (dist > 0) {
+        qh_removefacet (neighbor);
+        qh_appendfacet (neighbor);
+        if (neighbor->good) {
+          goodseen= True;
+          if (dist > bestdist) {
+            bestdist= dist;
+            bestfacet= neighbor;
+          }
+        }
+      }
+    }
+  }
+  if (bestfacet) {
+    *distp= bestdist;
+    trace2((qh ferr, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
+      qh_pointid(point), bestdist, bestfacet->id));
+    return bestfacet;
+  }
+  trace4((qh ferr, "qh_findgooddist: no good facet for p%d above f%d\n", 
+      qh_pointid(point), facetA->id));
+  return NULL;
+}  /* findgooddist */
+    
+/*---------------------------------
+  
+  qh_getarea( facetlist )
+    set area of all facets in facetlist
+    collect statistics
+
+  returns:
+    sets qh totarea/totvol to total area and volume of convex hull
+    for Delaunay triangulation, computes projected area of the lower or upper hull
+      ignores upper hull if qh ATinfinity
+  
+  notes:
+    could compute outer volume by expanding facet area by rays from interior
+    the following attempt at perpendicular projection underestimated badly:
+      qh.totoutvol += (-dist + facet->maxoutside + qh DISTround) 
+                            * area/ qh hull_dim;
+  design:
+    for each facet on facetlist
+      compute facet->area
+      update qh.totarea and qh.totvol
+*/
+void qh_getarea (facetT *facetlist) {
+  realT area;
+  realT dist;
+  facetT *facet;
+
+  if (qh REPORTfreq)
+    fprintf (qh ferr, "computing area of each facet and volume of the convex hull\n");
+  else 
+    trace1((qh ferr, "qh_getarea: computing volume and area for each facet\n"));
+  qh totarea= qh totvol= 0.0;
+  FORALLfacet_(facetlist) {
+    if (!facet->normal)
+      continue;
+    if (facet->upperdelaunay && qh ATinfinity)
+      continue;
+    facet->f.area= area= qh_facetarea (facet);
+    facet->isarea= True;
+    if (qh DELAUNAY) {
+      if (facet->upperdelaunay == qh UPPERdelaunay)
+	qh totarea += area;
+    }else {
+      qh totarea += area;
+      qh_distplane (qh interior_point, facet, &dist);
+      qh totvol += -dist * area/ qh hull_dim;
+    }
+    if (qh PRINTstatistics) {
+      wadd_(Wareatot, area);
+      wmax_(Wareamax, area);
+      wmin_(Wareamin, area);
+    }
+  }
+} /* getarea */
+
+/*---------------------------------
+  
+  qh_gram_schmidt( dim, row )
+    implements Gram-Schmidt orthogonalization by rows
+
+  returns:
+    false if zero norm
+    overwrites rows[dim][dim]
+
+  notes:
+    see Golub & van Loan Algorithm 6.2-2
+    overflow due to small divisors not handled
+
+  design:
+    for each row
+      compute norm for row
+      if non-zero, normalize row
+      for each remaining rowA
+        compute inner product of row and rowA
+        reduce rowA by row * inner product
+*/
+boolT qh_gram_schmidt(int dim, realT **row) {
+  realT *rowi, *rowj, norm;
+  int i, j, k;
+  
+  for(i=0; i < dim; i++) {
+    rowi= row[i];
+    for (norm= 0.0, k= dim; k--; rowi++)
+      norm += *rowi * *rowi;
+    norm= sqrt(norm);
+    wmin_(Wmindenom, norm);
+    if (norm == 0.0)  /* either 0 or overflow due to sqrt */
+      return False;
+    for(k= dim; k--; )
+      *(--rowi) /= norm;  
+    for(j= i+1; j < dim; j++) {
+      rowj= row[j];
+      for(norm= 0.0, k=dim; k--; )
+	norm += *rowi++ * *rowj++;
+      for(k=dim; k--; )
+	*(--rowj) -= *(--rowi) * norm;
+    }
+  }
+  return True;
+} /* gram_schmidt */
+
+
+/*---------------------------------
+  
+  qh_inthresholds( normal, angle )
+    return True if normal within qh.lower_/upper_threshold
+
+  returns:
+    estimate of angle by summing of threshold diffs
+      angle may be NULL
+      smaller "angle" is better
+  
+  notes:
+    invalid if qh.SPLITthresholds
+
+  see:
+    qh.lower_threshold in qh_initbuild()
+    qh_initthresholds()
+
+  design:
+    for each dimension
+      test threshold
+*/
+boolT qh_inthresholds (coordT *normal, realT *angle) {
+  boolT within= True;
+  int k;
+  realT threshold;
+
+  if (angle)
+    *angle= 0.0;
+  for(k= 0; k < qh hull_dim; k++) {
+    threshold= qh lower_threshold[k];
+    if (threshold > -REALmax/2) {
+      if (normal[k] < threshold)
+        within= False;
+      if (angle) {
+	threshold -= normal[k];
+	*angle += fabs_(threshold);
+      }
+    }
+    if (qh upper_threshold[k] < REALmax/2) {
+      threshold= qh upper_threshold[k];
+      if (normal[k] > threshold)
+        within= False;
+      if (angle) {
+	threshold -= normal[k];
+	*angle += fabs_(threshold);
+      }
+    }
+  }
+  return within;
+} /* inthresholds */
+    
+
+/*---------------------------------
+  
+  qh_joggleinput()
+    randomly joggle input to Qhull by qh.JOGGLEmax
+    initial input is qh.first_point/qh.num_points of qh.hull_dim
+      repeated calls use qh.input_points/qh.num_points
+ 
+  returns:
+    joggles points at qh.first_point/qh.num_points
+    copies data to qh.input_points/qh.input_malloc if first time
+    determines qh.JOGGLEmax if it was zero
+    if qh.DELAUNAY
+      computes the Delaunay projection of the joggled points
+
+  notes:
+    if qh.DELAUNAY, unnecessarily joggles the last coordinate
+    the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
+
+  design:
+    if qh.DELAUNAY
+      set qh.SCALElast for reduced precision errors
+    if first call
+      initialize qh.input_points to the original input points
+      if qh.JOGGLEmax == 0
+        determine default qh.JOGGLEmax
+    else
+      increase qh.JOGGLEmax according to qh.build_cnt
+    joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
+    if qh.DELAUNAY
+      sets the Delaunay projection
+*/
+void qh_joggleinput (void) {
+  int size, i, seed;
+  coordT *coordp, *inputp;
+  realT randr, randa, randb;
+
+  if (!qh input_points) { /* first call */
+    qh input_points= qh first_point;
+    qh input_malloc= qh POINTSmalloc;
+    size= qh num_points * qh hull_dim * sizeof(coordT);
+    if (!(qh first_point=(coordT*)malloc(size))) {
+      fprintf(qh ferr, "qhull error: insufficient memory to joggle %d points\n",
+          qh num_points);
+      qh_errexit(qh_ERRmem, NULL, NULL);
+    }
+    qh POINTSmalloc= True;
+    if (qh JOGGLEmax == 0.0) {
+      qh JOGGLEmax= qh_detjoggle (qh input_points, qh num_points, qh hull_dim);
+      qh_option ("QJoggle", NULL, &qh JOGGLEmax);
+    }
+  }else {                 /* repeated call */
+    if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
+      if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
+	realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
+	if (qh JOGGLEmax < maxjoggle) {
+	  qh JOGGLEmax *= qh_JOGGLEincrease;
+	  minimize_(qh JOGGLEmax, maxjoggle); 
+	}
+      }
+    }
+    qh_option ("QJoggle", NULL, &qh JOGGLEmax);
+  }
+  if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
+      fprintf (qh ferr, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input.  If possible, recompile Qhull with higher-precision reals.\n",
+	        qh JOGGLEmax);
+      qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  /* for some reason, using qh ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
+  seed= qh_RANDOMint;
+  qh_option ("_joggle-seed", &seed, NULL);
+  trace0((qh ferr, "qh_joggleinput: joggle input by %2.2g with seed %d\n", 
+    qh JOGGLEmax, seed));
+  inputp= qh input_points;
+  coordp= qh first_point;
+  randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
+  randb= -qh JOGGLEmax;
+  size= qh num_points * qh hull_dim;
+  for (i= size; i--; ) {
+    randr= qh_RANDOMint;
+    *(coordp++)= *(inputp++) + (randr * randa + randb);
+  }
+  if (qh DELAUNAY) {
+    qh last_low= qh last_high= qh last_newhigh= REALmax;
+    qh_setdelaunay (qh hull_dim, qh num_points, qh first_point);
+  }
+} /* joggleinput */
+
+/*---------------------------------
+  
+  qh_maxabsval( normal, dim )
+    return pointer to maximum absolute value of a dim vector
+    returns NULL if dim=0
+*/
+realT *qh_maxabsval (realT *normal, int dim) {
+  realT maxval= -REALmax;
+  realT *maxp= NULL, *colp, absval;
+  int k;
+
+  for (k= dim, colp= normal; k--; colp++) {
+    absval= fabs_(*colp);
+    if (absval > maxval) {
+      maxval= absval;
+      maxp= colp;
+    }
+  }
+  return maxp;
+} /* maxabsval */
+
+
+/*---------------------------------
+  
+  qh_maxmin( points, numpoints, dimension )
+    return max/min points for each dimension      
+    determine max and min coordinates
+
+  returns:
+    returns a temporary set of max and min points
+      may include duplicate points. Does not include qh.GOODpoint
+    sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
+         qh.MAXlastcoord, qh.MINlastcoord
+    initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
+
+  notes:
+    loop duplicated in qh_detjoggle()
+
+  design:
+    initialize global precision variables
+    checks definition of REAL...
+    for each dimension
+      for each point
+        collect maximum and minimum point
+      collect maximum of maximums and minimum of minimums
+      determine qh.NEARzero for Gaussian Elimination
+*/
+setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
+  int k;
+  realT maxcoord, temp;
+  pointT *minimum, *maximum, *point, *pointtemp;
+  setT *set;
+
+  qh max_outside= 0.0;
+  qh MAXabs_coord= 0.0;
+  qh MAXwidth= -REALmax;
+  qh MAXsumcoord= 0.0;
+  qh min_vertex= 0.0;
+  qh WAScoplanar= False;
+  if (qh ZEROcentrum)
+    qh ZEROall_ok= True;
+  if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
+  && REALmax > 0.0 && -REALmax < 0.0)
+    ; /* all ok */
+  else {
+    fprintf (qh ferr, "qhull error: floating point constants in user.h are wrong\n\
+REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
+	     REALepsilon, REALmin, REALmax, -REALmax);
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  set= qh_settemp(2*dimension);
+  for(k= 0; k < dimension; k++) {
+    if (points == qh GOODpointp)
+      minimum= maximum= points + dimension;
+    else
+      minimum= maximum= points;
+    FORALLpoint_(points, numpoints) {
+      if (point == qh GOODpointp)
+	continue;
+      if (maximum[k] < point[k])
+	maximum= point;
+      else if (minimum[k] > point[k])
+	minimum= point;
+    }
+    if (k == dimension-1) {
+      qh MINlastcoord= minimum[k];
+      qh MAXlastcoord= maximum[k];
+    }
+    if (qh SCALElast && k == dimension-1)
+      maxcoord= qh MAXwidth;
+    else {
+      maxcoord= fmax_(maximum[k], -minimum[k]);
+      if (qh GOODpointp) {
+        temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
+        maximize_(maxcoord, temp);
+      }
+      temp= maximum[k] - minimum[k];
+      maximize_(qh MAXwidth, temp);
+    }
+    maximize_(qh MAXabs_coord, maxcoord);
+    qh MAXsumcoord += maxcoord;
+    qh_setappend (&set, maximum);
+    qh_setappend (&set, minimum);
+    /* calculation of qh NEARzero is based on error formula 4.4-13 of
+       Golub & van Loan, authors say n^3 can be ignored and 10 be used in
+       place of rho */
+    qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
+  }
+  if (qh IStracing >=1)
+    qh_printpoints (qh ferr, "qh_maxmin: found the max and min points (by dim):", set);
+  return(set);
+} /* maxmin */
+
+/*---------------------------------
+
+  qh_maxouter()
+    return maximum distance from facet to outer plane
+    normally this is qh.max_outside+qh.DISTround
+    does not include qh.JOGGLEmax
+
+  see:
+    qh_outerinner()
+    
+  notes:
+    need to add another qh.DISTround if testing actual point with computation
+
+  for joggle:
+    qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
+    need to use Wnewvertexmax since could have a coplanar point for a high 
+      facet that is replaced by a low facet
+    need to add qh.JOGGLEmax if testing input points
+*/
+realT qh_maxouter (void) {
+  realT dist;
+
+  dist= fmax_(qh max_outside, qh DISTround);
+  dist += qh DISTround;
+  trace4((qh ferr, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
+  return dist;
+} /* maxouter */
+
+/*---------------------------------
+  
+  qh_maxsimplex( dim, maxpoints, points, numpoints, simplex )
+    determines maximum simplex for a set of points 
+    starts from points already in simplex
+    skips qh.GOODpointp (assumes that it isn't in maxpoints)
+  
+  returns:
+    simplex with dim+1 points
+
+  notes:
+    assumes at least pointsneeded points in points
+    maximizes determinate for x,y,z,w, etc.
+    uses maxpoints as long as determinate is clearly non-zero
+
+  design:
+    initialize simplex with at least two points
+      (find points with max or min x coordinate)
+    for each remaining dimension
+      add point that maximizes the determinate
+        (use points from maxpoints first)    
+*/
+void qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
+  pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
+  boolT nearzero, maxnearzero= False;
+  int k, sizinit;
+  realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
+
+  sizinit= qh_setsize (*simplex);
+  if (sizinit < 2) {
+    if (qh_setsize (maxpoints) >= 2) {
+      FOREACHpoint_(maxpoints) {
+        if (maxcoord < point[0]) {
+          maxcoord= point[0];
+          maxx= point;
+        }
+	if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+        }
+      }
+    }else {
+      FORALLpoint_(points, numpoints) {
+	if (point == qh GOODpointp)
+	  continue;
+        if (maxcoord < point[0]) {
+	  maxcoord= point[0];
+          maxx= point;
+        }
+	if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+	}
+      }
+    }
+    qh_setunique (simplex, minx);
+    if (qh_setsize (*simplex) < 2)
+      qh_setunique (simplex, maxx);
+    sizinit= qh_setsize (*simplex);
+    if (sizinit < 2) {
+      qh_precision ("input has same x coordinate");
+      if (zzval_(Zsetplane) > qh hull_dim+1) {
+	fprintf (qh ferr, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
+		 qh_setsize(maxpoints)+numpoints);
+	qh_errexit (qh_ERRprec, NULL, NULL);
+      }else {
+	fprintf (qh ferr, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
+	qh_errexit (qh_ERRinput, NULL, NULL);
+      }
+    }
+  }
+  for(k= sizinit; k < dim+1; k++) {
+    maxpoint= NULL;
+    maxdet= -REALmax;
+    FOREACHpoint_(maxpoints) {
+      if (!qh_setin (*simplex, point)) {
+        det= qh_detsimplex(point, *simplex, k, &nearzero);
+        if ((det= fabs_(det)) > maxdet) {
+	  maxdet= det;
+          maxpoint= point;
+	  maxnearzero= nearzero;
+        }
+      }
+    }
+    if (!maxpoint || maxnearzero) {
+      zinc_(Zsearchpoints);
+      if (!maxpoint) {
+        trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
+      }else {
+        trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
+		k+1, qh_pointid(maxpoint), maxdet));
+      }
+      FORALLpoint_(points, numpoints) {
+	if (point == qh GOODpointp)
+	  continue;
+        if (!qh_setin (*simplex, point)) {
+          det= qh_detsimplex(point, *simplex, k, &nearzero);
+          if ((det= fabs_(det)) > maxdet) {
+	    maxdet= det;
+            maxpoint= point;
+	    maxnearzero= nearzero;
+	  }
+        }
+      }
+    } /* !maxpoint */
+    if (!maxpoint) {
+      fprintf (qh ferr, "qhull internal error (qh_maxsimplex): not enough points available\n");
+      qh_errexit (qh_ERRqhull, NULL, NULL);
+    }
+    qh_setappend(simplex, maxpoint);
+    trace1((qh ferr, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
+	    qh_pointid(maxpoint), k+1, maxdet));
+  } /* k */ 
+} /* maxsimplex */
+
+/*---------------------------------
+  
+  qh_minabsval( normal, dim )
+    return minimum absolute value of a dim vector
+*/
+realT qh_minabsval (realT *normal, int dim) {
+  realT minval= 0;
+  realT maxval= 0;
+  realT *colp;
+  int k;
+
+  for (k= dim, colp= normal; k--; colp++) {
+    maximize_(maxval, *colp);
+    minimize_(minval, *colp);
+  }
+  return fmax_(maxval, -minval);
+} /* minabsval */
+
+
+/*---------------------------------
+  
+  qh_mindif( vecA, vecB, dim )
+    return index of min abs. difference of two vectors
+*/
+int qh_mindiff (realT *vecA, realT *vecB, int dim) {
+  realT mindiff= REALmax, diff;
+  realT *vecAp= vecA, *vecBp= vecB;
+  int k, mink= 0;
+
+  for (k= 0; k < dim; k++) {
+    diff= *vecAp++ - *vecBp++;
+    diff= fabs_(diff);
+    if (diff < mindiff) {
+      mindiff= diff;
+      mink= k;
+    }
+  }
+  return mink;
+} /* mindiff */
+
+
+
+/*---------------------------------
+  
+  qh_orientoutside( facet  )
+    make facet outside oriented via qh.interior_point
+
+  returns:
+    True if facet reversed orientation.
+*/
+boolT qh_orientoutside (facetT *facet) {
+  int k;
+  realT dist;
+
+  qh_distplane (qh interior_point, facet, &dist);
+  if (dist > 0) {
+    for (k= qh hull_dim; k--; )
+      facet->normal[k]= -facet->normal[k];
+    facet->offset= -facet->offset;
+    return True;
+  }
+  return False;
+} /* orientoutside */
+
+/*---------------------------------
+  
+  qh_outerinner( facet, outerplane, innerplane  )
+    if facet and qh.maxoutdone (i.e., qh_check_maxout)
+      returns outer and inner plane for facet
+    else
+      returns maximum outer and inner plane
+    accounts for qh.JOGGLEmax
+
+  see:
+    qh_maxouter(), qh_check_bestdist(), qh_check_points()
+
+  notes:
+    outerplaner or innerplane may be NULL
+    
+    includes qh.DISTround for actual points
+    adds another qh.DISTround if testing with floating point arithmetic
+*/
+void qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane) {
+  realT dist, mindist;
+  vertexT *vertex, **vertexp;
+
+  if (outerplane) {
+    if (!qh_MAXoutside || !facet || !qh maxoutdone) {
+      *outerplane= qh_maxouter();       /* includes qh.DISTround */
+    }else { /* qh_MAXoutside ... */
+#if qh_MAXoutside 
+      *outerplane= facet->maxoutside + qh DISTround;
+#endif
+      
+    }
+    if (qh JOGGLEmax < REALmax/2)
+      *outerplane += qh JOGGLEmax * sqrt (qh hull_dim);
+  }
+  if (innerplane) {
+    if (facet) {
+      mindist= REALmax;
+      FOREACHvertex_(facet->vertices) {
+        zinc_(Zdistio);
+        qh_distplane (vertex->point, facet, &dist);
+        minimize_(mindist, dist);
+      }
+      *innerplane= mindist - qh DISTround;
+    }else 
+      *innerplane= qh min_vertex - qh DISTround;
+    if (qh JOGGLEmax < REALmax/2)
+      *innerplane -= qh JOGGLEmax * sqrt (qh hull_dim);
+  }
+} /* outerinner */
+
+/*---------------------------------
+  
+  qh_pointdist( point1, point2, dim )
+    return distance between two points
+
+  notes:
+    returns distance squared if 'dim' is negative
+*/
+coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
+  coordT dist, diff;
+  int k;
+  
+  dist= 0.0;
+  for (k= (dim > 0 ? dim : -dim); k--; ) {
+    diff= *point1++ - *point2++;
+    dist += diff * diff;
+  }
+  if (dim > 0)
+    return(sqrt(dist));
+  return dist;
+} /* pointdist */
+
+
+/*---------------------------------
+  
+  qh_printmatrix( fp, string, rows, numrow, numcol )
+    print matrix to fp given by row vectors
+    print string as header
+
+  notes:
+    print a vector by qh_printmatrix(fp, "", &vect, 1, len)
+*/
+void qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol) {
+  realT *rowp;
+  realT r; /*bug fix*/
+  int i,k;
+
+  fprintf (fp, "%s\n", string);
+  for (i= 0; i < numrow; i++) {
+    rowp= rows[i];
+    for (k= 0; k < numcol; k++) {
+      r= *rowp++;
+      fprintf (fp, "%6.3g ", r);
+    }
+    fprintf (fp, "\n");
+  }
+} /* printmatrix */
+
+  
+/*---------------------------------
+  
+  qh_printpoints( fp, string, points )
+    print pointids to fp for a set of points
+    if string, prints string and 'p' point ids
+*/
+void qh_printpoints (FILE *fp, char *string, setT *points) {
+  pointT *point, **pointp;
+
+  if (string) {
+    fprintf (fp, "%s", string);
+    FOREACHpoint_(points) 
+      fprintf (fp, " p%d", qh_pointid(point));
+    fprintf (fp, "\n");
+  }else {
+    FOREACHpoint_(points) 
+      fprintf (fp, " %d", qh_pointid(point));
+    fprintf (fp, "\n");
+  }
+} /* printpoints */
+
+  
+/*---------------------------------
+  
+  qh_projectinput()
+    project input points using qh.lower_bound/upper_bound and qh DELAUNAY
+    if qh.lower_bound[k]=qh.upper_bound[k]= 0, 
+      removes dimension k 
+    if halfspace intersection
+      removes dimension k from qh.feasible_point
+    input points in qh first_point, num_points, input_dim
+
+  returns:
+    new point array in qh first_point of qh hull_dim coordinates
+    sets qh POINTSmalloc
+    if qh DELAUNAY 
+      projects points to paraboloid
+      lowbound/highbound is also projected
+    if qh ATinfinity
+      adds point "at-infinity"
+    if qh POINTSmalloc 
+      frees old point array
+
+  notes:
+    checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
+
+
+  design:
+    sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
+    determines newdim and newnum for qh hull_dim and qh num_points
+    projects points to newpoints
+    projects qh.lower_bound to itself
+    projects qh.upper_bound to itself
+    if qh DELAUNAY
+      if qh ATINFINITY
+        projects points to paraboloid
+        computes "infinity" point as vertex average and 10% above all points 
+      else
+        uses qh_setdelaunay to project points to paraboloid
+*/
+void qh_projectinput (void) {
+  int k,i;
+  int newdim= qh input_dim, newnum= qh num_points;
+  signed char *project;
+  int size= (qh input_dim+1)*sizeof(*project);
+  pointT *newpoints, *coord, *infinity;
+  realT paraboloid, maxboloid= 0;
+  
+  project= (signed char*)qh_memalloc (size);
+  memset ((char*)project, 0, size);
+  for (k= 0; k < qh input_dim; k++) {   /* skip Delaunay bound */
+    if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
+      project[k]= -1;
+      newdim--;
+    }
+  }
+  if (qh DELAUNAY) {
+    project[k]= 1;
+    newdim++;
+    if (qh ATinfinity)
+      newnum++;
+  }
+  if (newdim != qh hull_dim) {
+    fprintf(qh ferr, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (!(newpoints=(coordT*)malloc(newnum*newdim*sizeof(coordT)))){
+    fprintf(qh ferr, "qhull error: insufficient memory to project %d points\n",
+           qh num_points);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  qh_projectpoints (project, qh input_dim+1, qh first_point,
+                    qh num_points, qh input_dim, newpoints, newdim);
+  trace1((qh ferr, "qh_projectinput: updating lower and upper_bound\n"));
+  qh_projectpoints (project, qh input_dim+1, qh lower_bound,
+                    1, qh input_dim+1, qh lower_bound, newdim+1);
+  qh_projectpoints (project, qh input_dim+1, qh upper_bound,
+                    1, qh input_dim+1, qh upper_bound, newdim+1);
+  if (qh HALFspace) {
+    if (!qh feasible_point) {
+      fprintf(qh ferr, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+    qh_projectpoints (project, qh input_dim, qh feasible_point,
+		      1, qh input_dim, qh feasible_point, newdim);
+  }
+  qh_memfree(project, ((qh input_dim+1)*sizeof(*project)));
+  if (qh POINTSmalloc)
+    free (qh first_point);
+  qh first_point= newpoints;
+  qh POINTSmalloc= True;
+  if (qh DELAUNAY && qh ATinfinity) {
+    coord= qh first_point;
+    infinity= qh first_point + qh hull_dim * qh num_points;
+    for (k=qh hull_dim-1; k--; )
+      infinity[k]= 0.0;
+    for (i=qh num_points; i--; ) {
+      paraboloid= 0.0;
+      for (k=0; k < qh hull_dim-1; k++) {
+        paraboloid += *coord * *coord;
+	infinity[k] += *coord;
+        coord++;
+      }
+      *(coord++)= paraboloid;
+      maximize_(maxboloid, paraboloid);
+    }
+    /* coord == infinity */
+    for (k=qh hull_dim-1; k--; )
+      *(coord++) /= qh num_points;
+    *(coord++)= maxboloid * 1.1;
+    qh num_points++;
+    trace0((qh ferr, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
+  }else if (qh DELAUNAY)  /* !qh ATinfinity */
+    qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
+} /* projectinput */
+
+  
+/*---------------------------------
+  
+  qh_projectpoints( project, n, points, numpoints, dim, newpoints, newdim )
+    project points/numpoints/dim to newpoints/newdim
+    if project[k] == -1
+      delete dimension k 
+    if project[k] == 1 
+      add dimension k by duplicating previous column
+    n is size of project
+
+  notes:
+    newpoints may be points if only adding dimension at end
+
+  design:
+    check that 'project' and 'newdim' agree
+    for each dimension
+      if project == -1
+        skip dimension
+      else
+        determine start of column in newpoints
+        determine start of column in points 
+          if project == +1, duplicate previous column
+        copy dimension (column) from points to newpoints
+*/
+void qh_projectpoints (signed char *project, int n, realT *points, 
+        int numpoints, int dim, realT *newpoints, int newdim) {
+  int testdim= dim, oldk=0, newk=0, i,j=0,k;
+  realT *newp, *oldp;
+  
+  for (k= 0; k < n; k++)
+    testdim += project[k];
+  if (testdim != newdim) {
+    fprintf (qh ferr, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
+      newdim, testdim);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  for (j= 0; j= dim)
+	  continue;
+	oldp= points+oldk;
+      }else 
+	oldp= points+oldk++;
+      for (i=numpoints; i--; ) {
+        *newp= *oldp;
+        newp += newdim;
+        oldp += dim;
+      }
+    }
+    if (oldk >= dim)
+      break;
+  }
+  trace1((qh ferr, "qh_projectpoints: projected %d points from dim %d to dim %d\n", 
+    numpoints, dim, newdim));
+} /* projectpoints */
+        
+
+/*---------------------------------
+  
+  qh_rand() 
+  qh_srand( seed )
+    generate pseudo-random number between 1 and 2^31 -2
+
+  notes:
+    from Park & Miller's minimimal standard random number generator
+       Communications of the ACM, 31:1192-1201, 1988.
+    does not use 0 or 2^31 -1
+       this is silently enforced by qh_srand()
+    can make 'Rn' much faster by moving qh_rand to qh_distplane
+*/
+int qh_rand_seed= 1;  /* define as global variable instead of using qh */
+
+int qh_rand( void) {
+#define qh_rand_a 16807
+#define qh_rand_m 2147483647
+#define qh_rand_q 127773  /* m div a */
+#define qh_rand_r 2836    /* m mod a */
+  int lo, hi, test;
+  int seed = qh_rand_seed;
+
+  hi = seed / qh_rand_q;  /* seed div q */
+  lo = seed % qh_rand_q;  /* seed mod q */
+  test = qh_rand_a * lo - qh_rand_r * hi;
+  if (test > 0)
+    seed= test;
+  else
+    seed= test + qh_rand_m;
+  qh_rand_seed= seed;
+  /* seed = seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax;  for testing */
+  /* seed = qh_RANDOMmax;  for testing */
+  return seed;
+} /* rand */
+
+void qh_srand( int seed) {
+  if (seed < 1)
+    qh_rand_seed= 1;
+  else if (seed >= qh_rand_m)
+    qh_rand_seed= qh_rand_m - 1;
+  else
+    qh_rand_seed= seed;
+} /* qh_srand */
+
+/*---------------------------------
+  
+  qh_randomfactor()
+    return a random factor within qh.RANDOMmax of 1.0
+
+  notes:
+    qh.RANDOMa/b are defined in global.c
+*/
+realT qh_randomfactor (void) {
+  realT randr;
+
+  randr= qh_RANDOMint;
+  return randr * qh RANDOMa + qh RANDOMb;
+} /* randomfactor */
+
+/*---------------------------------
+  
+  qh_randommatrix( buffer, dim, rows )
+    generate a random dim X dim matrix in range [-1,1]
+    assumes buffer is [dim+1, dim]
+
+  returns:
+    sets buffer to random numbers
+    sets rows to rows of buffer
+      sets row[dim] as scratch row
+*/
+void qh_randommatrix (realT *buffer, int dim, realT **rows) {
+  int i, k;
+  realT **rowi, *coord, realr;
+
+  coord= buffer;
+  rowi= rows;
+  for (i=0; i < dim; i++) {
+    *(rowi++)= coord;
+    for (k=0; k < dim; k++) {
+      realr= qh_RANDOMint;
+      *(coord++)= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
+    }
+  }
+  *rowi= coord;
+} /* randommatrix */
+
+        
+/*---------------------------------
+  
+  qh_rotateinput( rows )
+    rotate input using row matrix
+    input points given by qh first_point, num_points, hull_dim
+    assumes rows[dim] is a scratch buffer
+    if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    rotated input
+    sets qh POINTSmalloc
+
+  design:
+    see qh_rotatepoints
+*/
+void qh_rotateinput (realT **rows) {
+
+  if (!qh POINTSmalloc) {
+    qh first_point= qh_copypoints (qh first_point, qh num_points, qh hull_dim);
+    qh POINTSmalloc= True;
+  }
+  qh_rotatepoints (qh first_point, qh num_points, qh hull_dim, rows);
+}  /* rotateinput */
+
+/*---------------------------------
+  
+  qh_rotatepoints( points, numpoints, dim, row )
+    rotate numpoints points by a d-dim row matrix
+    assumes rows[dim] is a scratch buffer
+
+  returns:
+    rotated points in place
+
+  design:
+    for each point
+      for each coordinate
+        use row[dim] to compute partial inner product
+      for each coordinate
+        rotate by partial inner product
+*/
+void qh_rotatepoints (realT *points, int numpoints, int dim, realT **row) {
+  realT *point, *rowi, *coord= NULL, sum, *newval;
+  int i,j,k;
+
+  if (qh IStracing >= 1)
+    qh_printmatrix (qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
+  for (point= points, j= numpoints; j--; point += dim) {
+    newval= row[dim];
+    for (i= 0; i < dim; i++) {
+      rowi= row[i];
+      coord= point;
+      for (sum= 0.0, k= dim; k--; )
+        sum += *rowi++ * *coord++;
+      *(newval++)= sum;
+    }
+    for (k= dim; k--; )
+      *(--coord)= *(--newval);
+  }
+} /* rotatepoints */  
+  
+
+/*---------------------------------
+  
+  qh_scaleinput()
+    scale input points using qh low_bound/high_bound
+    input points given by qh first_point, num_points, hull_dim
+    if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    scales coordinates of points to low_bound[k], high_bound[k]
+    sets qh POINTSmalloc
+
+  design:
+    see qh_scalepoints
+*/
+void qh_scaleinput (void) {
+
+  if (!qh POINTSmalloc) {
+    qh first_point= qh_copypoints (qh first_point, qh num_points, qh hull_dim);
+    qh POINTSmalloc= True;
+  }
+  qh_scalepoints (qh first_point, qh num_points, qh hull_dim,
+       qh lower_bound, qh upper_bound);
+}  /* scaleinput */
+  
+/*---------------------------------
+  
+  qh_scalelast( points, numpoints, dim, low, high, newhigh )
+    scale last coordinate to [0,m] for Delaunay triangulations
+    input points given by points, numpoints, dim
+
+  returns:
+    changes scale of last coordinate from [low, high] to [0, newhigh]
+    overwrites last coordinate of each point
+    saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
+
+  notes:
+    when called by qh_setdelaunay, low/high may not match actual data
+    
+  design:
+    compute scale and shift factors
+    apply to last coordinate of each point
+*/
+void qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
+		   coordT high, coordT newhigh) {
+  realT scale, shift;
+  coordT *coord;
+  int i;
+  boolT nearzero= False;
+
+  trace4((qh ferr, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
+    low, high, newhigh));
+  qh last_low= low;
+  qh last_high= high;
+  qh last_newhigh= newhigh;
+  scale= qh_divzero (newhigh, high - low,
+                  qh MINdenom_1, &nearzero);
+  if (nearzero) {
+    if (qh DELAUNAY)
+      fprintf (qh ferr, "qhull input error: can not scale last coordinate.  Input is cocircular\n   or cospherical.   Use option 'Qz' to add a point at infinity.\n");
+    else
+      fprintf (qh ferr, "qhull input error: can not scale last coordinate.  New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
+		newhigh, low, high, high-low);
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  shift= - low * newhigh / (high-low);
+  coord= points + dim - 1;
+  for (i= numpoints; i--; coord += dim)
+    *coord= *coord * scale + shift;
+} /* scalelast */
+
+/*---------------------------------
+  
+  qh_scalepoints( points, numpoints, dim, newlows, newhighs )
+    scale points to new lowbound and highbound
+    retains old bound when newlow= -REALmax or newhigh= +REALmax
+
+  returns:
+    scaled points
+    overwrites old points
+
+  design:
+    for each coordinate
+      compute current low and high bound
+      compute scale and shift factors
+      scale all points
+      enforce new low and high bound for all points
+*/
+void qh_scalepoints (pointT *points, int numpoints, int dim,
+	realT *newlows, realT *newhighs) {
+  int i,k;
+  realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
+  boolT nearzero= False;
+     
+  for (k= 0; k < dim; k++) {
+    newhigh= newhighs[k];
+    newlow= newlows[k];
+    if (newhigh > REALmax/2 && newlow < -REALmax/2)
+      continue;
+    low= REALmax;
+    high= -REALmax;
+    for (i= numpoints, coord= points+k; i--; coord += dim) {
+      minimize_(low, *coord);
+      maximize_(high, *coord);
+    }
+    if (newhigh > REALmax/2)
+      newhigh= high;
+    if (newlow < -REALmax/2)
+      newlow= low;
+    if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
+      fprintf (qh ferr, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
+	       k, k, newhigh, newlow);
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    scale= qh_divzero (newhigh - newlow, high - low,
+                  qh MINdenom_1, &nearzero);
+    if (nearzero) {
+      fprintf (qh ferr, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
+              k, newlow, newhigh, low, high);
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    shift= (newlow * high - low * newhigh)/(high-low);
+    coord= points+k;
+    for (i= numpoints; i--; coord += dim)
+      *coord= *coord * scale + shift;
+    coord= points+k;
+    if (newlow < newhigh) {
+      mincoord= newlow;
+      maxcoord= newhigh;
+    }else {
+      mincoord= newhigh;
+      maxcoord= newlow;
+    }
+    for (i= numpoints; i--; coord += dim) {
+      minimize_(*coord, maxcoord);  /* because of roundoff error */
+      maximize_(*coord, mincoord);
+    }
+    trace0((qh ferr, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
+      k, low, high, newlow, newhigh, numpoints, scale, shift));
+  }
+} /* scalepoints */    
+
+       
+/*---------------------------------
+  
+  qh_setdelaunay( dim, count, points )
+    project count points to dim-d paraboloid for Delaunay triangulation
+    
+    dim is one more than the dimension of the input set
+    assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
+
+    points is a dim*count realT array.  The first dim-1 coordinates
+    are the coordinates of the first input point.  array[dim] is
+    the first coordinate of the second input point.  array[2*dim] is
+    the first coordinate of the third input point.
+
+    if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
+      calls qh_scalelast to scale the last coordinate the same as the other points
+
+  returns:
+    for each point
+      sets point[dim-1] to sum of squares of coordinates
+    scale points to 'Qbb' if needed
+      
+  notes:
+    to project one point, use
+      qh_setdelaunay (qh hull_dim, 1, point)
+      
+    Do not use options 'Qbk', 'QBk', or 'QbB' since they scale 
+    the coordinates after the original projection.
+
+*/
+void qh_setdelaunay (int dim, int count, pointT *points) {
+  int i, k;
+  coordT *coordp, coord;
+  realT paraboloid;
+
+  trace0((qh ferr, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
+  coordp= points;
+  for (i= 0; i < count; i++) {
+    coord= *coordp++;
+    paraboloid= coord*coord;
+    for (k= dim-2; k--; ) {
+      coord= *coordp++;
+      paraboloid += coord*coord;
+    }
+    *coordp++ = paraboloid;
+  }
+  if (qh last_low < REALmax/2) 
+    qh_scalelast (points, count, dim, qh last_low, qh last_high, qh last_newhigh);
+} /* setdelaunay */
+
+  
+/*---------------------------------
+  
+  qh_sethalfspace( dim, coords, nextp, normal, offset, feasible )
+    set point to dual of halfspace relative to feasible point
+    halfspace is normal coefficients and offset.
+
+  returns:
+    false if feasible point is outside of hull (error message already reported)
+    overwrites coordinates for point at dim coords
+    nextp= next point (coords)
+
+  design:
+    compute distance from feasible point to halfspace
+    divide each normal coefficient by -dist
+*/
+boolT qh_sethalfspace (int dim, coordT *coords, coordT **nextp, 
+         coordT *normal, coordT *offset, coordT *feasible) {
+  coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
+  realT dist;
+  realT r; /*bug fix*/
+  int k;
+  boolT zerodiv;
+
+  dist= *offset;
+  for (k= dim; k--; )
+    dist += *(normp++) * *(feasiblep++);
+  if (dist > 0)
+    goto LABELerroroutside;
+  normp= normal;
+  if (dist < -qh MINdenom) {
+    for (k= dim; k--; )
+      *(coordp++)= *(normp++) / -dist;
+  }else {
+    for (k= dim; k--; ) {
+      *(coordp++)= qh_divzero (*(normp++), -dist, qh MINdenom_1, &zerodiv);
+      if (zerodiv) 
+        goto LABELerroroutside;
+    }
+  }
+  *nextp= coordp;
+  if (qh IStracing >= 4) {
+    fprintf (qh ferr, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
+    for (k= dim, coordp= coords; k--; ) {
+      r= *coordp++;
+      fprintf (qh ferr, " %6.2g", r);
+    }
+    fprintf (qh ferr, "\n");
+  }
+  return True;
+LABELerroroutside:
+  feasiblep= feasible;
+  normp= normal;
+  fprintf(qh ferr, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
+  for (k= dim; k--; )
+    fprintf (qh ferr, qh_REAL_1, r=*(feasiblep++));
+  fprintf (qh ferr, "\n     halfspace: "); 
+  for (k= dim; k--; )
+    fprintf (qh ferr, qh_REAL_1, r=*(normp++));
+  fprintf (qh ferr, "\n     at offset: ");
+  fprintf (qh ferr, qh_REAL_1, *offset);
+  fprintf (qh ferr, " and distance: ");
+  fprintf (qh ferr, qh_REAL_1, dist);
+  fprintf (qh ferr, "\n");
+  return False;
+} /* sethalfspace */
+
+/*---------------------------------
+  
+  qh_sethalfspace_all( dim, count, halfspaces, feasible )
+    generate dual for halfspace intersection with feasible point
+    array of count halfspaces
+      each halfspace is normal coefficients followed by offset 
+      the origin is inside the halfspace if the offset is negative
+
+  returns:
+    malloc'd array of count X dim-1 points
+
+  notes:
+    call before qh_init_B or qh_initqhull_globals 
+    unused/untested code: please email bradb at shore.net if this works ok for you
+    If using option 'Fp', also set qh feasible_point. It is a malloc'd array 
+      that is freed by qh_freebuffers.
+
+  design:
+    see qh_sethalfspace
+*/
+coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible) {
+  int i, newdim;
+  pointT *newpoints;
+  coordT *coordp, *normalp, *offsetp;
+
+  trace0((qh ferr, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
+  newdim= dim - 1;
+  if (!(newpoints=(coordT*)malloc(count*newdim*sizeof(coordT)))){
+    fprintf(qh ferr, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
+          count);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coordp= newpoints;
+  normalp= halfspaces;
+  for (i= 0; i < count; i++) {
+    offsetp= normalp + newdim;
+    if (!qh_sethalfspace (newdim, coordp, &coordp, normalp, offsetp, feasible)) {
+      fprintf (qh ferr, "The halfspace was at index %d\n", i);
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    normalp= offsetp + 1;
+  }
+  return newpoints;
+} /* sethalfspace_all */
+
+  
+/*---------------------------------
+  
+  qh_sharpnewfacets()
+
+  returns:
+    true if could be an acute angle (facets in different quadrants)
+ 
+  notes:
+    for qh_findbest
+
+  design:
+    for all facets on qh.newfacet_list
+      if two facets are in different quadrants
+        set issharp
+*/
+boolT qh_sharpnewfacets () {
+  facetT *facet;
+  boolT issharp = False;
+  int *quadrant, k;
+  
+  quadrant= (int*)qh_memalloc (qh hull_dim * sizeof(int));
+  FORALLfacet_(qh newfacet_list) {
+    if (facet == qh newfacet_list) {
+      for (k= qh hull_dim; k--; )
+      	quadrant[ k]= (facet->normal[ k] > 0);
+    }else {
+      for (k= qh hull_dim; k--; ) {
+        if (quadrant[ k] != (facet->normal[ k] > 0)) {
+          issharp= True;
+          break;
+        }
+      }
+    }
+    if (issharp)
+      break;
+  }
+  qh_memfree( quadrant, qh hull_dim * sizeof(int));
+  trace3((qh ferr, "qh_sharpnewfacets: %d\n", issharp));
+  return issharp;
+} /* sharpnewfacets */
+
+/*---------------------------------
+  
+  qh_voronoi_center( dim, points )
+    return Voronoi center for a set of points
+    dim is the orginal dimension of the points
+    gh.gm_matrix/qh.gm_row are scratch buffers
+
+  returns:
+    center as a temporary point
+    if non-simplicial, 
+      returns center for max simplex of points
+
+  notes:
+    from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
+
+  design:
+    if non-simplicial
+      determine max simplex for points
+    translate point0 of simplex to origin
+    compute sum of squares of diagonal
+    compute determinate
+    compute Voronoi center (see Bowyer & Woodwark)
+*/
+pointT *qh_voronoi_center (int dim, setT *points) {
+  pointT *point, **pointp, *point0;
+  pointT *center= (pointT*)qh_memalloc (qh center_size);
+  setT *simplex;
+  int i, j, k, size= qh_setsize(points);
+  coordT *gmcoord;
+  realT *diffp, sum2, *sum2row, *sum2p, det, factor;
+  boolT nearzero, infinite;
+
+  if (size == dim+1)
+    simplex= points;
+  else if (size < dim+1) {
+    fprintf (qh ferr, "qhull internal error (qh_voronoi_center):\n  need at least %d points to construct a Voronoi center\n",
+	     dim+1);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }else {
+    simplex= qh_settemp (dim+1);
+    qh_maxsimplex (dim, points, NULL, 0, &simplex);
+  }
+  point0= SETfirstt_(simplex, pointT);
+  gmcoord= qh gm_matrix;
+  for (k=0; k < dim; k++) {
+    qh gm_row[k]= gmcoord;
+    FOREACHpoint_(simplex) {
+      if (point != point0)
+        *(gmcoord++)= point[k] - point0[k];
+    }
+  }
+  sum2row= gmcoord;
+  for (i=0; i < dim; i++) {
+    sum2= 0.0;
+    for (k= 0; k < dim; k++) {
+      diffp= qh gm_row[k] + i;
+      sum2 += *diffp * *diffp;
+    }
+    *(gmcoord++)= sum2;
+  }
+  det= qh_determinant (qh gm_row, dim, &nearzero);
+  factor= qh_divzero (0.5, det, qh MINdenom, &infinite);
+  if (infinite) {
+    for (k=dim; k--; )
+      center[k]= qh_INFINITE;
+    if (qh IStracing)
+      qh_printpoints (qh ferr, "qh_voronoi_center: at infinity for ", simplex);
+  }else {
+    for (i=0; i < dim; i++) {
+      gmcoord= qh gm_matrix;
+      sum2p= sum2row;
+      for (k=0; k < dim; k++) {
+	qh gm_row[k]= gmcoord;
+	if (k == i) {
+	  for (j= dim; j--; )
+	    *(gmcoord++)= *sum2p++;
+	}else {
+	  FOREACHpoint_(simplex) {
+	    if (point != point0)
+	      *(gmcoord++)= point[k] - point0[k];
+	  }
+	}
+      }
+      center[i]= qh_determinant (qh gm_row, dim, &nearzero)*factor + point0[i];
+    }
+#ifndef qh_NOtrace
+    if (qh IStracing >= 3) {
+      fprintf (qh ferr, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
+      qh_printmatrix (qh ferr, "center:", ¢er, 1, dim);
+      if (qh IStracing >= 5) {
+	qh_printpoints (qh ferr, "points", simplex);
+	FOREACHpoint_(simplex)
+	  fprintf (qh ferr, "p%d dist %.2g, ", qh_pointid (point),
+		   qh_pointdist (point, center, dim));
+	fprintf (qh ferr, "\n");
+      }
+    }
+#endif
+  }
+  if (simplex != points)
+    qh_settempfree (&simplex);
+  return center;
+} /* voronoi_center */
+

Added: trunk/scipy/spatial/qhull/src/global.c
===================================================================
--- trunk/scipy/spatial/qhull/src/global.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/global.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,2041 @@
+/*
  ---------------------------------
+
+   global.c
+   initializes all the globals of the qhull application
+
+   see README
+
+   see qhull.h for qh.globals and function prototypes
+
+   see qhull_a.h for internal functions
+
+   copyright (c) 1993-2003, The Geometry Center
+ */
+
+#include "qhull_a.h"
+
+/*========= qh definition (see qhull.h) =======================*/
+
+#if qh_QHpointer
+qhT *qh_qh= NULL;	/* pointer to all global variables */
+#else
+qhT qh_qh;     		/* all global variables.
+			   Add "= {0}" if this causes a compiler error.
+			   Also qh_qhstat in stat.c and qhmem in mem.c.  */
+#endif
+
+/*----------------------------------
+
+  qh_version
+    version string by year and date
+
+    the revision increases on code changes only
+
+  notes:
+    change date:    Changes.txt, Announce.txt, README.txt, 
+                    qhull.man, qhull.txt, qhull-news.html, Eudora signatures, 
+    change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt
+    change year:    Copying.txt
+    check download size
+    recompile user_eg.c, rbox.c, qhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c
+*/
+
+char *qh_version = "2003.1 2003/12/30";
+
+/*---------------------------------
+
+  qh_appendprint( printFormat )
+    append printFormat to qh.PRINTout unless already defined
+*/
+void qh_appendprint (qh_PRINT format) {
+  int i;
+
+  for (i=0; i < qh_PRINTEND; i++) {
+    if (qh PRINTout[i] == format && format != qh_PRINTqhull)
+      break;
+    if (!qh PRINTout[i]) {
+      qh PRINTout[i]= format;
+      break;
+    }
+  }
+} /* appendprint */
+     
+/*---------------------------------
+  
+  qh_checkflags( commandStr, hiddenFlags )
+    errors if commandStr contains hiddenFlags
+    hiddenFlags starts and ends with a space and is space deliminated (checked)
+
+  notes:
+    ignores first word (e.g., "qconvex i")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+  
+  see:
+    qh_initflags() initializes Qhull according to commandStr
+*/
+void qh_checkflags(char *command, char *hiddenflags) {
+  char *s= command, *t, *chkerr, key, opt, prevopt;
+  char chkkey[]= "   ";
+  char chkopt[]=  "    ";
+  char chkopt2[]= "     ";
+
+  if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
+    fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (strpbrk(hiddenflags, ",\n\r\t")) { 
+    fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    key = *s++;
+    chkerr = NULL;
+    if (key == '\'') {         /* TO 'file name' */
+      t= strchr(s, '\'');
+      if (!t) {
+	fprintf(qh ferr, "qhull error (qh_checkflags): missing the 2nd single-quote for:\n%s\n", s-1);
+	qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+      s= t+1;
+      continue;
+    }
+    chkkey[1]= key;
+    if (strstr(hiddenflags, chkkey)) {
+      chkerr= chkkey;
+    }else if (isupper(key)) {
+      opt= ' ';
+      prevopt= ' ';
+      chkopt[1]= key;
+      chkopt2[1]= key;
+      while (!chkerr && *s && !isspace(*s)) {
+	opt= *s++;
+	if (isalpha(opt)) {
+	  chkopt[2]= opt;
+	  if (strstr(hiddenflags, chkopt))
+	    chkerr= chkopt;
+	  if (prevopt != ' ') {
+ 	    chkopt2[2]= prevopt;
+ 	    chkopt2[3]= opt;
+	    if (strstr(hiddenflags, chkopt2))
+	      chkerr= chkopt2;
+	  }
+	}else if (key == 'Q' && isdigit(opt) && prevopt != 'b' 
+	      && (prevopt == ' ' || islower(prevopt))) {
+  	    chkopt[2]= opt;
+	    if (strstr(hiddenflags, chkopt))
+	      chkerr= chkopt;
+	}else {
+	  qh_strtod (s-1, &t);
+	  if (s < t)
+	    s= t;
+	}
+        prevopt= opt;
+      }
+    }
+    if (chkerr) {
+      *chkerr= '\'';
+      chkerr[strlen(chkerr)-1]=  '\'';
+      fprintf(qh ferr, "qhull error: option %s is not used with this program.\n             It may be used with qhull.\n", chkerr);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+  }
+} /* checkflags */
+    
+/*---------------------------------
+  
+  qh_clock()
+    return user CPU time in 100ths (qh_SECtick)
+    only defined for qh_CLOCKtype == 2
+
+  notes:
+    use first value to determine time 0
+    from Stevens '92 8.15
+*/
+unsigned long qh_clock (void) {
+
+#if (qh_CLOCKtype == 2)
+  struct tms time;
+  static long clktck;  /* initialized first call */
+  double ratio, cpu;
+  unsigned long ticks;
+
+  if (!clktck) {
+    if ((clktck= sysconf (_SC_CLK_TCK)) < 0) {
+      fprintf (qh ferr, "qhull internal error (qh_clock): sysconf() failed.  Use qh_CLOCKtype 1 in user.h\n");
+      qh_errexit (qh_ERRqhull, NULL, NULL);
+    }
+  }
+  if (times (&time) == -1) {
+    fprintf (qh ferr, "qhull internal error (qh_clock): times() failed.  Use qh_CLOCKtype 1 in user.h\n");
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  ratio= qh_SECticks / (double)clktck;
+  ticks= time.tms_utime * ratio;
+  return ticks;
+#else
+  fprintf (qh ferr, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
+  qh_errexit (qh_ERRqhull, NULL, NULL); /* never returns */
+  return 0;
+#endif
+} /* clock */
+
+/*---------------------------------
+
+  qh_freebuffers()
+    free up global memory buffers
+
+  notes:
+    must match qh_initbuffers()
+*/
+void qh_freebuffers (void) {
+
+  trace5((qh ferr, "qh_freebuffers: freeing up global memory buffers\n"));
+  /* allocated by qh_initqhull_buffers */
+  qh_memfree (qh NEARzero, qh hull_dim * sizeof(realT));
+  qh_memfree (qh lower_threshold, (qh input_dim+1) * sizeof(realT));
+  qh_memfree (qh upper_threshold, (qh input_dim+1) * sizeof(realT));
+  qh_memfree (qh lower_bound, (qh input_dim+1) * sizeof(realT));
+  qh_memfree (qh upper_bound, (qh input_dim+1) * sizeof(realT));
+  qh_memfree (qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
+  qh_memfree (qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
+  qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
+  qh lower_bound= qh upper_bound= NULL;
+  qh gm_matrix= NULL;
+  qh gm_row= NULL;
+  qh_setfree (&qh other_points);
+  qh_setfree (&qh del_vertices);
+  qh_setfree (&qh coplanarset);
+  if (qh line)                /* allocated by qh_readinput, freed if no error */
+    free (qh line);
+  if (qh half_space)
+    free (qh half_space);
+  if (qh temp_malloc)
+    free (qh temp_malloc);
+  if (qh feasible_point)      /* allocated by qh_readfeasible */
+    free (qh feasible_point);
+  if (qh feasible_string)     /* allocated by qh_initflags */
+    free (qh feasible_string);
+  qh line= qh feasible_string= NULL;
+  qh half_space= qh feasible_point= qh temp_malloc= NULL;
+  /* usually allocated by qh_readinput */
+  if (qh first_point && qh POINTSmalloc) {
+    free(qh first_point);
+    qh first_point= NULL;
+  }
+  if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
+    free (qh input_points);
+    qh input_points= NULL;
+  }
+  trace5((qh ferr, "qh_freebuffers: finished\n"));
+} /* freebuffers */
+
+
+/*---------------------------------
+
+  qh_freebuild( allmem )
+    free global memory used by qh_initbuild and qh_buildhull
+    if !allmem,
+      does not free short memory (freed by qh_memfreeshort)
+
+  design:
+    free centrums
+    free each vertex
+    mark unattached ridges
+    for each facet
+      free ridges
+      free outside set, coplanar set, neighbor set, ridge set, vertex set
+      free facet
+    free hash table
+    free interior point
+    free merge set
+    free temporary sets
+*/
+void qh_freebuild (boolT allmem) {
+  facetT *facet;
+  vertexT *vertex;
+  ridgeT *ridge, **ridgep;
+  mergeT *merge, **mergep;
+
+  trace1((qh ferr, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
+  if (qh del_vertices)
+    qh_settruncate (qh del_vertices, 0);
+  if (allmem) {
+    qh_clearcenters (qh_ASnone);
+    while ((vertex= qh vertex_list)) {
+      if (vertex->next)
+        qh_delvertex (vertex);
+      else {
+        qh_memfree (vertex, sizeof(vertexT));
+        qh newvertex_list= qh vertex_list= NULL;
+      }
+    }
+  }else if (qh VERTEXneighbors) {
+    FORALLvertices
+      qh_setfreelong (&(vertex->neighbors));
+  }
+  qh VERTEXneighbors= False;
+  qh GOODclosest= NULL;
+  if (allmem) {
+    FORALLfacets {
+      FOREACHridge_(facet->ridges)
+        ridge->seen= False;
+    }
+    FORALLfacets {
+      if (facet->visible) {
+	FOREACHridge_(facet->ridges) {
+	  if (!otherfacet_(ridge, facet)->visible)
+	    ridge->seen= True;  /* an unattached ridge */
+	}
+      }
+    }
+    while ((facet= qh facet_list)) {
+      FOREACHridge_(facet->ridges) {
+        if (ridge->seen) {
+          qh_setfree(&(ridge->vertices));
+          qh_memfree(ridge, sizeof(ridgeT));
+        }else
+          ridge->seen= True;
+      }
+      qh_setfree (&(facet->outsideset));
+      qh_setfree (&(facet->coplanarset));
+      qh_setfree (&(facet->neighbors));
+      qh_setfree (&(facet->ridges));
+      qh_setfree (&(facet->vertices));
+      if (facet->next)
+        qh_delfacet (facet);
+      else {
+        qh_memfree (facet, sizeof(facetT));
+        qh visible_list= qh newfacet_list= qh facet_list= NULL;
+      }
+    }
+  }else {
+    FORALLfacets {
+      qh_setfreelong (&(facet->outsideset));
+      qh_setfreelong (&(facet->coplanarset));
+      if (!facet->simplicial) {
+        qh_setfreelong (&(facet->neighbors));
+        qh_setfreelong (&(facet->ridges));
+        qh_setfreelong (&(facet->vertices));
+      }
+    }
+  }
+  qh_setfree (&(qh hash_table));
+  qh_memfree (qh interior_point, qh normal_size);
+  qh interior_point= NULL;
+  FOREACHmerge_(qh facet_mergeset)  /* usually empty */
+    qh_memfree (merge, sizeof(mergeT));
+  qh facet_mergeset= NULL;  /* temp set */
+  qh degen_mergeset= NULL;  /* temp set */
+  qh_settempfree_all();
+} /* freebuild */
+
+/*---------------------------------
+
+  qh_freeqhull( allmem )
+    free global memory
+    if !allmem,
+      does not free short memory (freed by qh_memfreeshort)
+
+  notes:
+    sets qh.NOerrexit in case caller forgets to
+
+  design:
+    free global and temporary memory from qh_initbuild and qh_buildhull
+    free buffers
+    free statistics
+*/
+void qh_freeqhull (boolT allmem) {
+
+  trace1((qh ferr, "qh_freeqhull: free global memory\n"));
+  qh NOerrexit= True;  /* no more setjmp since called at exit */
+  qh_freebuild (allmem);
+  qh_freebuffers();
+  qh_freestatistics();
+#if qh_QHpointer
+  free (qh_qh);
+  qh_qh= NULL;
+#else
+  memset((char *)&qh_qh, 0, sizeof(qhT));
+  qh NOerrexit= True;
+#endif
+} /* freeqhull */
+
+/*---------------------------------
+
+  qh_init_A( infile, outfile, errfile, argc, argv )
+    initialize memory and stdio files
+    convert input options to option string (qh.qhull_command)
+
+  notes:
+    infile may be NULL if qh_readpoints() is not called
+
+    errfile should always be defined.  It is used for reporting
+    errors.  outfile is used for output and format options.
+
+    argc/argv may be 0/NULL
+
+    called before error handling initialized
+    qh_errexit() may not be used
+*/
+void qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
+  qh_meminit (errfile);
+  qh_initqhull_start (infile, outfile, errfile);
+  qh_init_qhull_command (argc, argv);
+} /* init_A */
+
+/*---------------------------------
+
+  qh_init_B( points, numpoints, dim, ismalloc )
+    initialize globals for points array
+
+    points has numpoints dim-dimensional points
+      points[0] is the first coordinate of the first point
+      points[1] is the second coordinate of the first point
+      points[dim] is the first coordinate of the second point
+
+    ismalloc=True
+      Qhull will call free(points) on exit or input transformation
+    ismalloc=False
+      Qhull will allocate a new point array if needed for input transformation
+
+    qh.qhull_command
+      is the option string.
+      It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
+
+  returns:
+    if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
+      projects the input to a new point array
+
+        if qh.DELAUNAY,
+          qh.hull_dim is increased by one
+        if qh.ATinfinity,
+          qh_projectinput adds point-at-infinity for Delaunay tri.
+
+    if qh.SCALEinput
+      changes the upper and lower bounds of the input, see qh_scaleinput()
+
+    if qh.ROTATEinput
+      rotates the input by a random rotation, see qh_rotateinput()
+      if qh.DELAUNAY
+        rotates about the last coordinate
+
+  notes:
+    called after points are defined
+    qh_errexit() may be used
+*/
+void qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc) {
+  qh_initqhull_globals (points, numpoints, dim, ismalloc);
+  if (qhmem.LASTsize == 0)
+    qh_initqhull_mem();
+  /* mem.c and qset.c are initialized */
+  qh_initqhull_buffers();
+  qh_initthresholds (qh qhull_command);
+  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
+    qh_projectinput();
+  if (qh SCALEinput)
+    qh_scaleinput();
+  if (qh ROTATErandom >= 0) {
+    qh_randommatrix (qh gm_matrix, qh hull_dim, qh gm_row);
+    if (qh DELAUNAY) {
+      int k, lastk= qh hull_dim-1;
+      for (k= 0; k < lastk; k++) {
+        qh gm_row[k][lastk]= 0.0;
+        qh gm_row[lastk][k]= 0.0;
+      }
+      qh gm_row[lastk][lastk]= 1.0;
+    }
+    qh_gram_schmidt (qh hull_dim, qh gm_row);
+    qh_rotateinput (qh gm_row);
+  }
+} /* init_B */
+
+/*---------------------------------
+
+  qh_init_qhull_command( argc, argv )
+    build qh.qhull_command from argc/argv
+
+  returns:
+    a space-deliminated string of options (just as typed)
+
+  notes:
+    makes option string easy to input and output
+
+    argc/argv may be 0/NULL
+*/
+void qh_init_qhull_command(int argc, char *argv[]) {
+  int i;
+  char *s;
+
+  if (argc) {
+    if ((s= strrchr( argv[0], '\\'))) /* Borland gives full path */
+      strcpy (qh qhull_command, s+1);
+    else
+      strcpy (qh qhull_command, argv[0]);
+    if ((s= strstr (qh qhull_command, ".EXE"))
+    ||  (s= strstr (qh qhull_command, ".exe")))
+      *s= '\0';
+  }
+  for (i=1; i < argc; i++) {
+    if (strlen (qh qhull_command) + strlen(argv[i]) + 1 < sizeof(qh qhull_command)) {
+      strcat (qh qhull_command, " ");
+      strcat (qh qhull_command, argv[i]);
+    }else {
+      fprintf (qh ferr, "qhull input error: more than %d characters in command line\n",
+        (int)sizeof(qh qhull_command));
+      exit (1);  /* can not use qh_errexit */
+    }
+  }
+} /* init_qhull_command */
+
+/*---------------------------------
+
+  qh_initflags( commandStr )
+    set flags and initialized constants from commandStr
+
+  returns:
+    sets qh.qhull_command to command if needed
+
+  notes:
+    ignores first word (e.g., "qhull d")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+  see:
+    qh_initthresholds() continues processing of 'Pdn' and 'PDn'
+    'prompt' in unix.c for documentation
+
+  design:
+    for each space-deliminated option group
+      if top-level option
+        check syntax
+        append approriate option to option string
+        set appropriate global variable or append printFormat to print options
+      else
+        for each sub-option
+          check syntax
+          append approriate option to option string
+          set appropriate global variable or append printFormat to print options
+
+
+*/
+void qh_initflags(char *command) {
+  int k, i, lastproject;
+  char *s= command, *t, *prev_s, *start, key;
+  boolT isgeom= False, wasproject;
+  realT r;
+
+  if (command != &qh qhull_command[0]) {
+    *qh qhull_command= '\0';
+    strncat( qh qhull_command, command, sizeof( qh qhull_command));
+  }
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    prev_s= s;
+    switch (*s++) {
+    case 'd':
+      qh_option ("delaunay", NULL, NULL);
+      qh DELAUNAY= True;
+      break;
+    case 'f':
+      qh_option ("facets", NULL, NULL);
+      qh_appendprint (qh_PRINTfacets);
+      break;
+    case 'i':
+      qh_option ("incidence", NULL, NULL);
+      qh_appendprint (qh_PRINTincidences);
+      break;
+    case 'm':
+      qh_option ("mathematica", NULL, NULL);
+      qh_appendprint (qh_PRINTmathematica);
+      break;
+    case 'n':
+      qh_option ("normals", NULL, NULL);
+      qh_appendprint (qh_PRINTnormals);
+      break;
+    case 'o':
+      qh_option ("offFile", NULL, NULL);
+      qh_appendprint (qh_PRINToff);
+      break;
+    case 'p':
+      qh_option ("points", NULL, NULL);
+      qh_appendprint (qh_PRINTpoints);
+      break;
+    case 's':
+      qh_option ("summary", NULL, NULL);
+      qh PRINTsummary= True;
+      break;
+    case 'v':
+      qh_option ("voronoi", NULL, NULL);
+      qh VORONOI= True;
+      qh DELAUNAY= True;
+      break;
+    case 'A':
+      if (!isdigit(*s) && *s != '.' && *s != '-')
+	fprintf(qh ferr, "qhull warning: no maximum cosine angle given for option 'An'.  Ignored.\n");
+      else {
+	if (*s == '-') {
+	  qh premerge_cos= -qh_strtod (s, &s);
+          qh_option ("Angle-premerge-", NULL, &qh premerge_cos);
+	  qh PREmerge= True;
+	}else {
+	  qh postmerge_cos= qh_strtod (s, &s);
+          qh_option ("Angle-postmerge", NULL, &qh postmerge_cos);
+	  qh POSTmerge= True;
+	}
+	qh MERGING= True;
+      }
+      break;
+    case 'C':
+      if (!isdigit(*s) && *s != '.' && *s != '-')
+	fprintf(qh ferr, "qhull warning: no centrum radius given for option 'Cn'.  Ignored.\n");
+      else {
+	if (*s == '-') {
+	  qh premerge_centrum= -qh_strtod (s, &s);
+          qh_option ("Centrum-premerge-", NULL, &qh premerge_centrum);
+	  qh PREmerge= True;
+	}else {
+	  qh postmerge_centrum= qh_strtod (s, &s);
+          qh_option ("Centrum-postmerge", NULL, &qh postmerge_centrum);
+	  qh POSTmerge= True;
+	}
+	qh MERGING= True;
+      }
+      break;
+    case 'E':
+      if (*s == '-')
+	fprintf(qh ferr, "qhull warning: negative maximum roundoff given for option 'An'.  Ignored.\n");
+      else if (!isdigit(*s))
+	fprintf(qh ferr, "qhull warning: no maximum roundoff given for option 'En'.  Ignored.\n");
+      else {
+	qh DISTround= qh_strtod (s, &s);
+        qh_option ("Distance-roundoff", NULL, &qh DISTround);
+	qh SETroundoff= True;
+      }
+      break;
+    case 'H':
+      start= s;
+      qh HALFspace= True;
+      qh_strtod (s, &t);
+      while (t > s)  {
+        if (*t && !isspace (*t)) {
+	  if (*t == ',')
+	    t++;
+	  else
+	    fprintf (qh ferr, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
+	}
+        s= t;
+	qh_strtod (s, &t);
+      }
+      if (start < t) {
+        if (!(qh feasible_string= (char*)calloc (t-start+1, 1))) {
+          fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n");
+          qh_errexit(qh_ERRmem, NULL, NULL);
+        }
+        strncpy (qh feasible_string, start, t-start);
+        qh_option ("Halfspace-about", NULL, NULL);
+        qh_option (qh feasible_string, NULL, NULL);
+      }else
+        qh_option ("Halfspace", NULL, NULL);
+      break;
+    case 'R':
+      if (!isdigit(*s))
+	fprintf(qh ferr, "qhull warning: missing random perturbation for option 'Rn'.  Ignored\n");
+      else {
+	qh RANDOMfactor= qh_strtod (s, &s);
+        qh_option ("Random_perturb", NULL, &qh RANDOMfactor);
+        qh RANDOMdist= True;
+      }
+      break;
+    case 'V':
+      if (!isdigit(*s) && *s != '-')
+	fprintf(qh ferr, "qhull warning: missing visible distance for option 'Vn'.  Ignored\n");
+      else {
+	qh MINvisible= qh_strtod (s, &s);
+        qh_option ("Visible", NULL, &qh MINvisible);
+      }
+      break;
+    case 'U':
+      if (!isdigit(*s) && *s != '-')
+	fprintf(qh ferr, "qhull warning: missing coplanar distance for option 'Un'.  Ignored\n");
+      else {
+	qh MAXcoplanar= qh_strtod (s, &s);
+        qh_option ("U-coplanar", NULL, &qh MAXcoplanar);
+      }
+      break;
+    case 'W':
+      if (*s == '-')
+	fprintf(qh ferr, "qhull warning: negative outside width for option 'Wn'.  Ignored.\n");
+      else if (!isdigit(*s))
+	fprintf(qh ferr, "qhull warning: missing outside width for option 'Wn'.  Ignored\n");
+      else {
+	qh MINoutside= qh_strtod (s, &s);
+        qh_option ("W-outside", NULL, &qh MINoutside);
+        qh APPROXhull= True;
+      }
+      break;
+    /************  sub menus ***************/
+    case 'F':
+      while (*s && !isspace(*s)) {
+	switch(*s++) {
+	case 'a':
+	  qh_option ("Farea", NULL, NULL);
+	  qh_appendprint (qh_PRINTarea);
+	  qh GETarea= True;
+	  break;
+	case 'A':
+	  qh_option ("FArea-total", NULL, NULL);
+	  qh GETarea= True;
+	  break;
+        case 'c':
+          qh_option ("Fcoplanars", NULL, NULL);
+          qh_appendprint (qh_PRINTcoplanars);
+          break;
+        case 'C':
+          qh_option ("FCentrums", NULL, NULL);
+          qh_appendprint (qh_PRINTcentrums);
+          break;
+	case 'd':
+          qh_option ("Fd-cdd-in", NULL, NULL);
+	  qh CDDinput= True;
+	  break;
+	case 'D':
+          qh_option ("FD-cdd-out", NULL, NULL);
+	  qh CDDoutput= True;
+	  break;
+	case 'F':
+	  qh_option ("FFacets-xridge", NULL, NULL);
+          qh_appendprint (qh_PRINTfacets_xridge);
+	  break;
+        case 'i':
+          qh_option ("Finner", NULL, NULL);
+          qh_appendprint (qh_PRINTinner);
+          break;
+        case 'I':
+          qh_option ("FIDs", NULL, NULL);
+          qh_appendprint (qh_PRINTids);
+          break;
+        case 'm':
+          qh_option ("Fmerges", NULL, NULL);
+          qh_appendprint (qh_PRINTmerges);
+          break;
+        case 'M':
+          qh_option ("FMaple", NULL, NULL);
+          qh_appendprint (qh_PRINTmaple);
+          break;
+        case 'n':
+          qh_option ("Fneighbors", NULL, NULL);
+          qh_appendprint (qh_PRINTneighbors);
+          break;
+        case 'N':
+          qh_option ("FNeighbors-vertex", NULL, NULL);
+          qh_appendprint (qh_PRINTvneighbors);
+          break;
+        case 'o':
+          qh_option ("Fouter", NULL, NULL);
+          qh_appendprint (qh_PRINTouter);
+          break;
+	case 'O':
+	  if (qh PRINToptions1st) {
+	    qh_option ("FOptions", NULL, NULL);
+	    qh_appendprint (qh_PRINToptions);
+	  }else
+	    qh PRINToptions1st= True;
+	  break;
+	case 'p':
+	  qh_option ("Fpoint-intersect", NULL, NULL);
+	  qh_appendprint (qh_PRINTpointintersect);
+	  break;
+	case 'P':
+	  qh_option ("FPoint-nearest", NULL, NULL);
+	  qh_appendprint (qh_PRINTpointnearest);
+	  break;
+	case 'Q':
+	  qh_option ("FQhull", NULL, NULL);
+	  qh_appendprint (qh_PRINTqhull);
+	  break;
+        case 's':
+          qh_option ("Fsummary", NULL, NULL);
+          qh_appendprint (qh_PRINTsummary);
+          break;
+        case 'S':
+          qh_option ("FSize", NULL, NULL);
+          qh_appendprint (qh_PRINTsize);
+          qh GETarea= True;
+          break;
+        case 't':
+          qh_option ("Ftriangles", NULL, NULL);
+          qh_appendprint (qh_PRINTtriangles);
+          break;
+        case 'v':
+          /* option set in qh_initqhull_globals */
+          qh_appendprint (qh_PRINTvertices);
+          break;
+        case 'V':
+          qh_option ("FVertex-average", NULL, NULL);
+          qh_appendprint (qh_PRINTaverage);
+          break;
+	case 'x':
+	  qh_option ("Fxtremes", NULL, NULL);
+	  qh_appendprint (qh_PRINTextremes);
+	  break;
+	default:
+	  s--;
+	  fprintf (qh ferr, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
+	  while (*++s && !isspace(*s));
+	  break;
+	}
+      }
+      break;
+    case 'G':
+      isgeom= True;
+      qh_appendprint (qh_PRINTgeom);
+      while (*s && !isspace(*s)) {
+	switch(*s++) {
+        case 'a':
+          qh_option ("Gall-points", NULL, NULL);
+          qh PRINTdots= True;
+          break;
+        case 'c':
+          qh_option ("Gcentrums", NULL, NULL);
+          qh PRINTcentrums= True;
+          break;
+	case 'h':
+          qh_option ("Gintersections", NULL, NULL);
+	  qh DOintersections= True;
+	  break;
+	case 'i':
+          qh_option ("Ginner", NULL, NULL);
+	  qh PRINTinner= True;
+	  break;
+	case 'n':
+          qh_option ("Gno-planes", NULL, NULL);
+	  qh PRINTnoplanes= True;
+	  break;
+	case 'o':
+          qh_option ("Gouter", NULL, NULL);
+	  qh PRINTouter= True;
+	  break;
+	case 'p':
+          qh_option ("Gpoints", NULL, NULL);
+	  qh PRINTcoplanar= True;
+	  break;
+	case 'r':
+          qh_option ("Gridges", NULL, NULL);
+	  qh PRINTridges= True;
+	  break;
+	case 't':
+          qh_option ("Gtransparent", NULL, NULL);
+	  qh PRINTtransparent= True;
+	  break;
+	case 'v':
+          qh_option ("Gvertices", NULL, NULL);
+	  qh PRINTspheres= True;
+	  break;
+	case 'D':
+	  if (!isdigit (*s))
+	    fprintf (qh ferr, "qhull input error: missing dimension for option 'GDn'\n");
+	  else {
+	    if (qh DROPdim >= 0)
+	      fprintf (qh ferr, "qhull warning: can only drop one dimension.  Previous 'GD%d' ignored\n",
+	           qh DROPdim);
+  	    qh DROPdim= qh_strtol (s, &s);
+            qh_option ("GDrop-dim", &qh DROPdim, NULL);
+          }
+	  break;
+	default:
+	  s--;
+	  fprintf (qh ferr, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
+	  while (*++s && !isspace(*s));
+	  break;
+	}
+      }
+      break;
+    case 'P':
+      while (*s && !isspace(*s)) {
+	switch(*s++) {
+	case 'd': case 'D':  /* see qh_initthresholds() */
+	  key= s[-1];
+	  i= qh_strtol (s, &s);
+	  r= 0;
+	  if (*s == ':') {
+	    s++;
+	    r= qh_strtod (s, &s);
+	  }
+	  if (key == 'd')
+  	    qh_option ("Pdrop-facets-dim-less", &i, &r);
+  	  else
+  	    qh_option ("PDrop-facets-dim-more", &i, &r);
+	  break;
+        case 'g':
+          qh_option ("Pgood-facets", NULL, NULL);
+          qh PRINTgood= True;
+          break;
+        case 'G':
+          qh_option ("PGood-facet-neighbors", NULL, NULL);
+          qh PRINTneighbors= True;
+          break;
+        case 'o':
+          qh_option ("Poutput-forced", NULL, NULL);
+          qh FORCEoutput= True;
+          break;
+        case 'p':
+          qh_option ("Pprecision-ignore", NULL, NULL);
+          qh PRINTprecision= False;
+          break;
+	case 'A':
+	  if (!isdigit (*s))
+	    fprintf (qh ferr, "qhull input error: missing facet count for keep area option 'PAn'\n");
+	  else {
+  	    qh KEEParea= qh_strtol (s, &s);
+            qh_option ("PArea-keep", &qh KEEParea, NULL);
+            qh GETarea= True;
+          }
+	  break;
+	case 'F':
+	  if (!isdigit (*s))
+	    fprintf (qh ferr, "qhull input error: missing facet area for option 'PFn'\n");
+	  else {
+  	    qh KEEPminArea= qh_strtod (s, &s);
+            qh_option ("PFacet-area-keep", NULL, &qh KEEPminArea);
+            qh GETarea= True;
+          }
+	  break;
+	case 'M':
+	  if (!isdigit (*s))
+	    fprintf (qh ferr, "qhull input error: missing merge count for option 'PMn'\n");
+	  else {
+  	    qh KEEPmerge= qh_strtol (s, &s);
+            qh_option ("PMerge-keep", &qh KEEPmerge, NULL);
+          }
+	  break;
+	default:
+	  s--;
+	  fprintf (qh ferr, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
+	  while (*++s && !isspace(*s));
+	  break;
+	}
+      }
+      break;
+    case 'Q':
+      lastproject= -1;
+      while (*s && !isspace(*s)) {
+	switch(*s++) {
+	case 'b': case 'B':  /* handled by qh_initthresholds */
+	  key= s[-1];
+	  if (key == 'b' && *s == 'B') {
+	    s++;
+	    r= qh_DEFAULTbox;
+	    qh SCALEinput= True;
+	    qh_option ("QbBound-unit-box", NULL, &r);
+	    break;
+	  }
+	  if (key == 'b' && *s == 'b') {
+	    s++;
+	    qh SCALElast= True;
+	    qh_option ("Qbbound-last", NULL, NULL);
+	    break;
+	  }
+	  k= qh_strtol (s, &s);
+	  r= 0.0;
+	  wasproject= False;
+	  if (*s == ':') {
+	    s++;
+	    if ((r= qh_strtod(s, &s)) == 0.0) {
+ 	      t= s;            /* need true dimension for memory allocation */
+	      while (*t && !isspace(*t)) {
+	        if (toupper(*t++) == 'B'
+	         && k == qh_strtol (t, &t)
+	         && *t++ == ':'
+	         && qh_strtod(t, &t) == 0.0) {
+	          qh PROJECTinput++;
+	          trace2((qh ferr, "qh_initflags: project dimension %d\n", k));
+	          qh_option ("Qb-project-dim", &k, NULL);
+		  wasproject= True;
+	          lastproject= k;
+	          break;
+		}
+	      }
+	    }
+  	  }
+	  if (!wasproject) {
+	    if (lastproject == k && r == 0.0)
+	      lastproject= -1;  /* doesn't catch all possible sequences */
+	    else if (key == 'b') {
+	      qh SCALEinput= True;
+	      if (r == 0.0)
+		r= -qh_DEFAULTbox;
+	      qh_option ("Qbound-dim-low", &k, &r);
+	    }else {
+	      qh SCALEinput= True;
+	      if (r == 0.0)
+		r= qh_DEFAULTbox;
+	      qh_option ("QBound-dim-high", &k, &r);
+	    }
+	  }
+	  break;
+	case 'c':
+	  qh_option ("Qcoplanar-keep", NULL, NULL);
+	  qh KEEPcoplanar= True;
+	  break;
+	case 'f':
+	  qh_option ("Qfurthest-outside", NULL, NULL);
+	  qh BESToutside= True;
+	  break;
+	case 'g':
+	  qh_option ("Qgood-facets-only", NULL, NULL);
+	  qh ONLYgood= True;
+	  break;
+	case 'i':
+	  qh_option ("Qinterior-keep", NULL, NULL);
+	  qh KEEPinside= True;
+	  break;
+	case 'm':
+	  qh_option ("Qmax-outside-only", NULL, NULL);
+	  qh ONLYmax= True;
+	  break;
+	case 'r':
+	  qh_option ("Qrandom-outside", NULL, NULL);
+	  qh RANDOMoutside= True;
+	  break;
+	case 's':
+	  qh_option ("Qsearch-initial-simplex", NULL, NULL);
+	  qh ALLpoints= True;
+	  break;
+	case 't':
+	  qh_option ("Qtriangulate", NULL, NULL);
+	  qh TRIangulate= True;
+	  break;
+	case 'T':
+	  qh_option ("QTestPoints", NULL, NULL);
+	  if (!isdigit (*s))
+	    fprintf (qh ferr, "qhull input error: missing number of test points for option 'QTn'\n");
+	  else {
+  	    qh TESTpoints= qh_strtol (s, &s);
+            qh_option ("QTestPoints", &qh TESTpoints, NULL);
+          }
+	  break;
+	case 'u':
+	  qh_option ("QupperDelaunay", NULL, NULL);
+	  qh UPPERdelaunay= True;
+	  break;
+	case 'v':
+	  qh_option ("Qvertex-neighbors-convex", NULL, NULL);
+	  qh TESTvneighbors= True;
+	  break;
+	case 'x':
+	  qh_option ("Qxact-merge", NULL, NULL);
+	  qh MERGEexact= True;
+	  break;
+	case 'z':
+	  qh_option ("Qz-infinity-point", NULL, NULL);
+	  qh ATinfinity= True;
+	  break;
+	case '0':
+	  qh_option ("Q0-no-premerge", NULL, NULL);
+	  qh NOpremerge= True;
+	  break;
+	case '1':
+	  if (!isdigit(*s)) {
+	    qh_option ("Q1-no-angle-sort", NULL, NULL);
+	    qh ANGLEmerge= False;
+	    break; 
+	  }
+	  switch(*s++) {
+  	  case '0':
+	    qh_option ("Q10-no-narrow", NULL, NULL);
+	    qh NOnarrow= True;
+	    break; 
+  	  case '1':
+	    qh_option ("Q11-trinormals Qtriangulate", NULL, NULL);
+	    qh TRInormals= True;
+	    qh TRIangulate= True;
+	    break; 
+	  default:
+	    s--;
+	    fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
+	    while (*++s && !isspace(*s));
+	    break;
+	  }
+	  break;
+	case '2':
+	  qh_option ("Q2-no-merge-independent", NULL, NULL);
+	  qh MERGEindependent= False;
+	  goto LABELcheckdigit;
+	  break; /* no warnings */
+	case '3':
+	  qh_option ("Q3-no-merge-vertices", NULL, NULL);
+	  qh MERGEvertices= False;
+	LABELcheckdigit:
+	  if (isdigit(*s))
+	    fprintf (qh ferr, "qhull warning: can not follow '1', '2', or '3' with a digit.  '%c' skipped.\n",
+	             *s++);
+	  break;
+	case '4':
+	  qh_option ("Q4-avoid-old-into-new", NULL, NULL);
+	  qh AVOIDold= True;
+	  break;
+	case '5':
+	  qh_option ("Q5-no-check-outer", NULL, NULL);
+	  qh SKIPcheckmax= True;
+	  break;
+	case '6':
+	  qh_option ("Q6-no-concave-merge", NULL, NULL);
+	  qh SKIPconvex= True;
+	  break;
+	case '7':
+	  qh_option ("Q7-no-breadth-first", NULL, NULL);
+	  qh VIRTUALmemory= True;
+	  break;
+	case '8':
+	  qh_option ("Q8-no-near-inside", NULL, NULL);
+	  qh NOnearinside= True;
+	  break;
+	case '9':
+	  qh_option ("Q9-pick-furthest", NULL, NULL);
+	  qh PICKfurthest= True;
+	  break;
+	case 'G':
+	  i= qh_strtol (s, &t);
+	  if (qh GOODpoint)
+	    fprintf (qh ferr, "qhull warning: good point already defined for option 'QGn'.  Ignored\n");
+          else if (s == t)
+	    fprintf (qh ferr, "qhull warning: missing good point id for option 'QGn'.  Ignored\n");
+	  else if (i < 0 || *s == '-') {
+ 	    qh GOODpoint= i-1;
+  	    qh_option ("QGood-if-dont-see-point", &i, NULL);
+	  }else {
+ 	    qh GOODpoint= i+1;
+  	    qh_option ("QGood-if-see-point", &i, NULL);
+  	  }
+ 	  s= t;
+	  break;
+	case 'J':
+          if (!isdigit(*s) && *s != '-')
+   	    qh JOGGLEmax= 0.0;
+	  else {
+ 	    qh JOGGLEmax= (realT) qh_strtod (s, &s);
+            qh_option ("QJoggle", NULL, &qh JOGGLEmax);
+	  }
+	  break;
+	case 'R':
+          if (!isdigit(*s) && *s != '-')
+	    fprintf (qh ferr, "qhull warning: missing random seed for option 'QRn'.  Ignored\n");
+	  else {
+ 	    qh ROTATErandom= i= qh_strtol(s, &s);
+   	    if (i > 0)
+   	      qh_option ("QRotate-id", &i, NULL );
+	    else if (i < -1)
+   	      qh_option ("QRandom-seed", &i, NULL );
+          }
+	  break;
+	case 'V':
+	  i= qh_strtol (s, &t);
+	  if (qh GOODvertex)
+	    fprintf (qh ferr, "qhull warning: good vertex already defined for option 'QVn'.  Ignored\n");
+          else if (s == t)
+	    fprintf (qh ferr, "qhull warning: no good point id given for option 'QVn'.  Ignored\n");
+	  else if (i < 0) {
+ 	    qh GOODvertex= i - 1;
+ 	    qh_option ("QV-good-facets-not-point", &i, NULL);
+	  }else {
+  	    qh_option ("QV-good-facets-point", &i, NULL);
+	    qh GOODvertex= i + 1;
+          }
+ 	  s= t;
+	  break;
+	default:
+	  s--;
+	  fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
+	  while (*++s && !isspace(*s));
+	  break;
+	}
+      }
+      break;
+    case 'T':
+      while (*s && !isspace(*s)) {
+	if (isdigit(*s) || *s == '-')
+	  qh IStracing= qh_strtol(s, &s);
+	else switch(*s++) {
+	case 'c':
+          qh_option ("Tcheck-frequently", NULL, NULL);
+	  qh CHECKfrequently= True;
+	  break;
+	case 's':
+          qh_option ("Tstatistics", NULL, NULL);
+	  qh PRINTstatistics= True;
+	  break;
+	case 'v':
+          qh_option ("Tverify", NULL, NULL);
+	  qh VERIFYoutput= True;
+	  break;
+	case 'z':
+	  if (!qh fout)
+	    fprintf (qh ferr, "qhull warning: output file undefined (stdout).  Option 'Tz' ignored.\n");
+	  else {
+	    qh_option ("Tz-stdout", NULL, NULL);
+  	    qh ferr= qh fout;
+  	    qhmem.ferr= qh fout;
+	  }
+	  break;
+	case 'C':
+	  if (!isdigit(*s))
+	    fprintf (qh ferr, "qhull warning: missing point id for cone for trace option 'TCn'.  Ignored\n");
+	  else {
+	    i= qh_strtol (s, &s);
+	    qh_option ("TCone-stop", &i, NULL);
+	    qh STOPcone= i + 1;
+          }
+	  break;
+	case 'F':
+	  if (!isdigit(*s))
+	    fprintf (qh ferr, "qhull warning: missing frequency count for trace option 'TFn'.  Ignored\n");
+	  else {
+	    qh REPORTfreq= qh_strtol (s, &s);
+            qh_option ("TFacet-log", &qh REPORTfreq, NULL);
+	    qh REPORTfreq2= qh REPORTfreq/2;  /* for tracemerging() */
+	  }
+	  break;
+	case 'I':
+	  if (s[0] != ' ' || s[1] == '\"' || s[1] == '\'' ||isspace (s[1])) {
+	    s++;
+	    fprintf (qh ferr, "qhull warning: option 'TI' mistyped.\nUse 'TI', one space, file name, and space or end-of-line.\nDo not use quotes.  Option 'FI' ignored.\n");
+	  }else {  /* not a procedure because of qh_option (filename, NULL, NULL); */
+	    char filename[500], *t= filename;
+
+	    s++;
+	    while (*s) {
+	      if (t - filename >= sizeof (filename)-2) {
+		fprintf (qh ferr, "qhull error: filename for 'TI' too long.\n");
+		qh_errexit (qh_ERRinput, NULL, NULL);
+	      }
+	      if (isspace (*s))
+		break;
+	      *(t++)= *s++;
+	    }
+	    *t= '\0';
+	    if (!freopen (filename, "r", stdin)) {
+	      fprintf (qh ferr, "qhull error: could not open file \"%s\".", filename);
+	      qh_errexit (qh_ERRinput, NULL, NULL);
+	    }else {
+	      qh_option ("TInput-file", NULL, NULL);
+	      qh_option (filename, NULL, NULL);
+	    }
+	  }
+	  break;
+	case 'O':
+	  if (s[0] != ' ' || s[1] == '\"' || isspace (s[1])) {
+	    s++;
+	    fprintf (qh ferr, "qhull warning: option 'TO' mistyped.\nUse 'TO', one space, file name, and space or end-of-line.\nThe file name may be enclosed in single quotes.\nDo not use double quotes.  Option 'FO' ignored.\n");
+	  }else {  /* not a procedure because of qh_option (filename, NULL, NULL); */
+	    char filename[500], *t= filename;
+	    boolT isquote= False;
+
+	    s++;
+	    if (*s == '\'') {
+	      isquote= True;
+	      s++;
+	    }
+	    while (*s) {
+	      if (t - filename >= sizeof (filename)-2) {
+		fprintf (qh ferr, "qhull error: filename for 'TO' too long.\n");
+		qh_errexit (qh_ERRinput, NULL, NULL);
+	      }
+	      if (isquote) {
+		if (*s == '\'') {
+		  s++;
+		  isquote= False;
+		  break;
+		}
+	      }else if (isspace (*s))
+		break;
+	      *(t++)= *s++;
+	    }
+	    *t= '\0';
+	    if (isquote)
+	      fprintf (qh ferr, "qhull error: missing end quote for option 'TO'.  Rest of line ignored.\n");
+	    else if (!freopen (filename, "w", stdout)) {
+	      fprintf (qh ferr, "qhull error: could not open file \"%s\".", filename);
+	      qh_errexit (qh_ERRinput, NULL, NULL);
+	    }else {
+	      qh_option ("TOutput-file", NULL, NULL);
+	      qh_option (filename, NULL, NULL);
+	    }
+	  }
+	  break;
+	case 'P':
+	  if (!isdigit(*s))
+	    fprintf (qh ferr, "qhull warning: missing point id for trace option 'TPn'.  Ignored\n");
+	  else {
+	    qh TRACEpoint= qh_strtol (s, &s);
+            qh_option ("Trace-point", &qh TRACEpoint, NULL);
+          }
+	  break;
+	case 'M':
+	  if (!isdigit(*s))
+	    fprintf (qh ferr, "qhull warning: missing merge id for trace option 'TMn'.  Ignored\n");
+	  else {
+	    qh TRACEmerge= qh_strtol (s, &s);
+            qh_option ("Trace-merge", &qh TRACEmerge, NULL);
+          }
+	  break;
+	case 'R':
+	  if (!isdigit(*s))
+	    fprintf (qh ferr, "qhull warning: missing rerun count for trace option 'TRn'.  Ignored\n");
+	  else {
+	    qh RERUN= qh_strtol (s, &s);
+            qh_option ("TRerun", &qh RERUN, NULL);
+          }
+	  break;
+	case 'V':
+	  i= qh_strtol (s, &t);
+	  if (s == t)
+	    fprintf (qh ferr, "qhull warning: missing furthest point id for trace option 'TVn'.  Ignored\n");
+	  else if (i < 0) {
+	    qh STOPpoint= i - 1;
+            qh_option ("TV-stop-before-point", &i, NULL);
+	  }else {
+	    qh STOPpoint= i + 1;
+            qh_option ("TV-stop-after-point", &i, NULL);
+          }
+          s= t;
+	  break;
+	case 'W':
+	  if (!isdigit(*s))
+	    fprintf (qh ferr, "qhull warning: missing max width for trace option 'TWn'.  Ignored\n");
+	  else {
+ 	    qh TRACEdist= (realT) qh_strtod (s, &s);
+            qh_option ("TWide-trace", NULL, &qh TRACEdist);
+          }
+	  break;
+	default:
+	  s--;
+	  fprintf (qh ferr, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
+	  while (*++s && !isspace(*s));
+	  break;
+	}
+      }
+      break;
+    default:
+      fprintf (qh ferr, "qhull warning: unknown flag %c (%x)\n", (int)s[-1],
+	       (int)s[-1]);
+      break;
+    }
+    if (s-1 == prev_s && *s && !isspace(*s)) {
+      fprintf (qh ferr, "qhull warning: missing space after flag %c (%x); reserved for menu. Skipped.\n",
+	       (int)*prev_s, (int)*prev_s);
+      while (*s && !isspace(*s))
+	s++;
+    }
+  }
+  if (isgeom && !qh FORCEoutput && qh PRINTout[1])
+    fprintf (qh ferr, "qhull warning: additional output formats are not compatible with Geomview\n");
+  /* set derived values in qh_initqhull_globals */
+} /* initflags */
+
+
+/*---------------------------------
+
+  qh_initqhull_buffers()
+    initialize global memory buffers
+
+  notes:
+    must match qh_freebuffers()
+*/
+void qh_initqhull_buffers (void) {
+  int k;
+
+  qh TEMPsize= (qhmem.LASTsize - sizeof (setT))/SETelemsize;
+  if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
+    qh TEMPsize= 8;  /* e.g., if qh_NOmem */
+  qh other_points= qh_setnew (qh TEMPsize);
+  qh del_vertices= qh_setnew (qh TEMPsize);
+  qh coplanarset= qh_setnew (qh TEMPsize);
+  qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
+  qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  for(k= qh input_dim+1; k--; ) {
+    qh lower_threshold[k]= -REALmax;
+    qh upper_threshold[k]= REALmax;
+    qh lower_bound[k]= -REALmax;
+    qh upper_bound[k]= REALmax;
+  }
+  qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
+  qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
+} /* initqhull_buffers */
+
+/*---------------------------------
+
+  qh_initqhull_globals( points, numpoints, dim, ismalloc )
+    initialize globals
+    if ismalloc
+      points were malloc'd and qhull should free at end
+
+  returns:
+    sets qh.first_point, num_points, input_dim, hull_dim and others
+    seeds random number generator (seed=1 if tracing)
+    modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
+    adjust user flags as needed
+    also checks DIM3 dependencies and constants
+
+  notes:
+    do not use qh_point() since an input transformation may move them elsewhere
+
+  see:
+    qh_initqhull_start() sets default values for non-zero globals
+
+  design:
+    initialize points array from input arguments
+    test for qh.ZEROcentrum
+      (i.e., use opposite vertex instead of cetrum for convexity testing)
+    test for qh.PRINTgood (i.e., only print 'good' facets)
+    initialize qh.CENTERtype, qh.normal_size,
+      qh.center_size, qh.TRACEpoint/level,
+    initialize and test random numbers
+    check for conflicting print output options
+*/
+void qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc) {
+  int seed, pointsneeded, extra= 0, i, randi, k;
+  boolT printgeom= False, printmath= False, printcoplanar= False;
+  realT randr;
+  realT factorial;
+
+  time_t timedata;
+
+  trace0((qh ferr, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
+      qh qhull_command));
+  qh POINTSmalloc= ismalloc;
+  qh first_point= points;
+  qh num_points= numpoints;
+  qh hull_dim= qh input_dim= dim;
+  if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
+    qh MERGING= True;
+    if (qh hull_dim <= 4) {
+      qh PREmerge= True;
+      qh_option ("_pre-merge", NULL, NULL);
+    }else {
+      qh MERGEexact= True;
+      qh_option ("Qxact_merge", NULL, NULL);
+    }
+  }else if (qh MERGEexact) 
+    qh MERGING= True;
+  if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
+#ifdef qh_NOmerge
+    qh JOGGLEmax= 0.0;
+#endif
+  }
+  if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
+    fprintf(qh ferr, "qhull warning: joggle ('QJ') always produces simplicial output.  Triangulated output ('Qt') does nothing.\n");
+  if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
+    qh SCALElast= True;
+    qh_option ("Qbbound-last-qj", NULL, NULL);
+  }
+  if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
+  && qh premerge_centrum == 0) {
+    qh ZEROcentrum= True;
+    qh ZEROall_ok= True;
+    qh_option ("_zero-centrum", NULL, NULL);
+  }
+  if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
+    fprintf(qh ferr, "qhull warning: real epsilon, %2.2g, is probably too large for joggle ('QJn')\nRecompile with double precision reals (see user.h).\n",
+          REALepsilon);
+#ifdef qh_NOmerge
+  if (qh MERGING) {
+    fprintf (qh ferr, "qhull input error: merging not installed (qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+#endif
+  if (!(qh PRINTgood || qh PRINTneighbors)) {
+    if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
+	|| (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
+      qh PRINTgood= True;
+      qh_option ("Pgood", NULL, NULL);
+    }
+  }
+  if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
+    qh KEEPinside= True;
+    qh_option ("Qinterior-keep", NULL, NULL);
+  }
+  if (qh DELAUNAY && qh HALFspace) {
+    fprintf (qh ferr, "qhull input error: can not use Delaunay ('d') or Voronoi ('v') with halfspace intersection ('H')\n");
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
+    fprintf (qh ferr, "qhull input error: use upper-Delaunay ('Qu') or infinity-point ('Qz') with Delaunay ('d') or Voronoi ('v')\n");
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  if (qh UPPERdelaunay && qh ATinfinity) {
+    fprintf (qh ferr, "qhull input error: can not use infinity-point ('Qz') with upper-Delaunay ('Qu')\n");
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
+    fprintf (qh ferr, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
+  qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
+  qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar) 
+                          && !qh NOnearinside);
+  if (qh MERGING)
+    qh CENTERtype= qh_AScentrum;
+  else if (qh VORONOI)
+    qh CENTERtype= qh_ASvoronoi;
+  if (qh TESTvneighbors && !qh MERGING) {
+    fprintf(qh ferr, "qhull input error: test vertex neighbors ('Qv') needs a merge option\n");
+    qh_errexit (qh_ERRinput, NULL ,NULL);
+  }
+  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
+    qh hull_dim -= qh PROJECTinput;
+    if (qh DELAUNAY) {
+      qh hull_dim++;
+      extra= 1;
+    }
+  }
+  if (qh hull_dim <= 1) {
+    fprintf(qh ferr, "qhull error: dimension %d must be > 1\n", qh hull_dim);
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  for (k= 2, factorial=1.0; k < qh hull_dim; k++)
+    factorial *= k;
+  qh AREAfactor= 1.0 / factorial;
+  trace2((qh ferr, "qh_initqhull_globals: initialize globals.  dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
+	dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
+  qh normal_size= qh hull_dim * sizeof(coordT);
+  qh center_size= qh normal_size - sizeof(coordT);
+  pointsneeded= qh hull_dim+1;
+  if (qh hull_dim > qh_DIMmergeVertex) {
+    qh MERGEvertices= False;
+    qh_option ("Q3-no-merge-vertices-dim-high", NULL, NULL);
+  }
+  if (qh GOODpoint)
+    pointsneeded++;
+#ifdef qh_NOtrace
+  if (qh IStracing) {
+    fprintf (qh ferr, "qhull input error: tracing is not installed (qh_NOtrace in user.h)");
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+#endif
+  if (qh RERUN > 1) {
+    qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
+    if (qh IStracing != -1)
+      qh IStracing= 0;
+  }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
+    qh TRACElevel= (qh IStracing? qh IStracing : 3);
+    qh IStracing= 0;
+  }
+  if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
+    seed= time (&timedata);
+    if (qh ROTATErandom  == -1) {
+      seed= -seed;
+      qh_option ("QRandom-seed", &seed, NULL );
+    }else
+      qh_option ("QRotate-random", &seed, NULL);
+    qh ROTATErandom= seed;
+  }
+  seed= qh ROTATErandom;
+  if (seed == INT_MIN)    /* default value */
+    seed= 1;
+  else if (seed < 0)
+    seed= -seed;
+  qh_RANDOMseed_(seed);
+  randr= 0.0;
+  for (i= 1000; i--; ) {
+    randi= qh_RANDOMint;
+    randr += randi;
+    if (randi > qh_RANDOMmax) {
+      fprintf (qh ferr, "\
+qhull configuration error (qh_RANDOMmax in user.h):\n\
+   random integer %d > qh_RANDOMmax (%.8g)\n",
+	       randi, qh_RANDOMmax);
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+  }
+  qh_RANDOMseed_(seed);
+  randr = randr/1000;
+  if (randr < qh_RANDOMmax/10
+  || randr > qh_RANDOMmax * 5)
+    fprintf (qh ferr, "\
+qhull configuration warning (qh_RANDOMmax in user.h):\n\
+   average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
+   Is qh_RANDOMmax (%.2g) wrong?\n",
+	     randr, qh_RANDOMmax/2.0, qh_RANDOMmax);
+  qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
+  qh RANDOMb= 1.0 - qh RANDOMfactor;
+  if (qh_HASHfactor < 1.1) {
+    fprintf(qh ferr, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1.  Qhull uses linear hash probing\n",
+      qh_HASHfactor);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  if (numpoints+extra < pointsneeded) {
+    fprintf(qh ferr,"qhull input error: not enough points (%d) to construct initial simplex (need %d)\n",
+	    numpoints, pointsneeded);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh PRINTtransparent) {
+    if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
+      fprintf(qh ferr,"qhull input error: transparent Delaunay ('Gt') needs 3-d Delaunay ('d') w/o 'GDn'\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    qh DROPdim = 3;
+    qh PRINTridges = True;
+  }
+  for (i= qh_PRINTEND; i--; ) {
+    if (qh PRINTout[i] == qh_PRINTgeom)
+      printgeom= True;
+    else if (qh PRINTout[i] == qh_PRINTmathematica || qh PRINTout[i] == qh_PRINTmaple)
+      printmath= True;
+    else if (qh PRINTout[i] == qh_PRINTcoplanars)
+      printcoplanar= True;
+    else if (qh PRINTout[i] == qh_PRINTpointnearest)
+      printcoplanar= True;
+    else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
+      fprintf (qh ferr, "qhull input error: option 'Fp' is only used for \nhalfspace intersection ('Hn,n,n').\n");
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
+      fprintf (qh ferr, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
+      fprintf (qh ferr, "qhull input error: option 'FC' is not available for Voronoi vertices ('v')\n");
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }else if (qh PRINTout[i] == qh_PRINTvertices) {
+      if (qh VORONOI)
+        qh_option ("Fvoronoi", NULL, NULL);
+      else 
+        qh_option ("Fvertices", NULL, NULL);
+    }
+  }
+  if (printcoplanar && qh DELAUNAY && qh JOGGLEmax < REALmax/2) {
+    if (qh PRINTprecision) 
+      fprintf (qh ferr, "qhull input warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
+  }
+  if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
+    if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar) {
+      qh KEEPcoplanar = True;
+      qh_option ("Qcoplanar", NULL, NULL);
+    }
+  }
+  if (printmath && (qh hull_dim > 3 || qh VORONOI)) {
+    fprintf (qh ferr, "qhull input error: Mathematica and Maple output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  if (printgeom) {
+    if (qh hull_dim > 4) {
+      fprintf (qh ferr, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
+     + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
+      fprintf (qh ferr, "qhull input error: no output specified for Geomview\n");
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
+      fprintf (qh ferr, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    /* can not warn about furthest-site Geomview output: no lower_threshold */
+    if (qh hull_dim == 4 && qh DROPdim == -1 &&
+	(qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
+      fprintf (qh ferr, "qhull input warning: coplanars, vertices, and centrums output not\n\
+available for 4-d output (ignored).  Could use 'GDn' instead.\n");
+      qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
+    }
+  }
+  qh PRINTdim= qh hull_dim;
+  if (qh DROPdim >=0) {    /* after Geomview checks */
+    if (qh DROPdim < qh hull_dim) {
+      qh PRINTdim--;
+      if (!printgeom || qh hull_dim < 3)
+        fprintf (qh ferr, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
+    }else
+      qh DROPdim= -1;
+  }else if (qh VORONOI) {
+    qh DROPdim= qh hull_dim-1;
+    qh PRINTdim= qh hull_dim-1;
+  }
+} /* initqhull_globals */
+ 
+/*---------------------------------
+
+  qh_initqhull_mem(  )
+    initialize mem.c for qhull
+    qh.hull_dim and qh.normal_size determine some of the allocation sizes
+    if qh.MERGING,
+      includes ridgeT
+    calls qh_user_memsizes() to add up to 10 additional sizes for quick allocation
+      (see numsizes below)
+
+  returns:
+    mem.c already for qh_memalloc/qh_memfree (errors if called beforehand)
+
+  notes:
+    qh_produceoutput() prints memsizes
+
+*/
+void qh_initqhull_mem (void) {
+  int numsizes;
+  int i;
+
+  numsizes= 8+10;
+  qh_meminitbuffers (qh IStracing, qh_MEMalign, numsizes,
+                     qh_MEMbufsize,qh_MEMinitbuf);
+  qh_memsize(sizeof(vertexT));
+  if (qh MERGING) {
+    qh_memsize(sizeof(ridgeT));
+    qh_memsize(sizeof(mergeT));
+  }
+  qh_memsize(sizeof(facetT));
+  i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;  /* ridge.vertices */
+  qh_memsize(i);
+  qh_memsize(qh normal_size);        /* normal */
+  i += SETelemsize;                 /* facet.vertices, .ridges, .neighbors */
+  qh_memsize(i);
+  qh_user_memsizes();
+  qh_memsetup();
+} /* initqhull_mem */
+
+/*---------------------------------
+
+  qh_initqhull_start( infile, outfile, errfile )
+    start initialization of qhull
+    initialize statistics, stdio, default values for global variables
+
+  see:
+    qh_maxmin() determines the precision constants
+*/
+void qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile) {
+
+  qh_CPUclock; /* start the clock */
+#if qh_QHpointer
+  if (!(qh_qh= (qhT *)malloc (sizeof(qhT)))) {
+    fprintf (errfile, "qhull error (qh_initqhull_globals): insufficient memory\n");
+    exit (qh_ERRmem);  /* no error handler */
+  }
+  memset((char *)qh_qh, 0, sizeof(qhT));   /* every field is 0, FALSE, NULL */
+#else
+  memset((char *)&qh_qh, 0, sizeof(qhT));
+#endif
+  strcat (qh qhull, "qhull");
+  qh_initstatistics();
+  qh ANGLEmerge= True;
+  qh DROPdim= -1;
+  qh ferr= errfile;
+  qh fin= infile;
+  qh fout= outfile;
+  qh furthest_id= -1;
+  qh JOGGLEmax= REALmax;
+  qh KEEPminArea = REALmax;
+  qh last_low= REALmax;
+  qh last_high= REALmax;
+  qh last_newhigh= REALmax;
+  qh max_outside= 0.0;
+  qh max_vertex= 0.0;
+  qh MAXabs_coord= 0.0;
+  qh MAXsumcoord= 0.0;
+  qh MAXwidth= -REALmax;
+  qh MERGEindependent= True;
+  qh MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
+  qh MINoutside= 0.0;
+  qh MINvisible= REALmax;
+  qh MAXcoplanar= REALmax;
+  qh outside_err= REALmax;
+  qh premerge_centrum= 0.0;
+  qh premerge_cos= REALmax;
+  qh PRINTprecision= True;
+  qh PRINTradius= 0.0;
+  qh postmerge_cos= REALmax;
+  qh postmerge_centrum= 0.0;
+  qh ROTATErandom= INT_MIN;
+  qh MERGEvertices= True;
+  qh totarea= 0.0;
+  qh totvol= 0.0;
+  qh TRACEdist= REALmax;
+  qh TRACEpoint= -1; /* recompile or use 'TPn' */
+  qh tracefacet_id= UINT_MAX;  /* recompile to trace a facet */
+  qh tracevertex_id= UINT_MAX; /* recompile to trace a vertex */
+  qh_RANDOMseed_(1);
+} /* initqhull_start */
+
+/*---------------------------------
+
+  qh_initthresholds( commandString )
+    set thresholds for printing and scaling from commandString
+
+  returns:
+    sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
+
+  see:
+    qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
+    qh_inthresholds()
+
+  design:
+    for each 'Pdn' or 'PDn' option
+      check syntax
+      set qh.lower_threshold or qh.upper_threshold
+    set qh.GOODthreshold if an unbounded threshold is used
+    set qh.SPLITthreshold if a bounded threshold is used
+*/
+void qh_initthresholds(char *command) {
+  realT value;
+  int index, maxdim, k;
+  char *s= command;
+  char key;
+
+  maxdim= qh input_dim;
+  if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
+    maxdim++;
+  while (*s) {
+    if (*s == '-')
+      s++;
+    if (*s == 'P') {
+      s++;
+      while (*s && !isspace(key= *s++)) {
+	if (key == 'd' || key == 'D') {
+	  if (!isdigit(*s)) {
+	    fprintf(qh ferr, "qhull warning: no dimension given for Print option '%c' at: %s.  Ignored\n",
+		    key, s-1);
+	    continue;
+	  }
+	  index= qh_strtol (s, &s);
+	  if (index >= qh hull_dim) {
+	    fprintf(qh ferr, "qhull warning: dimension %d for Print option '%c' is >= %d.  Ignored\n",
+	        index, key, qh hull_dim);
+	    continue;
+	  }
+	  if (*s == ':') {
+	    s++;
+	    value= qh_strtod(s, &s);
+	    if (fabs((double)value) > 1.0) {
+	      fprintf(qh ferr, "qhull warning: value %2.4g for Print option %c is > +1 or < -1.  Ignored\n",
+	              value, key);
+	      continue;
+	    }
+	  }else
+	    value= 0.0;
+	  if (key == 'd')
+	    qh lower_threshold[index]= value;
+	  else
+	    qh upper_threshold[index]= value;
+	}
+      }
+    }else if (*s == 'Q') {
+      s++;
+      while (*s && !isspace(key= *s++)) {
+	if (key == 'b' && *s == 'B') {
+	  s++;
+	  for (k=maxdim; k--; ) {
+	    qh lower_bound[k]= -qh_DEFAULTbox;
+	    qh upper_bound[k]= qh_DEFAULTbox;
+	  }
+	}else if (key == 'b' && *s == 'b')
+	  s++;
+	else if (key == 'b' || key == 'B') {
+	  if (!isdigit(*s)) {
+	    fprintf(qh ferr, "qhull warning: no dimension given for Qhull option %c.  Ignored\n",
+		    key);
+	    continue;
+	  }
+	  index= qh_strtol (s, &s);
+	  if (index >= maxdim) {
+	    fprintf(qh ferr, "qhull warning: dimension %d for Qhull option %c is >= %d.  Ignored\n",
+	        index, key, maxdim);
+	    continue;
+	  }
+	  if (*s == ':') {
+	    s++;
+	    value= qh_strtod(s, &s);
+	  }else if (key == 'b')
+	    value= -qh_DEFAULTbox;
+	  else
+	    value= qh_DEFAULTbox;
+	  if (key == 'b')
+	    qh lower_bound[index]= value;
+	  else
+	    qh upper_bound[index]= value;
+	}
+      }
+    }else {
+      while (*s && !isspace (*s))
+        s++;
+    }
+    while (isspace (*s))
+      s++;
+  }
+  for (k= qh hull_dim; k--; ) {
+    if (qh lower_threshold[k] > -REALmax/2) {
+      qh GOODthreshold= True;
+      if (qh upper_threshold[k] < REALmax/2) {
+        qh SPLITthresholds= True;
+        qh GOODthreshold= False;
+        break;
+      }
+    }else if (qh upper_threshold[k] < REALmax/2)
+      qh GOODthreshold= True;
+  }
+} /* initthresholds */
+
+/*---------------------------------
+
+  qh_option( option, intVal, realVal )
+    add an option description to qh.qhull_options
+
+  notes:
+    will be printed with statistics ('Ts') and errors
+    strlen(option) < 40
+*/
+void qh_option (char *option, int *i, realT *r) {
+  char buf[200];
+  int len, maxlen;
+
+  sprintf (buf, "  %s", option);
+  if (i)
+    sprintf (buf+strlen(buf), " %d", *i);
+  if (r)
+    sprintf (buf+strlen(buf), " %2.2g", *r);
+  len= strlen(buf);
+  qh qhull_optionlen += len;
+  maxlen= sizeof (qh qhull_options) - len -1;
+  maximize_(maxlen, 0);
+  if (qh qhull_optionlen >= 80 && maxlen > 0) {
+    qh qhull_optionlen= len;
+    strncat (qh qhull_options, "\n", maxlen--);
+  }
+  strncat (qh qhull_options, buf, maxlen);
+} /* option */
+
+#if qh_QHpointer
+/*---------------------------------
+
+  qh_restore_qhull( oldqh )
+    restores a previously saved qhull
+    also restores qh_qhstat and qhmem.tempstack
+
+  notes:
+    errors if current qhull hasn't been saved or freed
+    uses qhmem for error reporting
+
+  NOTE 1998/5/11:
+    Freeing memory after qh_save_qhull and qh_restore_qhull
+    is complicated.  The procedures will be redesigned.
+
+  see:
+    qh_save_qhull()
+*/
+void qh_restore_qhull (qhT **oldqh) {
+
+  if (*oldqh && strcmp ((*oldqh)->qhull, "qhull")) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
+                  *oldqh);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  if (qh_qh) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  if (!*oldqh || !(*oldqh)->old_qhstat) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
+                  *oldqh);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  qh_qh= *oldqh;
+  *oldqh= NULL;
+  qh_qhstat= qh old_qhstat;
+  qhmem.tempstack= qh old_tempstack;
+  trace1((qh ferr, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
+} /* restore_qhull */
+
+/*---------------------------------
+
+  qh_save_qhull(  )
+    saves qhull for a later qh_restore_qhull
+    also saves qh_qhstat and qhmem.tempstack
+
+  returns:
+    qh_qh=NULL
+
+  notes:
+    need to initialize qhull or call qh_restore_qhull before continuing
+
+  NOTE 1998/5/11:
+    Freeing memory after qh_save_qhull and qh_restore_qhull
+    is complicated.  The procedures will be redesigned.
+
+  see:
+    qh_restore_qhull()
+*/
+qhT *qh_save_qhull (void) {
+  qhT *oldqh;
+
+  trace1((qhmem.ferr, "qh_save_qhull: save qhull %p\n", qh_qh));
+  if (!qh_qh) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_save_qhull): qhull not initialized\n");
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  qh old_qhstat= qh_qhstat;
+  qh_qhstat= NULL;
+  qh old_tempstack= qhmem.tempstack;
+  qhmem.tempstack= NULL;
+  oldqh= qh_qh;
+  qh_qh= NULL;
+  return oldqh;
+} /* save_qhull */
+
+#endif
+
+/*---------------------------------
+
+  qh_strtol( s, endp) qh_strtod( s, endp)
+    internal versions of strtol() and strtod()
+    does not skip trailing spaces
+  notes:
+    some implementations of strtol()/strtod() skip trailing spaces
+*/
+double qh_strtod (const char *s, char **endp) {
+  double result;
+
+  result= strtod (s, endp);
+  if (s < (*endp) && (*endp)[-1] == ' ')
+    (*endp)--;
+  return result;
+} /* strtod */
+
+int qh_strtol (const char *s, char **endp) {
+  int result;
+
+  result= (int) strtol (s, endp, 10);
+  if (s< (*endp) && (*endp)[-1] == ' ')
+    (*endp)--;
+  return result;
+} /* strtol */

Added: trunk/scipy/spatial/qhull/src/io.c
===================================================================
--- trunk/scipy/spatial/qhull/src/io.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/io.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,4108 @@
+/*
  ---------------------------------
+
+   io.c 
+   Input/Output routines of qhull application
+
+   see qh-io.htm and io.h
+
+   see user.c for qh_errprint and qh_printfacetlist
+
+   unix.c calls qh_readpoints and qh_produce_output
+
+   unix.c and user.c are the only callers of io.c functions
+   This allows the user to avoid loading io.o from qhull.a
+
+   copyright (c) 1993-2003 The Geometry Center        
+*/
+
+#include "qhull_a.h"
+
+/*========= -functions in alphabetical order after qh_produce_output()  =====*/
+
+/*---------------------------------
+  
+  qh_produce_output()
+    prints out the result of qhull in desired format
+    if qh.GETarea
+      computes and prints area and volume
+    qh.PRINTout[] is an array of output formats
+
+  notes:
+    prints output in qh.PRINTout order
+*/
+void qh_produce_output(void) {
+  int i, tempsize= qh_setsize ((setT*)qhmem.tempstack), d_1;
+
+  if (qh VORONOI) {
+    qh_clearcenters (qh_ASvoronoi);
+    qh_vertexneighbors();
+  }
+  if (qh TRIangulate) {
+    qh_triangulate(); 
+    if (qh VERIFYoutput && !qh CHECKfrequently) 
+      qh_checkpolygon (qh facet_list);
+  }
+  qh_findgood_all (qh facet_list); 
+  if (qh GETarea)
+    qh_getarea(qh facet_list);
+  if (qh KEEParea || qh KEEPmerge || qh KEEPminArea < REALmax/2)
+    qh_markkeep (qh facet_list);
+  if (qh PRINTsummary)
+    qh_printsummary(qh ferr);
+  else if (qh PRINTout[0] == qh_PRINTnone)
+    qh_printsummary(qh fout);
+  for (i= 0; i < qh_PRINTEND; i++)
+    qh_printfacets (qh fout, qh PRINTout[i], qh facet_list, NULL, !qh_ALL);
+  qh_allstatistics();
+  if (qh PRINTprecision && !qh MERGING && (qh JOGGLEmax > REALmax/2 || qh RERUN))
+    qh_printstats (qh ferr, qhstat precision, NULL);
+  if (qh VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0)) 
+    qh_printstats (qh ferr, qhstat vridges, NULL);
+  if (qh PRINTstatistics) {
+    qh_collectstatistics();
+    qh_printstatistics(qh ferr, "");
+    qh_memstatistics (qh ferr);
+    d_1= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;
+    fprintf(qh ferr, "\
+    size in bytes: merge %d ridge %d vertex %d facet %d\n\
+         normal %d ridge vertices %d facet vertices or neighbors %d\n",
+	    sizeof(mergeT), sizeof(ridgeT),
+	    sizeof(vertexT), sizeof(facetT),
+	    qh normal_size, d_1, d_1 + SETelemsize);
+  }
+  if (qh_setsize ((setT*)qhmem.tempstack) != tempsize) {
+    fprintf (qh ferr, "qhull internal error (qh_produce_output): temporary sets not empty (%d)\n",
+	     qh_setsize ((setT*)qhmem.tempstack));
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+} /* produce_output */
+
+
+/*---------------------------------
+  
+  dfacet( id )
+    print facet by id, for debugging
+
+*/
+void dfacet (unsigned id) {
+  facetT *facet;
+
+  FORALLfacets {
+    if (facet->id == id) {
+      qh_printfacet (qh fout, facet);
+      break;
+    }
+  }
+} /* dfacet */
+
+
+/*---------------------------------
+  
+  dvertex( id )
+    print vertex by id, for debugging
+*/
+void dvertex (unsigned id) {
+  vertexT *vertex;
+
+  FORALLvertices {
+    if (vertex->id == id) {
+      qh_printvertex (qh fout, vertex);
+      break;
+    }
+  }
+} /* dvertex */
+
+
+/*---------------------------------
+  
+  qh_compare_vertexpoint( p1, p2 )
+    used by qsort() to order vertices by point id 
+*/
+int qh_compare_vertexpoint(const void *p1, const void *p2) {
+  vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2);
+ 
+  return ((qh_pointid(a->point) > qh_pointid(b->point)?1:-1));
+} /* compare_vertexpoint */
+
+/*---------------------------------
+  
+  qh_compare_facetarea( p1, p2 )
+    used by qsort() to order facets by area
+*/
+int qh_compare_facetarea(const void *p1, const void *p2) {
+  facetT *a= *((facetT **)p1), *b= *((facetT **)p2);
+
+  if (!a->isarea)
+    return -1;
+  if (!b->isarea)
+    return 1; 
+  if (a->f.area > b->f.area)
+    return 1;
+  else if (a->f.area == b->f.area)
+    return 0;
+  return -1;
+} /* compare_facetarea */
+
+/*---------------------------------
+  
+  qh_compare_facetmerge( p1, p2 )
+    used by qsort() to order facets by number of merges
+*/
+int qh_compare_facetmerge(const void *p1, const void *p2) {
+  facetT *a= *((facetT **)p1), *b= *((facetT **)p2);
+ 
+  return (a->nummerge - b->nummerge);
+} /* compare_facetvisit */
+
+/*---------------------------------
+  
+  qh_compare_facetvisit( p1, p2 )
+    used by qsort() to order facets by visit id or id
+*/
+int qh_compare_facetvisit(const void *p1, const void *p2) {
+  facetT *a= *((facetT **)p1), *b= *((facetT **)p2);
+  int i,j;
+
+  if (!(i= a->visitid))
+    i= - a->id; /* do not convert to int */
+  if (!(j= b->visitid))
+    j= - b->id;
+  return (i - j);
+} /* compare_facetvisit */
+
+/*---------------------------------
+  
+  qh_countfacets( facetlist, facets, printall, 
+          numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars  )
+    count good facets for printing and set visitid
+    if allfacets, ignores qh_skipfacet()
+
+  notes:
+    qh_printsummary and qh_countfacets must match counts
+
+  returns:
+    numfacets, numsimplicial, total neighbors, numridges, coplanars
+    each facet with ->visitid indicating 1-relative position
+      ->visitid==0 indicates not good
+  
+  notes
+    numfacets >= numsimplicial
+    if qh.NEWfacets, 
+      does not count visible facets (matches qh_printafacet)
+
+  design:
+    for all facets on facetlist and in facets set
+      unless facet is skipped or visible (i.e., will be deleted)
+        mark facet->visitid
+        update counts
+*/
+void qh_countfacets (facetT *facetlist, setT *facets, boolT printall,
+    int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
+  facetT *facet, **facetp;
+  int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
+
+  FORALLfacet_(facetlist) {
+    if ((facet->visible && qh NEWfacets)
+    || (!printall && qh_skipfacet(facet)))
+      facet->visitid= 0;
+    else {
+      facet->visitid= ++numfacets;
+      totneighbors += qh_setsize (facet->neighbors);
+      if (facet->simplicial) {
+        numsimplicial++;
+	if (facet->keepcentrum && facet->tricoplanar)
+	  numtricoplanars++;
+      }else
+        numridges += qh_setsize (facet->ridges);
+      if (facet->coplanarset)
+        numcoplanars += qh_setsize (facet->coplanarset);
+    }
+  }
+  FOREACHfacet_(facets) {
+    if ((facet->visible && qh NEWfacets)
+    || (!printall && qh_skipfacet(facet)))
+      facet->visitid= 0;
+    else {
+      facet->visitid= ++numfacets;
+      totneighbors += qh_setsize (facet->neighbors);
+      if (facet->simplicial){
+        numsimplicial++;
+	if (facet->keepcentrum && facet->tricoplanar)
+	  numtricoplanars++;
+      }else
+        numridges += qh_setsize (facet->ridges);
+      if (facet->coplanarset)
+        numcoplanars += qh_setsize (facet->coplanarset);
+    }
+  }
+  qh visit_id += numfacets+1;
+  *numfacetsp= numfacets;
+  *numsimplicialp= numsimplicial;
+  *totneighborsp= totneighbors;
+  *numridgesp= numridges;
+  *numcoplanarsp= numcoplanars;
+  *numtricoplanarsp= numtricoplanars;
+} /* countfacets */
+
+/*---------------------------------
+  
+  qh_detvnorm( vertex, vertexA, centers, offset )
+    compute separating plane of the Voronoi diagram for a pair of input sites
+    centers= set of facets (i.e., Voronoi vertices)
+      facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
+        
+  assumes:
+    qh_ASvoronoi and qh_vertexneighbors() already set
+  
+  returns:
+    norm
+      a pointer into qh.gm_matrix to qh.hull_dim-1 reals
+      copy the data before reusing qh.gm_matrix
+    offset
+      if 'QVn'
+        sign adjusted so that qh.GOODvertexp is inside
+      else
+        sign adjusted so that vertex is inside
+      
+    qh.gm_matrix= simplex of points from centers relative to first center
+    
+  notes:
+    in io.c so that code for 'v Tv' can be removed by removing io.c
+    returns pointer into qh.gm_matrix to avoid tracking of temporary memory
+  
+  design:
+    determine midpoint of input sites
+    build points as the set of Voronoi vertices
+    select a simplex from points (if necessary)
+      include midpoint if the Voronoi region is unbounded
+    relocate the first vertex of the simplex to the origin
+    compute the normalized hyperplane through the simplex
+    orient the hyperplane toward 'QVn' or 'vertex'
+    if 'Tv' or 'Ts'
+      if bounded
+        test that hyperplane is the perpendicular bisector of the input sites
+      test that Voronoi vertices not in the simplex are still on the hyperplane
+    free up temporary memory
+*/
+pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
+  facetT *facet, **facetp;
+  int  i, k, pointid, pointidA, point_i, point_n;
+  setT *simplex= NULL;
+  pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
+  coordT *coord, *gmcoord, *normalp;
+  setT *points= qh_settemp (qh TEMPsize);
+  boolT nearzero= False;
+  boolT unbounded= False;
+  int numcenters= 0;
+  int dim= qh hull_dim - 1;
+  realT dist, offset, angle, zero= 0.0;
+
+  midpoint= qh gm_matrix + qh hull_dim * qh hull_dim;  /* last row */
+  for (k= 0; k < dim; k++)
+    midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
+  FOREACHfacet_(centers) {
+    numcenters++;
+    if (!facet->visitid)
+      unbounded= True;
+    else {
+      if (!facet->center)
+        facet->center= qh_facetcenter (facet->vertices);
+      qh_setappend (&points, facet->center);
+    }
+  }
+  if (numcenters > dim) {
+    simplex= qh_settemp (qh TEMPsize);
+    qh_setappend (&simplex, vertex->point);
+    if (unbounded)
+      qh_setappend (&simplex, midpoint);
+    qh_maxsimplex (dim, points, NULL, 0, &simplex);
+    qh_setdelnth (simplex, 0);
+  }else if (numcenters == dim) {
+    if (unbounded)
+      qh_setappend (&points, midpoint);
+    simplex= points; 
+  }else {
+    fprintf(qh ferr, "qh_detvnorm: too few points (%d) to compute separating plane\n", numcenters);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  i= 0;
+  gmcoord= qh gm_matrix;
+  point0= SETfirstt_(simplex, pointT);
+  FOREACHpoint_(simplex) {
+    if (qh IStracing >= 4)
+      qh_printmatrix(qh ferr, "qh_detvnorm: Voronoi vertex or midpoint", 
+                              &point, 1, dim);
+    if (point != point0) {
+      qh gm_row[i++]= gmcoord;
+      coord= point0;
+      for (k= dim; k--; )
+        *(gmcoord++)= *point++ - *coord++;
+    }
+  }
+  qh gm_row[i]= gmcoord;  /* does not overlap midpoint, may be used later for qh_areasimplex */
+  normal= gmcoord;
+  qh_sethyperplane_gauss (dim, qh gm_row, point0, True,
+           	normal, &offset, &nearzero);
+  if (qh GOODvertexp == vertexA->point)
+    inpoint= vertexA->point;
+  else
+    inpoint= vertex->point;
+  zinc_(Zdistio);
+  dist= qh_distnorm (dim, inpoint, normal, &offset);
+  if (dist > 0) {
+    offset= -offset;
+    normalp= normal;
+    for (k= dim; k--; ) {
+      *normalp= -(*normalp);
+      normalp++;
+    }
+  }
+  if (qh VERIFYoutput || qh PRINTstatistics) {
+    pointid= qh_pointid (vertex->point);
+    pointidA= qh_pointid (vertexA->point);
+    if (!unbounded) {
+      zinc_(Zdiststat);
+      dist= qh_distnorm (dim, midpoint, normal, &offset);
+      if (dist < 0)
+        dist= -dist;
+      zzinc_(Zridgemid);
+      wwmax_(Wridgemidmax, dist);
+      wwadd_(Wridgemid, dist);
+      trace4((qh ferr, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
+                 pointid, pointidA, dist));
+      for (k= 0; k < dim; k++) 
+        midpoint[k]= vertexA->point[k] - vertex->point[k];  /* overwrites midpoint! */
+      qh_normalize (midpoint, dim, False);
+      angle= qh_distnorm (dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
+      if (angle < 0.0)
+	angle= angle + 1.0;
+      else
+	angle= angle - 1.0;
+      if (angle < 0.0)
+	angle -= angle;
+      trace4((qh ferr, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
+                 pointid, pointidA, angle, nearzero));
+      if (nearzero) {
+        zzinc_(Zridge0);
+        wwmax_(Wridge0max, angle);
+        wwadd_(Wridge0, angle);
+      }else {
+        zzinc_(Zridgeok)
+        wwmax_(Wridgeokmax, angle);
+        wwadd_(Wridgeok, angle);
+      }
+    }
+    if (simplex != points) {
+      FOREACHpoint_i_(points) {
+        if (!qh_setin (simplex, point)) {
+          facet= SETelemt_(centers, point_i, facetT);
+	  zinc_(Zdiststat);
+  	  dist= qh_distnorm (dim, point, normal, &offset);
+          if (dist < 0)
+            dist= -dist;
+	  zzinc_(Zridge);
+          wwmax_(Wridgemax, dist);
+          wwadd_(Wridge, dist);
+          trace4((qh ferr, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
+                             pointid, pointidA, facet->visitid, dist));
+        }
+      }
+    }
+  }
+  *offsetp= offset;
+  if (simplex != points)
+    qh_settempfree (&simplex);
+  qh_settempfree (&points);
+  return normal;
+} /* detvnorm */
+
+/*---------------------------------
+
+  qh_detvridge( vertexA )
+    determine Voronoi ridge from 'seen' neighbors of vertexA
+    include one vertex-at-infinite if an !neighbor->visitid
+
+  returns:
+    temporary set of centers (facets, i.e., Voronoi vertices)
+    sorted by center id
+*/
+setT *qh_detvridge (vertexT *vertex) {
+  setT *centers= qh_settemp (qh TEMPsize);
+  setT *tricenters= qh_settemp (qh TEMPsize);
+  facetT *neighbor, **neighborp;
+  boolT firstinf= True;
+  
+  FOREACHneighbor_(vertex) {
+    if (neighbor->seen) {
+      if (neighbor->visitid) {
+	if (!neighbor->tricoplanar || qh_setunique (&tricenters, neighbor->center)) 
+	  qh_setappend (¢ers, neighbor);
+      }else if (firstinf) {
+        firstinf= False;
+        qh_setappend (¢ers, neighbor);
+      }
+    }
+  }
+  qsort (SETaddr_(centers, facetT), qh_setsize (centers),
+             sizeof (facetT *), qh_compare_facetvisit);
+  qh_settempfree (&tricenters);
+  return centers;
+} /* detvridge */      
+
+/*---------------------------------
+
+  qh_detvridge3( atvertex, vertex )
+    determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
+    include one vertex-at-infinite for !neighbor->visitid
+    assumes all facet->seen2= True
+
+  returns:
+    temporary set of centers (facets, i.e., Voronoi vertices)
+    listed in adjacency order (not oriented)
+    all facet->seen2= True
+
+  design:
+    mark all neighbors of atvertex
+    for each adjacent neighbor of both atvertex and vertex
+      if neighbor selected
+        add neighbor to set of Voronoi vertices
+*/
+setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex) {
+  setT *centers= qh_settemp (qh TEMPsize);
+  setT *tricenters= qh_settemp (qh TEMPsize);
+  facetT *neighbor, **neighborp, *facet= NULL;
+  boolT firstinf= True;
+  
+  FOREACHneighbor_(atvertex)
+    neighbor->seen2= False;
+  FOREACHneighbor_(vertex) {
+    if (!neighbor->seen2) {
+      facet= neighbor;
+      break;
+    }
+  }
+  while (facet) { 
+    facet->seen2= True;
+    if (neighbor->seen) {
+      if (facet->visitid) {
+	if (!facet->tricoplanar || qh_setunique (&tricenters, facet->center)) 
+	  qh_setappend (¢ers, facet);
+      }else if (firstinf) {
+        firstinf= False;
+        qh_setappend (¢ers, facet);
+      }
+    }
+    FOREACHneighbor_(facet) {
+      if (!neighbor->seen2) {
+	if (qh_setin (vertex->neighbors, neighbor))
+          break;
+	else
+	  neighbor->seen2= True;
+      }
+    }
+    facet= neighbor;
+  }
+  if (qh CHECKfrequently) {
+    FOREACHneighbor_(vertex) {
+      if (!neighbor->seen2) {
+	fprintf (stderr, "qh_detvridge3: neigbors of vertex p%d are not connected at facet %d\n",
+	         qh_pointid (vertex->point), neighbor->id);
+	qh_errexit (qh_ERRqhull, neighbor, NULL);
+      }
+    }
+  }
+  FOREACHneighbor_(atvertex) 
+    neighbor->seen2= True;
+  qh_settempfree (&tricenters);
+  return centers;
+} /* detvridge3 */      
+
+/*---------------------------------
+  
+  qh_eachvoronoi( fp, printvridge, vertex, visitall, innerouter, inorder )
+    if visitall,
+      visit all Voronoi ridges for vertex (i.e., an input site)
+    else
+      visit all unvisited Voronoi ridges for vertex
+      all vertex->seen= False if unvisited
+    assumes
+      all facet->seen= False
+      all facet->seen2= True (for qh_detvridge3)
+      all facet->visitid == 0 if vertex_at_infinity
+                         == index of Voronoi vertex 
+                         >= qh.num_facets if ignored
+    innerouter:
+      qh_RIDGEall--  both inner (bounded) and outer (unbounded) ridges
+      qh_RIDGEinner- only inner
+      qh_RIDGEouter- only outer
+      
+    if inorder
+      orders vertices for 3-d Voronoi diagrams
+  
+  returns:
+    number of visited ridges (does not include previously visited ridges)
+    
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers)
+        fp== any pointer (assumes FILE*)
+        vertex,vertexA= pair of input sites that define a Voronoi ridge
+        centers= set of facets (i.e., Voronoi vertices)
+                 ->visitid == index or 0 if vertex_at_infinity
+                 ordered for 3-d Voronoi diagram
+  notes:
+    uses qh.vertex_visit
+  
+  see:
+    qh_eachvoronoi_all()
+  
+  design:
+    mark selected neighbors of atvertex
+    for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
+      for each unvisited vertex 
+        if atvertex and vertex share more than d-1 neighbors
+          bump totalcount
+          if printvridge defined
+            build the set of shared neighbors (i.e., Voronoi vertices)
+            call printvridge
+*/
+int qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
+  boolT unbounded;
+  int count;
+  facetT *neighbor, **neighborp, *neighborA, **neighborAp;
+  setT *centers;
+  setT *tricenters= qh_settemp (qh TEMPsize);
+
+  vertexT *vertex, **vertexp;
+  boolT firstinf;
+  unsigned int numfacets= (unsigned int)qh num_facets;
+  int totridges= 0;
+
+  qh vertex_visit++;
+  atvertex->seen= True;
+  if (visitall) {
+    FORALLvertices 
+      vertex->seen= False;
+  }
+  FOREACHneighbor_(atvertex) {
+    if (neighbor->visitid < numfacets) 
+      neighbor->seen= True;
+  }
+  FOREACHneighbor_(atvertex) {
+    if (neighbor->seen) {
+      FOREACHvertex_(neighbor->vertices) {
+        if (vertex->visitid != qh vertex_visit && !vertex->seen) {
+	  vertex->visitid= qh vertex_visit;
+          count= 0;
+          firstinf= True;
+	  qh_settruncate (tricenters, 0);
+          FOREACHneighborA_(vertex) {
+            if (neighborA->seen) {
+	      if (neighborA->visitid) {
+		if (!neighborA->tricoplanar || qh_setunique (&tricenters, neighborA->center))
+		  count++;
+              }else if (firstinf) {
+                count++;
+                firstinf= False;
+	      }
+	    }
+          }
+          if (count >= qh hull_dim - 1) {  /* e.g., 3 for 3-d Voronoi */
+            if (firstinf) {
+              if (innerouter == qh_RIDGEouter)
+                continue;
+              unbounded= False;
+            }else {
+              if (innerouter == qh_RIDGEinner)
+                continue;
+              unbounded= True;
+            }
+            totridges++;
+            trace4((qh ferr, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
+                  count, qh_pointid (atvertex->point), qh_pointid (vertex->point)));
+            if (printvridge) { 
+	      if (inorder && qh hull_dim == 3+1) /* 3-d Voronoi diagram */
+                centers= qh_detvridge3 (atvertex, vertex);
+	      else
+                centers= qh_detvridge (vertex);
+              (*printvridge) (fp, atvertex, vertex, centers, unbounded);
+              qh_settempfree (¢ers);
+            }
+          }
+        }
+      }
+    }
+  }
+  FOREACHneighbor_(atvertex) 
+    neighbor->seen= False;
+  qh_settempfree (&tricenters);
+  return totridges;
+} /* eachvoronoi */
+  
+
+/*---------------------------------
+  
+  qh_eachvoronoi_all( fp, printvridge, isupper, innerouter, inorder )
+    visit all Voronoi ridges
+    
+    innerouter:
+      see qh_eachvoronoi()
+      
+    if inorder
+      orders vertices for 3-d Voronoi diagrams
+    
+  returns
+    total number of ridges 
+
+    if isupper == facet->upperdelaunay  (i.e., a Vornoi vertex)
+      facet->visitid= Voronoi vertex index (same as 'o' format)
+    else 
+      facet->visitid= 0
+
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers)
+      [see qh_eachvoronoi]
+      
+  notes:
+    Not used for qhull.exe
+    same effect as qh_printvdiagram but ridges not sorted by point id
+*/
+int qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder) {
+  facetT *facet;
+  vertexT *vertex;
+  int numcenters= 1;  /* vertex 0 is vertex-at-infinity */
+  int totridges= 0;
+
+  qh_clearcenters (qh_ASvoronoi);
+  qh_vertexneighbors();
+  maximize_(qh visit_id, (unsigned) qh num_facets);
+  FORALLfacets {
+    facet->visitid= 0;
+    facet->seen= False;
+    facet->seen2= True;
+  }
+  FORALLfacets {
+    if (facet->upperdelaunay == isupper)
+      facet->visitid= numcenters++;
+  }
+  FORALLvertices 
+    vertex->seen= False;
+  FORALLvertices {
+    if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
+      continue;
+    totridges += qh_eachvoronoi (fp, printvridge, vertex, 
+                   !qh_ALL, innerouter, inorder);
+  }
+  return totridges;
+} /* eachvoronoi_all */
+      
+/*---------------------------------
+  
+  qh_facet2point( facet, point0, point1, mindist )
+    return two projected temporary vertices for a 2-d facet
+    may be non-simplicial
+
+  returns:
+    point0 and point1 oriented and projected to the facet
+    returns mindist (maximum distance below plane)
+*/
+void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
+  vertexT *vertex0, *vertex1;
+  realT dist;
+  
+  if (facet->toporient ^ qh_ORIENTclock) {
+    vertex0= SETfirstt_(facet->vertices, vertexT);
+    vertex1= SETsecondt_(facet->vertices, vertexT);
+  }else {
+    vertex1= SETfirstt_(facet->vertices, vertexT);
+    vertex0= SETsecondt_(facet->vertices, vertexT);
+  }
+  zadd_(Zdistio, 2);
+  qh_distplane(vertex0->point, facet, &dist);
+  *mindist= dist;
+  *point0= qh_projectpoint(vertex0->point, facet, dist);
+  qh_distplane(vertex1->point, facet, &dist);
+  minimize_(*mindist, dist);		
+  *point1= qh_projectpoint(vertex1->point, facet, dist);
+} /* facet2point */
+
+
+/*---------------------------------
+  
+  qh_facetvertices( facetlist, facets, allfacets )
+    returns temporary set of vertices in a set and/or list of facets
+    if allfacets, ignores qh_skipfacet()
+
+  returns:
+    vertices with qh.vertex_visit
+    
+  notes:
+    optimized for allfacets of facet_list
+
+  design:
+    if allfacets of facet_list
+      create vertex set from vertex_list
+    else
+      for each selected facet in facets or facetlist
+        append unvisited vertices to vertex set
+*/
+setT *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets) {
+  setT *vertices;
+  facetT *facet, **facetp;
+  vertexT *vertex, **vertexp;
+
+  qh vertex_visit++;
+  if (facetlist == qh facet_list && allfacets && !facets) {
+    vertices= qh_settemp (qh num_vertices);
+    FORALLvertices {
+      vertex->visitid= qh vertex_visit; 
+      qh_setappend (&vertices, vertex);
+    }
+  }else {
+    vertices= qh_settemp (qh TEMPsize);
+    FORALLfacet_(facetlist) {
+      if (!allfacets && qh_skipfacet (facet))
+        continue;
+      FOREACHvertex_(facet->vertices) {
+        if (vertex->visitid != qh vertex_visit) {
+          vertex->visitid= qh vertex_visit;
+          qh_setappend (&vertices, vertex);
+        }
+      }
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (!allfacets && qh_skipfacet (facet))
+      continue;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        vertex->visitid= qh vertex_visit;
+        qh_setappend (&vertices, vertex);
+      }
+    }
+  }
+  return vertices;
+} /* facetvertices */
+
+/*---------------------------------
+  
+  qh_geomplanes( facet, outerplane, innerplane )
+    return outer and inner planes for Geomview 
+    qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
+
+  notes:
+    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+*/
+void qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane) {
+  realT radius;
+
+  if (qh MERGING || qh JOGGLEmax < REALmax/2) {
+    qh_outerinner (facet, outerplane, innerplane);
+    radius= qh PRINTradius;
+    if (qh JOGGLEmax < REALmax/2)
+      radius -= qh JOGGLEmax * sqrt (qh hull_dim);  /* already accounted for in qh_outerinner() */
+    *outerplane += radius;
+    *innerplane -= radius;
+    if (qh PRINTcoplanar || qh PRINTspheres) {
+      *outerplane += qh MAXabs_coord * qh_GEOMepsilon;
+      *innerplane -= qh MAXabs_coord * qh_GEOMepsilon;
+    }
+  }else 
+    *innerplane= *outerplane= 0;
+} /* geomplanes */
+
+
+/*---------------------------------
+  
+  qh_markkeep( facetlist )
+    mark good facets that meet qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
+    ignores visible facets (not part of convex hull)
+
+  returns:
+    may clear facet->good
+    recomputes qh.num_good
+
+  design:
+    get set of good facets
+    if qh.KEEParea
+      sort facets by area
+      clear facet->good for all but n largest facets
+    if qh.KEEPmerge
+      sort facets by merge count
+      clear facet->good for all but n most merged facets
+    if qh.KEEPminarea
+      clear facet->good if area too small
+    update qh.num_good    
+*/
+void qh_markkeep (facetT *facetlist) {
+  facetT *facet, **facetp;
+  setT *facets= qh_settemp (qh num_facets);
+  int size, count;
+
+  trace2((qh ferr, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
+          qh KEEParea, qh KEEPmerge, qh KEEPminArea));
+  FORALLfacet_(facetlist) {
+    if (!facet->visible && facet->good)
+      qh_setappend (&facets, facet);
+  }
+  size= qh_setsize (facets);
+  if (qh KEEParea) {
+    qsort (SETaddr_(facets, facetT), size,
+             sizeof (facetT *), qh_compare_facetarea);
+    if ((count= size - qh KEEParea) > 0) {
+      FOREACHfacet_(facets) {
+        facet->good= False;
+        if (--count == 0)
+          break;
+      }
+    }
+  }
+  if (qh KEEPmerge) {
+    qsort (SETaddr_(facets, facetT), size,
+             sizeof (facetT *), qh_compare_facetmerge);
+    if ((count= size - qh KEEPmerge) > 0) {
+      FOREACHfacet_(facets) {
+        facet->good= False;
+        if (--count == 0)
+          break;
+      }
+    }
+  }
+  if (qh KEEPminArea < REALmax/2) {
+    FOREACHfacet_(facets) {
+      if (!facet->isarea || facet->f.area < qh KEEPminArea)
+	facet->good= False;
+    }
+  }
+  qh_settempfree (&facets);
+  count= 0;
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      count++;
+  }
+  qh num_good= count;
+} /* markkeep */
+
+
+/*---------------------------------
+  
+  qh_markvoronoi( facetlist, facets, printall, islower, numcenters )
+    mark voronoi vertices for printing by site pairs
+  
+  returns:
+    temporary set of vertices indexed by pointid
+    islower set if printing lower hull (i.e., at least one facet is lower hull)
+    numcenters= total number of Voronoi vertices
+    bumps qh.printoutnum for vertex-at-infinity
+    clears all facet->seen and sets facet->seen2
+    
+    if selected
+      facet->visitid= Voronoi vertex id
+    else if upper hull (or 'Qu' and lower hull)
+      facet->visitid= 0
+    else
+      facet->visitid >= qh num_facets
+  
+  notes:
+    ignores qh.ATinfinity, if defined
+*/
+setT *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp) {
+  int numcenters=0;
+  facetT *facet, **facetp;
+  setT *vertices;
+  boolT islower= False;
+
+  qh printoutnum++;
+  qh_clearcenters (qh_ASvoronoi);  /* in case, qh_printvdiagram2 called by user */
+  qh_vertexneighbors();
+  vertices= qh_pointvertex();
+  if (qh ATinfinity) 
+    SETelem_(vertices, qh num_points-1)= NULL;
+  qh visit_id++;
+  maximize_(qh visit_id, (unsigned) qh num_facets);
+  FORALLfacet_(facetlist) { 
+    if (printall || !qh_skipfacet (facet)) {
+      if (!facet->upperdelaunay) {
+        islower= True;
+	break;
+      }
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (printall || !qh_skipfacet (facet)) {
+      if (!facet->upperdelaunay) {
+        islower= True;
+	break;
+      }
+    }
+  }
+  FORALLfacets {
+    if (facet->normal && (facet->upperdelaunay == islower))
+      facet->visitid= 0;  /* facetlist or facets may overwrite */
+    else
+      facet->visitid= qh visit_id;
+    facet->seen= False;
+    facet->seen2= True;
+  }
+  numcenters++;  /* qh_INFINITE */
+  FORALLfacet_(facetlist) {
+    if (printall || !qh_skipfacet (facet))
+      facet->visitid= numcenters++;
+  }
+  FOREACHfacet_(facets) {
+    if (printall || !qh_skipfacet (facet))
+      facet->visitid= numcenters++;  
+  }
+  *islowerp= islower;
+  *numcentersp= numcenters;
+  trace2((qh ferr, "qh_markvoronoi: islower %d numcenters %d\n", islower, numcenters));
+  return vertices;
+} /* markvoronoi */
+
+/*---------------------------------
+  
+  qh_order_vertexneighbors( vertex )
+    order facet neighbors of a 2-d or 3-d vertex by adjacency
+
+  notes:
+    does not orient the neighbors
+
+  design:
+    initialize a new neighbor set with the first facet in vertex->neighbors
+    while vertex->neighbors non-empty
+      select next neighbor in the previous facet's neighbor set
+    set vertex->neighbors to the new neighbor set
+*/
+void qh_order_vertexneighbors(vertexT *vertex) {
+  setT *newset;
+  facetT *facet, *neighbor, **neighborp;
+
+  trace4((qh ferr, "qh_order_vertexneighbors: order neighbors of v%d for 3-d\n", vertex->id));
+  newset= qh_settemp (qh_setsize (vertex->neighbors));
+  facet= (facetT*)qh_setdellast (vertex->neighbors);
+  qh_setappend (&newset, facet);
+  while (qh_setsize (vertex->neighbors)) {
+    FOREACHneighbor_(vertex) {
+      if (qh_setin (facet->neighbors, neighbor)) {
+        qh_setdel(vertex->neighbors, neighbor);
+        qh_setappend (&newset, neighbor);
+        facet= neighbor;
+        break;
+      }
+    }
+    if (!neighbor) {
+      fprintf (qh ferr, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
+        vertex->id, facet->id);
+      qh_errexit (qh_ERRqhull, facet, NULL);
+    }
+  }
+  qh_setfree (&vertex->neighbors);
+  qh_settemppop ();
+  vertex->neighbors= newset;
+} /* order_vertexneighbors */
+
+/*---------------------------------
+  
+  qh_printafacet( fp, format, facet, printall )
+    print facet to fp in given output format (see qh.PRINTout)
+
+  returns:
+    nop if !printall and qh_skipfacet()
+    nop if visible facet and NEWfacets and format != PRINTfacets
+    must match qh_countfacets
+
+  notes
+    preserves qh.visit_id
+    facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
+
+  see
+    qh_printbegin() and qh_printend()
+
+  design:
+    test for printing facet
+    call appropriate routine for format
+    or output results directly
+*/
+void qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall) {
+  realT color[4], offset, dist, outerplane, innerplane;
+  boolT zerodiv;
+  coordT *point, *normp, *coordp, **pointp, *feasiblep;
+  int k;
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+
+  if (!printall && qh_skipfacet (facet))
+    return;
+  if (facet->visible && qh NEWfacets && format != qh_PRINTfacets)
+    return;
+  qh printoutnum++;
+  switch (format) {
+  case qh_PRINTarea:
+    if (facet->isarea) {
+      fprintf (fp, qh_REAL_1, facet->f.area);
+      fprintf (fp, "\n");
+    }else
+      fprintf (fp, "0\n");
+    break;
+  case qh_PRINTcoplanars:
+    fprintf (fp, "%d", qh_setsize (facet->coplanarset));
+    FOREACHpoint_(facet->coplanarset)
+      fprintf (fp, " %d", qh_pointid (point));
+    fprintf (fp, "\n");
+    break;
+  case qh_PRINTcentrums:
+    qh_printcenter (fp, format, NULL, facet);
+    break;
+  case qh_PRINTfacets:
+    qh_printfacet (fp, facet);
+    break;
+  case qh_PRINTfacets_xridge:
+    qh_printfacetheader (fp, facet);
+    break;
+  case qh_PRINTgeom:  /* either 2 , 3, or 4-d by qh_printbegin */
+    if (!facet->normal)
+      break;
+    for (k= qh hull_dim; k--; ) {
+      color[k]= (facet->normal[k]+1.0)/2.0;
+      maximize_(color[k], -1.0);
+      minimize_(color[k], +1.0);
+    }
+    qh_projectdim3 (color, color);
+    if (qh PRINTdim != qh hull_dim)
+      qh_normalize2 (color, 3, True, NULL, NULL);
+    if (qh hull_dim <= 2)
+      qh_printfacet2geom (fp, facet, color);
+    else if (qh hull_dim == 3) {
+      if (facet->simplicial)
+        qh_printfacet3geom_simplicial (fp, facet, color);
+      else
+        qh_printfacet3geom_nonsimplicial (fp, facet, color);
+    }else {
+      if (facet->simplicial)
+        qh_printfacet4geom_simplicial (fp, facet, color);
+      else
+        qh_printfacet4geom_nonsimplicial (fp, facet, color);
+    }
+    break;
+  case qh_PRINTids:
+    fprintf (fp, "%d\n", facet->id);
+    break;
+  case qh_PRINTincidences:
+  case qh_PRINToff:
+  case qh_PRINTtriangles:
+    if (qh hull_dim == 3 && format != qh_PRINTtriangles) 
+      qh_printfacet3vertex (fp, facet, format);
+    else if (facet->simplicial || qh hull_dim == 2 || format == qh_PRINToff)
+      qh_printfacetNvertex_simplicial (fp, facet, format);
+    else
+      qh_printfacetNvertex_nonsimplicial (fp, facet, qh printoutvar++, format);
+    break;
+  case qh_PRINTinner:
+    qh_outerinner (facet, NULL, &innerplane);
+    offset= facet->offset - innerplane;
+    goto LABELprintnorm;
+    break; /* prevent warning */
+  case qh_PRINTmerges:
+    fprintf (fp, "%d\n", facet->nummerge);
+    break;
+  case qh_PRINTnormals:
+    offset= facet->offset;
+    goto LABELprintnorm;
+    break; /* prevent warning */
+  case qh_PRINTouter:
+    qh_outerinner (facet, &outerplane, NULL);
+    offset= facet->offset - outerplane;
+  LABELprintnorm:
+    if (!facet->normal) {
+      fprintf (fp, "no normal for facet f%d\n", facet->id);
+      break;
+    }
+    if (qh CDDoutput) {
+      fprintf (fp, qh_REAL_1, -offset);
+      for (k=0; k < qh hull_dim; k++) 
+	fprintf (fp, qh_REAL_1, -facet->normal[k]);
+    }else {
+      for (k=0; k < qh hull_dim; k++) 
+	fprintf (fp, qh_REAL_1, facet->normal[k]);
+      fprintf (fp, qh_REAL_1, offset);
+    }
+    fprintf (fp, "\n");
+    break;
+  case qh_PRINTmathematica:  /* either 2 or 3-d by qh_printbegin */
+  case qh_PRINTmaple:
+    if (qh hull_dim == 2)
+      qh_printfacet2math (fp, facet, format, qh printoutvar++);
+    else 
+      qh_printfacet3math (fp, facet, format, qh printoutvar++);
+    break;
+  case qh_PRINTneighbors:
+    fprintf (fp, "%d", qh_setsize (facet->neighbors));
+    FOREACHneighbor_(facet)
+      fprintf (fp, " %d", 
+	       neighbor->visitid ? neighbor->visitid - 1: - neighbor->id);
+    fprintf (fp, "\n");
+    break;
+  case qh_PRINTpointintersect:
+    if (!qh feasible_point) {
+      fprintf (fp, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n");
+      qh_errexit( qh_ERRinput, NULL, NULL);
+    }
+    if (facet->offset > 0)
+      goto LABELprintinfinite;
+    point= coordp= (coordT*)qh_memalloc (qh normal_size);
+    normp= facet->normal;
+    feasiblep= qh feasible_point;
+    if (facet->offset < -qh MINdenom) {
+      for (k= qh hull_dim; k--; )
+        *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
+    }else {
+      for (k= qh hull_dim; k--; ) {
+        *(coordp++)= qh_divzero (*(normp++), facet->offset, qh MINdenom_1,
+				 &zerodiv) + *(feasiblep++);
+        if (zerodiv) {
+          qh_memfree (point, qh normal_size);
+          goto LABELprintinfinite;
+        }
+      }
+    }
+    qh_printpoint (fp, NULL, point);
+    qh_memfree (point, qh normal_size);
+    break;
+  LABELprintinfinite:
+    for (k= qh hull_dim; k--; )
+      fprintf (fp, qh_REAL_1, qh_INFINITE);
+    fprintf (fp, "\n");   
+    break;
+  case qh_PRINTpointnearest:
+    FOREACHpoint_(facet->coplanarset) {
+      int id, id2;
+      vertex= qh_nearvertex (facet, point, &dist);
+      id= qh_pointid (vertex->point);
+      id2= qh_pointid (point);
+      fprintf (fp, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
+    }
+    break;
+  case qh_PRINTpoints:  /* VORONOI only by qh_printbegin */
+    if (qh CDDoutput)
+      fprintf (fp, "1 ");
+    qh_printcenter (fp, format, NULL, facet);
+    break;
+  case qh_PRINTvertices:
+    fprintf (fp, "%d", qh_setsize (facet->vertices));
+    FOREACHvertex_(facet->vertices)
+      fprintf (fp, " %d", qh_pointid (vertex->point));
+    fprintf (fp, "\n");
+    break;
+  }
+} /* printafacet */
+
+/*---------------------------------
+  
+  qh_printbegin(  )
+    prints header for all output formats
+
+  returns:
+    checks for valid format
+  
+  notes:
+    uses qh.visit_id for 3/4off
+    changes qh.interior_point if printing centrums
+    qh_countfacets clears facet->visitid for non-good facets
+    
+  see
+    qh_printend() and qh_printafacet()
+    
+  design:
+    count facets and related statistics
+    print header for format
+*/
+void qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+  int i, num;
+  facetT *facet, **facetp;
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+  pointT *point, **pointp, *pointtemp;
+
+  qh printoutnum= 0;
+  qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, 
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+  switch (format) {
+  case qh_PRINTnone:
+    break;
+  case qh_PRINTarea:
+    fprintf (fp, "%d\n", numfacets);
+    break;
+  case qh_PRINTcoplanars:
+    fprintf (fp, "%d\n", numfacets);
+    break;
+  case qh_PRINTcentrums:
+    if (qh CENTERtype == qh_ASnone)
+      qh_clearcenters (qh_AScentrum);
+    fprintf (fp, "%d\n%d\n", qh hull_dim, numfacets);
+    break;
+  case qh_PRINTfacets:
+  case qh_PRINTfacets_xridge:
+    if (facetlist)
+      qh_printvertexlist (fp, "Vertices and facets:\n", facetlist, facets, printall);
+    break;
+  case qh_PRINTgeom: 
+    if (qh hull_dim > 4)  /* qh_initqhull_globals also checks */
+      goto LABELnoformat;
+    if (qh VORONOI && qh hull_dim > 3)  /* PRINTdim == DROPdim == hull_dim-1 */
+      goto LABELnoformat;
+    if (qh hull_dim == 2 && (qh PRINTridges || qh DOintersections))
+      fprintf (qh ferr, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
+    if (qh hull_dim == 4 && (qh PRINTinner || qh PRINTouter ||
+			     (qh PRINTdim == 4 && qh PRINTcentrums)))
+      fprintf (qh ferr, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
+    if (qh PRINTdim == 4 && (qh PRINTspheres))
+      fprintf (qh ferr, "qhull warning: output for vertices not implemented in 4-d\n");
+    if (qh PRINTdim == 4 && qh DOintersections && qh PRINTnoplanes)
+      fprintf (qh ferr, "qhull warning: 'Gnh' generates no output in 4-d\n");
+    if (qh PRINTdim == 2) {
+      fprintf(fp, "{appearance {linewidth 3} LIST # %s | %s\n",
+	      qh rbox_command, qh qhull_command);
+    }else if (qh PRINTdim == 3) {
+      fprintf(fp, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
+	      qh rbox_command, qh qhull_command);
+    }else if (qh PRINTdim == 4) {
+      qh visit_id++;
+      num= 0;
+      FORALLfacet_(facetlist)    /* get number of ridges to be printed */
+        qh_printend4geom (NULL, facet, &num, printall);
+      FOREACHfacet_(facets)
+        qh_printend4geom (NULL, facet, &num, printall);
+      qh ridgeoutnum= num;
+      qh printoutvar= 0;  /* counts number of ridges in output */
+      fprintf (fp, "LIST # %s | %s\n", qh rbox_command, qh qhull_command);
+    }
+    if (qh PRINTdots) {
+      qh printoutnum++;
+      num= qh num_points + qh_setsize (qh other_points);
+      if (qh DELAUNAY && qh ATinfinity)
+	num--;
+      if (qh PRINTdim == 4)
+        fprintf (fp, "4VECT %d %d 1\n", num, num);
+      else
+	fprintf (fp, "VECT %d %d 1\n", num, num);
+      for (i= num; i--; ) {
+        if (i % 20 == 0)
+          fprintf (fp, "\n");
+	fprintf (fp, "1 ");
+      }
+      fprintf (fp, "# 1 point per line\n1 ");
+      for (i= num-1; i--; ) {
+        if (i % 20 == 0)
+          fprintf (fp, "\n");
+	fprintf (fp, "0 ");
+      }
+      fprintf (fp, "# 1 color for all\n");
+      FORALLpoints {
+        if (!qh DELAUNAY || !qh ATinfinity || qh_pointid(point) != qh num_points-1) {
+	  if (qh PRINTdim == 4)
+	    qh_printpoint (fp, NULL, point);
+	  else
+	    qh_printpoint3 (fp, point);
+	}
+      }
+      FOREACHpoint_(qh other_points) {
+	if (qh PRINTdim == 4)
+	  qh_printpoint (fp, NULL, point);
+	else
+	  qh_printpoint3 (fp, point);
+      }
+      fprintf (fp, "0 1 1 1  # color of points\n");
+    }
+    if (qh PRINTdim == 4  && !qh PRINTnoplanes)
+      /* 4dview loads up multiple 4OFF objects slowly */
+      fprintf(fp, "4OFF %d %d 1\n", 3*qh ridgeoutnum, qh ridgeoutnum);
+    qh PRINTcradius= 2 * qh DISTround;  /* include test DISTround */
+    if (qh PREmerge) {
+      maximize_(qh PRINTcradius, qh premerge_centrum + qh DISTround);
+    }else if (qh POSTmerge)
+      maximize_(qh PRINTcradius, qh postmerge_centrum + qh DISTround);
+    qh PRINTradius= qh PRINTcradius;
+    if (qh PRINTspheres + qh PRINTcoplanar)
+      maximize_(qh PRINTradius, qh MAXabs_coord * qh_MINradius);
+    if (qh premerge_cos < REALmax/2) {
+      maximize_(qh PRINTradius, (1- qh premerge_cos) * qh MAXabs_coord);
+    }else if (!qh PREmerge && qh POSTmerge && qh postmerge_cos < REALmax/2) {
+      maximize_(qh PRINTradius, (1- qh postmerge_cos) * qh MAXabs_coord);
+    }
+    maximize_(qh PRINTradius, qh MINvisible); 
+    if (qh JOGGLEmax < REALmax/2)
+      qh PRINTradius += qh JOGGLEmax * sqrt (qh hull_dim);
+    if (qh PRINTdim != 4 &&
+	(qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
+      vertices= qh_facetvertices (facetlist, facets, printall);
+      if (qh PRINTspheres && qh PRINTdim <= 3)
+         qh_printspheres (fp, vertices, qh PRINTradius);
+      if (qh PRINTcoplanar || qh PRINTcentrums) {
+        qh firstcentrum= True;
+        if (qh PRINTcoplanar&& !qh PRINTspheres) {
+          FOREACHvertex_(vertices) 
+            qh_printpointvect2 (fp, vertex->point, NULL,
+				qh interior_point, qh PRINTradius);
+	}
+        FORALLfacet_(facetlist) {
+	  if (!printall && qh_skipfacet(facet))
+	    continue;
+	  if (!facet->normal)
+	    continue;
+          if (qh PRINTcentrums && qh PRINTdim <= 3)
+            qh_printcentrum (fp, facet, qh PRINTcradius);
+	  if (!qh PRINTcoplanar)
+	    continue;
+          FOREACHpoint_(facet->coplanarset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+          FOREACHpoint_(facet->outsideset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+        }
+        FOREACHfacet_(facets) {
+	  if (!printall && qh_skipfacet(facet))
+	    continue;
+	  if (!facet->normal)
+	    continue;
+          if (qh PRINTcentrums && qh PRINTdim <= 3)
+            qh_printcentrum (fp, facet, qh PRINTcradius);
+	  if (!qh PRINTcoplanar)
+	    continue;
+          FOREACHpoint_(facet->coplanarset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+          FOREACHpoint_(facet->outsideset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+        }
+      }
+      qh_settempfree (&vertices);
+    }
+    qh visit_id++; /* for printing hyperplane intersections */
+    break;
+  case qh_PRINTids:
+    fprintf (fp, "%d\n", numfacets);
+    break;
+  case qh_PRINTincidences:
+    if (qh VORONOI && qh PRINTprecision)
+      fprintf (qh ferr, "qhull warning: writing Delaunay.  Use 'p' or 'o' for Voronoi centers\n");
+    qh printoutvar= qh vertex_id;  /* centrum id for non-simplicial facets */
+    if (qh hull_dim <= 3)
+      fprintf(fp, "%d\n", numfacets);
+    else
+      fprintf(fp, "%d\n", numsimplicial+numridges);
+    break;
+  case qh_PRINTinner:
+  case qh_PRINTnormals:
+  case qh_PRINTouter:
+    if (qh CDDoutput)
+      fprintf (fp, "%s | %s\nbegin\n    %d %d real\n", qh rbox_command, 
+              qh qhull_command, numfacets, qh hull_dim+1);
+    else
+      fprintf (fp, "%d\n%d\n", qh hull_dim+1, numfacets);
+    break;
+  case qh_PRINTmathematica:  
+  case qh_PRINTmaple:
+    if (qh hull_dim > 3)  /* qh_initbuffers also checks */
+      goto LABELnoformat;
+    if (qh VORONOI)
+      fprintf (qh ferr, "qhull warning: output is the Delaunay triangulation\n");
+    if (format == qh_PRINTmaple) {
+      if (qh hull_dim == 2)
+	fprintf(fp, "PLOT(CURVES(\n");
+      else
+	fprintf(fp, "PLOT3D(POLYGONS(\n");
+    }else
+      fprintf(fp, "{\n");
+    qh printoutvar= 0;   /* counts number of facets for notfirst */
+    break;
+  case qh_PRINTmerges:
+    fprintf (fp, "%d\n", numfacets);
+    break;
+  case qh_PRINTpointintersect:
+    fprintf (fp, "%d\n%d\n", qh hull_dim, numfacets);
+    break;
+  case qh_PRINTneighbors:
+    fprintf (fp, "%d\n", numfacets);
+    break;
+  case qh_PRINToff:
+  case qh_PRINTtriangles:
+    if (qh VORONOI)
+      goto LABELnoformat;
+    num = qh hull_dim;
+    if (format == qh_PRINToff || qh hull_dim == 2)
+      fprintf (fp, "%d\n%d %d %d\n", num, 
+        qh num_points+qh_setsize (qh other_points), numfacets, totneighbors/2);
+    else { /* qh_PRINTtriangles */
+      qh printoutvar= qh num_points+qh_setsize (qh other_points); /* first centrum */
+      if (qh DELAUNAY)
+        num--;  /* drop last dimension */
+      fprintf (fp, "%d\n%d %d %d\n", num, qh printoutvar 
+	+ numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
+    }
+    FORALLpoints
+      qh_printpointid (qh fout, NULL, num, point, -1);
+    FOREACHpoint_(qh other_points)
+      qh_printpointid (qh fout, NULL, num, point, -1);
+    if (format == qh_PRINTtriangles && qh hull_dim > 2) {
+      FORALLfacets {
+	if (!facet->simplicial && facet->visitid)
+          qh_printcenter (qh fout, format, NULL, facet);
+      }
+    }
+    break;
+  case qh_PRINTpointnearest:
+    fprintf (fp, "%d\n", numcoplanars);
+    break;
+  case qh_PRINTpoints:
+    if (!qh VORONOI)
+      goto LABELnoformat;
+    if (qh CDDoutput)
+      fprintf (fp, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
+             qh qhull_command, numfacets, qh hull_dim);
+    else
+      fprintf (fp, "%d\n%d\n", qh hull_dim-1, numfacets);
+    break;
+  case qh_PRINTvertices:
+    fprintf (fp, "%d\n", numfacets);
+    break;
+  case qh_PRINTsummary:
+  default:
+  LABELnoformat:
+    fprintf (qh ferr, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
+         qh hull_dim);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+} /* printbegin */
+
+/*---------------------------------
+  
+  qh_printcenter( fp, string, facet )
+    print facet->center as centrum or Voronoi center
+    string may be NULL.  Don't include '%' codes.
+    nop if qh CENTERtype neither CENTERvoronoi nor CENTERcentrum
+    if upper envelope of Delaunay triangulation and point at-infinity
+      prints qh_INFINITE instead;
+
+  notes:
+    defines facet->center if needed
+    if format=PRINTgeom, adds a 0 if would otherwise be 2-d
+*/
+void qh_printcenter (FILE *fp, int format, char *string, facetT *facet) {
+  int k, num;
+
+  if (qh CENTERtype != qh_ASvoronoi && qh CENTERtype != qh_AScentrum)
+    return;
+  if (string)
+    fprintf (fp, string, facet->id);
+  if (qh CENTERtype == qh_ASvoronoi) {
+    num= qh hull_dim-1;
+    if (!facet->normal || !facet->upperdelaunay || !qh ATinfinity) {
+      if (!facet->center)
+        facet->center= qh_facetcenter (facet->vertices);
+      for (k=0; k < num; k++)
+        fprintf (fp, qh_REAL_1, facet->center[k]);
+    }else {
+      for (k=0; k < num; k++)
+        fprintf (fp, qh_REAL_1, qh_INFINITE);
+    }
+  }else /* qh CENTERtype == qh_AScentrum */ {
+    num= qh hull_dim;
+    if (format == qh_PRINTtriangles && qh DELAUNAY) 
+      num--;
+    if (!facet->center) 
+      facet->center= qh_getcentrum (facet);
+    for (k=0; k < num; k++)
+      fprintf (fp, qh_REAL_1, facet->center[k]);
+  }
+  if (format == qh_PRINTgeom && num == 2)
+    fprintf (fp, " 0\n");
+  else
+    fprintf (fp, "\n");
+} /* printcenter */
+
+/*---------------------------------
+  
+  qh_printcentrum( fp, facet, radius )
+    print centrum for a facet in OOGL format
+    radius defines size of centrum
+    2-d or 3-d only
+
+  returns:
+    defines facet->center if needed
+*/
+void qh_printcentrum (FILE *fp, facetT *facet, realT radius) {
+  pointT *centrum, *projpt;
+  boolT tempcentrum= False;
+  realT xaxis[4], yaxis[4], normal[4], dist;
+  realT green[3]={0, 1, 0};
+  vertexT *apex;
+  int k;
+  
+  if (qh CENTERtype == qh_AScentrum) {
+    if (!facet->center)
+      facet->center= qh_getcentrum (facet);
+    centrum= facet->center;
+  }else {
+    centrum= qh_getcentrum (facet);
+    tempcentrum= True;
+  }
+  fprintf (fp, "{appearance {-normal -edge normscale 0} ");
+  if (qh firstcentrum) {
+    qh firstcentrum= False;
+    fprintf (fp, "{INST geom { define centrum CQUAD  # f%d\n\
+-0.3 -0.3 0.0001     0 0 1 1\n\
+ 0.3 -0.3 0.0001     0 0 1 1\n\
+ 0.3  0.3 0.0001     0 0 1 1\n\
+-0.3  0.3 0.0001     0 0 1 1 } transform { \n", facet->id);
+  }else
+    fprintf (fp, "{INST geom { : centrum } transform { # f%d\n", facet->id);
+  apex= SETfirstt_(facet->vertices, vertexT);
+  qh_distplane(apex->point, facet, &dist);
+  projpt= qh_projectpoint(apex->point, facet, dist);
+  for (k= qh hull_dim; k--; ) {
+    xaxis[k]= projpt[k] - centrum[k];
+    normal[k]= facet->normal[k];
+  }
+  if (qh hull_dim == 2) {
+    xaxis[2]= 0;
+    normal[2]= 0;
+  }else if (qh hull_dim == 4) {
+    qh_projectdim3 (xaxis, xaxis);
+    qh_projectdim3 (normal, normal);
+    qh_normalize2 (normal, qh PRINTdim, True, NULL, NULL);
+  }
+  qh_crossproduct (3, xaxis, normal, yaxis);
+  fprintf (fp, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
+  fprintf (fp, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
+  fprintf (fp, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
+  qh_printpoint3 (fp, centrum);
+  fprintf (fp, "1 }}}\n"); 
+  qh_memfree (projpt, qh normal_size);
+  qh_printpointvect (fp, centrum, facet->normal, NULL, radius, green);
+  if (tempcentrum)
+    qh_memfree (centrum, qh normal_size);
+} /* printcentrum */
+  
+/*---------------------------------
+  
+  qh_printend( fp, format )
+    prints trailer for all output formats
+
+  see:
+    qh_printbegin() and qh_printafacet()
+      
+*/
+void qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+  int num;
+  facetT *facet, **facetp;
+
+  if (!qh printoutnum)
+    fprintf (qh ferr, "qhull warning: no facets printed\n");
+  switch (format) {
+  case qh_PRINTgeom:
+    if (qh hull_dim == 4 && qh DROPdim < 0  && !qh PRINTnoplanes) {
+      qh visit_id++;
+      num= 0;
+      FORALLfacet_(facetlist)
+        qh_printend4geom (fp, facet,&num, printall);
+      FOREACHfacet_(facets) 
+        qh_printend4geom (fp, facet, &num, printall);
+      if (num != qh ridgeoutnum || qh printoutvar != qh ridgeoutnum) {
+	fprintf (qh ferr, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh ridgeoutnum, qh printoutvar, num);
+	qh_errexit (qh_ERRqhull, NULL, NULL);
+      }
+    }else
+      fprintf(fp, "}\n");
+    break;
+  case qh_PRINTinner:
+  case qh_PRINTnormals:
+  case qh_PRINTouter:
+    if (qh CDDoutput) 
+      fprintf (fp, "end\n");
+    break;
+  case qh_PRINTmaple:
+    fprintf(fp, "));\n");
+    break;
+  case qh_PRINTmathematica:
+    fprintf(fp, "}\n");
+    break;
+  case qh_PRINTpoints:
+    if (qh CDDoutput)
+      fprintf (fp, "end\n");
+    break;
+  }
+} /* printend */
+
+/*---------------------------------
+  
+  qh_printend4geom( fp, facet, numridges, printall )
+    helper function for qh_printbegin/printend
+
+  returns:
+    number of printed ridges
+  
+  notes:
+    just counts printed ridges if fp=NULL
+    uses facet->visitid
+    must agree with qh_printfacet4geom...
+
+  design:
+    computes color for facet from its normal
+    prints each ridge of facet 
+*/
+void qh_printend4geom (FILE *fp, facetT *facet, int *nump, boolT printall) {
+  realT color[3];
+  int i, num= *nump;
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  
+  if (!printall && qh_skipfacet(facet))
+    return;
+  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+    return;
+  if (!facet->normal)
+    return;
+  if (fp) {
+    for (i=0; i < 3; i++) {
+      color[i]= (facet->normal[i]+1.0)/2.0;
+      maximize_(color[i], -1.0);
+      minimize_(color[i], +1.0);
+    }
+  }
+  facet->visitid= qh visit_id;
+  if (facet->simplicial) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+	if (fp)
+          fprintf (fp, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
+		 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+		 facet->id, neighbor->id);
+	num++;
+      }
+    }
+  }else {
+    FOREACHridge_(facet->ridges) {
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->visitid != qh visit_id) {
+	if (fp)
+          fprintf (fp, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
+		 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+		 ridge->id, facet->id, neighbor->id);
+	num++;
+      }
+    }
+  }
+  *nump= num;
+} /* printend4geom */
+
+/*---------------------------------
+  
+  qh_printextremes( fp, facetlist, facets, printall )
+    print extreme points for convex hulls or halfspace intersections
+
+  notes:
+    #points, followed by ids, one per line
+    
+    sorted by id
+    same order as qh_printpoints_out if no coplanar/interior points
+*/
+void qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall) {
+  setT *vertices, *points;
+  pointT *point;
+  vertexT *vertex, **vertexp;
+  int id;
+  int numpoints=0, point_i, point_n;
+  int allpoints= qh num_points + qh_setsize (qh other_points);
+
+  points= qh_settemp (allpoints);
+  qh_setzero (points, 0, allpoints);
+  vertices= qh_facetvertices (facetlist, facets, printall);
+  FOREACHvertex_(vertices) {
+    id= qh_pointid (vertex->point);
+    if (id >= 0) {
+      SETelem_(points, id)= vertex->point;
+      numpoints++;
+    }
+  }
+  qh_settempfree (&vertices);
+  fprintf (fp, "%d\n", numpoints);
+  FOREACHpoint_i_(points) {
+    if (point) 
+      fprintf (fp, "%d\n", point_i);
+  }
+  qh_settempfree (&points);
+} /* printextremes */
+
+/*---------------------------------
+  
+  qh_printextremes_2d( fp, facetlist, facets, printall )
+    prints point ids for facets in qh_ORIENTclock order
+
+  notes:
+    #points, followed by ids, one per line
+    if facetlist/facets are disjoint than the output includes skips
+    errors if facets form a loop
+    does not print coplanar points
+*/
+void qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall) {
+  int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
+  setT *vertices;
+  facetT *facet, *startfacet, *nextfacet;
+  vertexT *vertexA, *vertexB;
+
+  qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, 
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh visit_id */
+  vertices= qh_facetvertices (facetlist, facets, printall);
+  fprintf(fp, "%d\n", qh_setsize (vertices));
+  qh_settempfree (&vertices);
+  if (!numfacets)
+    return;
+  facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
+  qh vertex_visit++;
+  qh visit_id++;
+  do {
+    if (facet->toporient ^ qh_ORIENTclock) {
+      vertexA= SETfirstt_(facet->vertices, vertexT);
+      vertexB= SETsecondt_(facet->vertices, vertexT);
+      nextfacet= SETfirstt_(facet->neighbors, facetT);
+    }else {
+      vertexA= SETsecondt_(facet->vertices, vertexT);
+      vertexB= SETfirstt_(facet->vertices, vertexT);
+      nextfacet= SETsecondt_(facet->neighbors, facetT);
+    }
+    if (facet->visitid == qh visit_id) {
+      fprintf(qh ferr, "qh_printextremes_2d: loop in facet list.  facet %d nextfacet %d\n",
+                 facet->id, nextfacet->id);
+      qh_errexit2 (qh_ERRqhull, facet, nextfacet);
+    }
+    if (facet->visitid) {
+      if (vertexA->visitid != qh vertex_visit) {
+	vertexA->visitid= qh vertex_visit;
+	fprintf(fp, "%d\n", qh_pointid (vertexA->point));
+      }
+      if (vertexB->visitid != qh vertex_visit) {
+	vertexB->visitid= qh vertex_visit;
+	fprintf(fp, "%d\n", qh_pointid (vertexB->point));
+      }
+    }
+    facet->visitid= qh visit_id;
+    facet= nextfacet;
+  }while (facet && facet != startfacet);
+} /* printextremes_2d */
+
+/*---------------------------------
+  
+  qh_printextremes_d( fp, facetlist, facets, printall )
+    print extreme points of input sites for Delaunay triangulations
+
+  notes:
+    #points, followed by ids, one per line
+    
+    unordered
+*/
+void qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall) {
+  setT *vertices;
+  vertexT *vertex, **vertexp;
+  boolT upperseen, lowerseen;
+  facetT *neighbor, **neighborp;
+  int numpoints=0;
+
+  vertices= qh_facetvertices (facetlist, facets, printall);
+  qh_vertexneighbors();
+  FOREACHvertex_(vertices) {
+    upperseen= lowerseen= False;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->upperdelaunay)
+        upperseen= True;
+      else
+        lowerseen= True;
+    }
+    if (upperseen && lowerseen) {
+      vertex->seen= True;
+      numpoints++;
+    }else
+      vertex->seen= False;
+  }
+  fprintf (fp, "%d\n", numpoints);
+  FOREACHvertex_(vertices) {
+    if (vertex->seen)
+      fprintf (fp, "%d\n", qh_pointid (vertex->point));
+  }
+  qh_settempfree (&vertices);
+} /* printextremes_d */
+
+/*---------------------------------
+  
+  qh_printfacet( fp, facet )
+    prints all fields of a facet to fp
+
+  notes:
+    ridges printed in neighbor order
+*/
+void qh_printfacet(FILE *fp, facetT *facet) {
+
+  qh_printfacetheader (fp, facet);
+  if (facet->ridges)
+    qh_printfacetridges (fp, facet);
+} /* printfacet */
+
+
+/*---------------------------------
+  
+  qh_printfacet2geom( fp, facet, color )
+    print facet as part of a 2-d VECT for Geomview
+  
+    notes:
+      assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+      mindist is calculated within io.c.  maxoutside is calculated elsewhere
+      so a DISTround error may have occured.
+*/
+void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) {
+  pointT *point0, *point1;
+  realT mindist, innerplane, outerplane;
+  int k;
+
+  qh_facet2point (facet, &point0, &point1, &mindist);
+  qh_geomplanes (facet, &outerplane, &innerplane);
+  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+    qh_printfacet2geom_points(fp, point0, point1, facet, outerplane, color);
+  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+    for(k= 3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet2geom_points(fp, point0, point1, facet, innerplane, color);
+  }
+  qh_memfree (point1, qh normal_size);
+  qh_memfree (point0, qh normal_size); 
+} /* printfacet2geom */
+
+/*---------------------------------
+  
+  qh_printfacet2geom_points( fp, point1, point2, facet, offset, color )
+    prints a 2-d facet as a VECT with 2 points at some offset.   
+    The points are on the facet's plane.
+*/
+void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
+			       facetT *facet, realT offset, realT color[3]) {
+  pointT *p1= point1, *p2= point2;
+
+  fprintf(fp, "VECT 1 2 1 2 1 # f%d\n", facet->id);
+  if (offset != 0.0) {
+    p1= qh_projectpoint (p1, facet, -offset);
+    p2= qh_projectpoint (p2, facet, -offset);
+  }
+  fprintf(fp, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
+           p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
+  if (offset != 0.0) {
+    qh_memfree (p1, qh normal_size);
+    qh_memfree (p2, qh normal_size);
+  }
+  fprintf(fp, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printfacet2geom_points */
+
+
+/*---------------------------------
+  
+  qh_printfacet2math( fp, facet, format, notfirst )
+    print 2-d Maple or Mathematica output for a facet
+    may be non-simplicial
+
+  notes:
+    use %16.8f since Mathematica 2.2 does not handle exponential format
+    see qh_printfacet3math
+*/
+void qh_printfacet2math(FILE *fp, facetT *facet, int format, int notfirst) {
+  pointT *point0, *point1;
+  realT mindist;
+  char *pointfmt;
+  
+  qh_facet2point (facet, &point0, &point1, &mindist);
+  if (notfirst)
+    fprintf(fp, ",");
+  if (format == qh_PRINTmaple)
+    pointfmt= "[[%16.8f, %16.8f], [%16.8f, %16.8f]]\n";
+  else
+    pointfmt= "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n";
+  fprintf(fp, pointfmt, point0[0], point0[1], point1[0], point1[1]);
+  qh_memfree (point1, qh normal_size);
+  qh_memfree (point0, qh normal_size);
+} /* printfacet2math */
+
+
+/*---------------------------------
+  
+  qh_printfacet3geom_nonsimplicial( fp, facet, color )
+    print Geomview OFF for a 3-d nonsimplicial facet.
+    if DOintersections, prints ridges to unvisited neighbors (qh visit_id) 
+
+  notes
+    uses facet->visitid for intersections and ridges
+*/
+void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
+  ridgeT *ridge, **ridgep;
+  setT *projectedpoints, *vertices;
+  vertexT *vertex, **vertexp, *vertexA, *vertexB;
+  pointT *projpt, *point, **pointp;
+  facetT *neighbor;
+  realT dist, outerplane, innerplane;
+  int cntvertices, k;
+  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+
+  qh_geomplanes (facet, &outerplane, &innerplane); 
+  vertices= qh_facet3vertex (facet); /* oriented */
+  cntvertices= qh_setsize(vertices);
+  projectedpoints= qh_settemp(cntvertices);
+  FOREACHvertex_(vertices) {
+    zinc_(Zdistio);
+    qh_distplane(vertex->point, facet, &dist);
+    projpt= qh_projectpoint(vertex->point, facet, dist);
+    qh_setappend (&projectedpoints, projpt);
+  }
+  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+    qh_printfacet3geom_points(fp, projectedpoints, facet, outerplane, color);
+  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet3geom_points(fp, projectedpoints, facet, innerplane, color);
+  }
+  FOREACHpoint_(projectedpoints)
+    qh_memfree (point, qh normal_size);
+  qh_settempfree(&projectedpoints);
+  qh_settempfree(&vertices);
+  if ((qh DOintersections || qh PRINTridges)
+  && (!facet->visible || !qh NEWfacets)) {
+    facet->visitid= qh visit_id;
+    FOREACHridge_(facet->ridges) {
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->visitid != qh visit_id) {
+        if (qh DOintersections)
+          qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, black);
+        if (qh PRINTridges) {
+          vertexA= SETfirstt_(ridge->vertices, vertexT);
+          vertexB= SETsecondt_(ridge->vertices, vertexT);
+          qh_printline3geom (fp, vertexA->point, vertexB->point, green);
+        }
+      }
+    }
+  }
+} /* printfacet3geom_nonsimplicial */
+
+/*---------------------------------
+  
+  qh_printfacet3geom_points( fp, points, facet, offset )
+    prints a 3-d facet as OFF Geomview object. 
+    offset is relative to the facet's hyperplane
+    Facet is determined as a list of points
+*/
+void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
+  int k, n= qh_setsize(points), i;
+  pointT *point, **pointp;
+  setT *printpoints;
+
+  fprintf(fp, "{ OFF %d 1 1 # f%d\n", n, facet->id);
+  if (offset != 0.0) {
+    printpoints= qh_settemp (n);
+    FOREACHpoint_(points) 
+      qh_setappend (&printpoints, qh_projectpoint(point, facet, -offset));
+  }else
+    printpoints= points;
+  FOREACHpoint_(printpoints) {
+    for (k=0; k < qh hull_dim; k++) {
+      if (k == qh DROPdim)
+        fprintf(fp, "0 ");
+      else
+        fprintf(fp, "%8.4g ", point[k]);
+    }
+    if (printpoints != points)
+      qh_memfree (point, qh normal_size);
+    fprintf (fp, "\n");
+  }
+  if (printpoints != points)
+    qh_settempfree (&printpoints);
+  fprintf(fp, "%d ", n);
+  for(i= 0; i < n; i++)
+    fprintf(fp, "%d ", i);
+  fprintf(fp, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
+} /* printfacet3geom_points */
+
+
+/*---------------------------------
+  
+  qh_printfacet3geom_simplicial(  )
+    print Geomview OFF for a 3-d simplicial facet.
+
+  notes:
+    may flip color
+    uses facet->visitid for intersections and ridges
+
+    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+    innerplane may be off by qh DISTround.  Maxoutside is calculated elsewhere
+    so a DISTround error may have occured.
+*/
+void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
+  setT *points, *vertices;
+  vertexT *vertex, **vertexp, *vertexA, *vertexB;
+  facetT *neighbor, **neighborp;
+  realT outerplane, innerplane;
+  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+  int k;
+
+  qh_geomplanes (facet, &outerplane, &innerplane); 
+  vertices= qh_facet3vertex (facet);
+  points= qh_settemp (qh TEMPsize);
+  FOREACHvertex_(vertices)
+    qh_setappend(&points, vertex->point);
+  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+    qh_printfacet3geom_points(fp, points, facet, outerplane, color);
+  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+              outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+    for (k= 3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet3geom_points(fp, points, facet, innerplane, color);
+  }
+  qh_settempfree(&points);
+  qh_settempfree(&vertices);
+  if ((qh DOintersections || qh PRINTridges)
+  && (!facet->visible || !qh NEWfacets)) {
+    facet->visitid= qh visit_id;
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+	vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
+	                  SETindex_(facet->neighbors, neighbor), 0);
+        if (qh DOintersections)
+	   qh_printhyperplaneintersection(fp, facet, neighbor, vertices, black); 
+        if (qh PRINTridges) {
+          vertexA= SETfirstt_(vertices, vertexT);
+          vertexB= SETsecondt_(vertices, vertexT);
+          qh_printline3geom (fp, vertexA->point, vertexB->point, green);
+        }
+	qh_setfree(&vertices);
+      }
+    }
+  }
+} /* printfacet3geom_simplicial */
+
+/*---------------------------------
+  
+  qh_printfacet3math( fp, facet, notfirst )
+    print 3-d Maple or Mathematica output for a facet
+
+  notes:
+    may be non-simplicial
+    use %16.8f since Mathematica 2.2 does not handle exponential format
+    see qh_printfacet2math
+*/
+void qh_printfacet3math (FILE *fp, facetT *facet, int format, int notfirst) {
+  vertexT *vertex, **vertexp;
+  setT *points, *vertices;
+  pointT *point, **pointp;
+  boolT firstpoint= True;
+  realT dist;
+  char *pointfmt, *endfmt;
+  
+  if (notfirst)
+    fprintf(fp, ",\n");
+  vertices= qh_facet3vertex (facet);
+  points= qh_settemp (qh_setsize (vertices));
+  FOREACHvertex_(vertices) {
+    zinc_(Zdistio);
+    qh_distplane(vertex->point, facet, &dist);
+    point= qh_projectpoint(vertex->point, facet, dist);
+    qh_setappend (&points, point);
+  }
+  if (format == qh_PRINTmaple) {
+    fprintf(fp, "[");
+    pointfmt= "[%16.8f, %16.8f, %16.8f]";
+    endfmt= "]";
+  }else {
+    fprintf(fp, "Polygon[{");
+    pointfmt= "{%16.8f, %16.8f, %16.8f}";
+    endfmt= "}]";
+  }
+  FOREACHpoint_(points) {
+    if (firstpoint)
+      firstpoint= False;
+    else
+      fprintf(fp, ",\n");
+    fprintf(fp, pointfmt, point[0], point[1], point[2]);
+  }
+  FOREACHpoint_(points)
+    qh_memfree (point, qh normal_size);
+  qh_settempfree(&points);
+  qh_settempfree(&vertices);
+  fprintf(fp, endfmt);
+} /* printfacet3math */
+
+
+/*---------------------------------
+  
+  qh_printfacet3vertex( fp, facet, format )
+    print vertices in a 3-d facet as point ids
+
+  notes:
+    prints number of vertices first if format == qh_PRINToff
+    the facet may be non-simplicial
+*/
+void qh_printfacet3vertex(FILE *fp, facetT *facet, int format) {
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+
+  vertices= qh_facet3vertex (facet);
+  if (format == qh_PRINToff)
+    fprintf (fp, "%d ", qh_setsize (vertices));
+  FOREACHvertex_(vertices) 
+    fprintf (fp, "%d ", qh_pointid(vertex->point));
+  fprintf (fp, "\n");
+  qh_settempfree(&vertices);
+} /* printfacet3vertex */
+
+
+/*---------------------------------
+  
+  qh_printfacet4geom_nonsimplicial(  )
+    print Geomview 4OFF file for a 4d nonsimplicial facet
+    prints all ridges to unvisited neighbors (qh.visit_id)
+    if qh.DROPdim
+      prints in OFF format
+  
+  notes:
+    must agree with printend4geom()
+*/
+void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
+  facetT *neighbor;
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, **vertexp;
+  pointT *point;
+  int k;
+  realT dist;
+  
+  facet->visitid= qh visit_id;
+  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+    return;
+  FOREACHridge_(facet->ridges) {
+    neighbor= otherfacet_(ridge, facet);
+    if (neighbor->visitid == qh visit_id) 
+      continue;
+    if (qh PRINTtransparent && !neighbor->good)
+      continue;  
+    if (qh DOintersections)
+      qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, color);
+    else {
+      if (qh DROPdim >= 0) 
+	fprintf(fp, "OFF 3 1 1 # f%d\n", facet->id);
+      else {
+	qh printoutvar++;
+	fprintf (fp, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
+      }
+      FOREACHvertex_(ridge->vertices) {
+	zinc_(Zdistio);
+	qh_distplane(vertex->point,facet, &dist);
+	point=qh_projectpoint(vertex->point,facet, dist);
+	for(k= 0; k < qh hull_dim; k++) {
+	  if (k != qh DROPdim)
+  	    fprintf(fp, "%8.4g ", point[k]);
+  	}
+	fprintf (fp, "\n");
+	qh_memfree (point, qh normal_size);
+      }
+      if (qh DROPdim >= 0)
+        fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+    }
+  }
+} /* printfacet4geom_nonsimplicial */
+
+
+/*---------------------------------
+  
+  qh_printfacet4geom_simplicial( fp, facet, color )
+    print Geomview 4OFF file for a 4d simplicial facet
+    prints triangles for unvisited neighbors (qh.visit_id)
+
+  notes:
+    must agree with printend4geom()
+*/
+void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
+  setT *vertices;
+  facetT *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  int k;
+  
+  facet->visitid= qh visit_id;
+  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+    return;
+  FOREACHneighbor_(facet) {
+    if (neighbor->visitid == qh visit_id)
+      continue;
+    if (qh PRINTtransparent && !neighbor->good)
+      continue;  
+    vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
+	                  SETindex_(facet->neighbors, neighbor), 0);
+    if (qh DOintersections)
+      qh_printhyperplaneintersection(fp, facet, neighbor, vertices, color);
+    else {
+      if (qh DROPdim >= 0) 
+	fprintf(fp, "OFF 3 1 1 # ridge between f%d f%d\n",
+		facet->id, neighbor->id);
+      else {
+	qh printoutvar++;
+	fprintf (fp, "# ridge between f%d f%d\n", facet->id, neighbor->id);
+      }
+      FOREACHvertex_(vertices) {
+	for(k= 0; k < qh hull_dim; k++) {
+	  if (k != qh DROPdim)
+  	    fprintf(fp, "%8.4g ", vertex->point[k]);
+  	}
+	fprintf (fp, "\n");
+      }
+      if (qh DROPdim >= 0) 
+        fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+    }
+    qh_setfree(&vertices);
+  }
+} /* printfacet4geom_simplicial */
+
+
+/*---------------------------------
+  
+  qh_printfacetNvertex_nonsimplicial( fp, facet, id, format )
+    print vertices for an N-d non-simplicial facet
+    triangulates each ridge to the id
+*/
+void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format) {
+  vertexT *vertex, **vertexp;
+  ridgeT *ridge, **ridgep;
+
+  if (facet->visible && qh NEWfacets)
+    return;
+  FOREACHridge_(facet->ridges) {
+    if (format == qh_PRINTtriangles)
+      fprintf(fp, "%d ", qh hull_dim);
+    fprintf(fp, "%d ", id);
+    if ((ridge->top == facet) ^ qh_ORIENTclock) {
+      FOREACHvertex_(ridge->vertices)
+        fprintf(fp, "%d ", qh_pointid(vertex->point));
+    }else {
+      FOREACHvertexreverse12_(ridge->vertices)
+        fprintf(fp, "%d ", qh_pointid(vertex->point));
+    }
+    fprintf(fp, "\n");
+  }
+} /* printfacetNvertex_nonsimplicial */
+
+
+/*---------------------------------
+  
+  qh_printfacetNvertex_simplicial( fp, facet, format )
+    print vertices for an N-d simplicial facet
+    prints vertices for non-simplicial facets
+      2-d facets (orientation preserved by qh_mergefacet2d)
+      PRINToff ('o') for 4-d and higher
+*/
+void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format) {
+  vertexT *vertex, **vertexp;
+
+  if (format == qh_PRINToff || format == qh_PRINTtriangles)
+    fprintf (fp, "%d ", qh_setsize (facet->vertices));
+  if ((facet->toporient ^ qh_ORIENTclock) 
+  || (qh hull_dim > 2 && !facet->simplicial)) {
+    FOREACHvertex_(facet->vertices)
+      fprintf(fp, "%d ", qh_pointid(vertex->point));
+  }else {
+    FOREACHvertexreverse12_(facet->vertices)
+      fprintf(fp, "%d ", qh_pointid(vertex->point));
+  }
+  fprintf(fp, "\n");
+} /* printfacetNvertex_simplicial */
+
+
+/*---------------------------------
+  
+  qh_printfacetheader( fp, facet )
+    prints header fields of a facet to fp
+    
+  notes:
+    for 'f' output and debugging
+*/
+void qh_printfacetheader(FILE *fp, facetT *facet) {
+  pointT *point, **pointp, *furthest;
+  facetT *neighbor, **neighborp;
+  realT dist;
+
+  if (facet == qh_MERGEridge) {
+    fprintf (fp, " MERGEridge\n");
+    return;
+  }else if (facet == qh_DUPLICATEridge) {
+    fprintf (fp, " DUPLICATEridge\n");
+    return;
+  }else if (!facet) {
+    fprintf (fp, " NULLfacet\n");
+    return;
+  }
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  fprintf(fp, "- f%d\n", facet->id);
+  fprintf(fp, "    - flags:");
+  if (facet->toporient) 
+    fprintf(fp, " top");
+  else
+    fprintf(fp, " bottom");
+  if (facet->simplicial)
+    fprintf(fp, " simplicial");
+  if (facet->tricoplanar)
+    fprintf(fp, " tricoplanar");
+  if (facet->upperdelaunay)
+    fprintf(fp, " upperDelaunay");
+  if (facet->visible)
+    fprintf(fp, " visible");
+  if (facet->newfacet)
+    fprintf(fp, " new");
+  if (facet->tested)
+    fprintf(fp, " tested");
+  if (!facet->good)
+    fprintf(fp, " notG");
+  if (facet->seen)
+    fprintf(fp, " seen");
+  if (facet->coplanar)
+    fprintf(fp, " coplanar");
+  if (facet->mergehorizon)
+    fprintf(fp, " mergehorizon");
+  if (facet->keepcentrum)
+    fprintf(fp, " keepcentrum");
+  if (facet->dupridge)
+    fprintf(fp, " dupridge");
+  if (facet->mergeridge && !facet->mergeridge2)
+    fprintf(fp, " mergeridge1");
+  if (facet->mergeridge2)
+    fprintf(fp, " mergeridge2");
+  if (facet->newmerge)
+    fprintf(fp, " newmerge");
+  if (facet->flipped) 
+    fprintf(fp, " flipped");
+  if (facet->notfurthest) 
+    fprintf(fp, " notfurthest");
+  if (facet->degenerate)
+    fprintf(fp, " degenerate");
+  if (facet->redundant)
+    fprintf(fp, " redundant");
+  fprintf(fp, "\n");
+  if (facet->isarea)
+    fprintf(fp, "    - area: %2.2g\n", facet->f.area);
+  else if (qh NEWfacets && facet->visible && facet->f.replace)
+    fprintf(fp, "    - replacement: f%d\n", facet->f.replace->id);
+  else if (facet->newfacet) {
+    if (facet->f.samecycle && facet->f.samecycle != facet)
+      fprintf(fp, "    - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
+  }else if (facet->tricoplanar /* !isarea */) {
+    if (facet->f.triowner)
+      fprintf(fp, "    - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
+  }else if (facet->f.newcycle)
+    fprintf(fp, "    - was horizon to f%d\n", facet->f.newcycle->id);
+  if (facet->nummerge)
+    fprintf(fp, "    - merges: %d\n", facet->nummerge);
+  qh_printpointid(fp, "    - normal: ", qh hull_dim, facet->normal, -1);
+  fprintf(fp, "    - offset: %10.7g\n", facet->offset);
+  if (qh CENTERtype == qh_ASvoronoi || facet->center)
+    qh_printcenter (fp, qh_PRINTfacets, "    - center: ", facet);
+#if qh_MAXoutside
+  if (facet->maxoutside > qh DISTround)
+    fprintf(fp, "    - maxoutside: %10.7g\n", facet->maxoutside);
+#endif
+  if (!SETempty_(facet->outsideset)) {
+    furthest= (pointT*)qh_setlast(facet->outsideset);
+    if (qh_setsize (facet->outsideset) < 6) {
+      fprintf(fp, "    - outside set (furthest p%d):\n", qh_pointid(furthest));
+      FOREACHpoint_(facet->outsideset)
+	qh_printpoint(fp, "     ", point);
+    }else if (qh_setsize (facet->outsideset) < 21) {
+      qh_printpoints(fp, "    - outside set:", facet->outsideset);
+    }else {
+      fprintf(fp, "    - outside set:  %d points.", qh_setsize(facet->outsideset));
+      qh_printpoint(fp, "  Furthest", furthest);
+    }
+#if !qh_COMPUTEfurthest
+    fprintf(fp, "    - furthest distance= %2.2g\n", facet->furthestdist);
+#endif
+  }
+  if (!SETempty_(facet->coplanarset)) {
+    furthest= (pointT*)qh_setlast(facet->coplanarset);
+    if (qh_setsize (facet->coplanarset) < 6) {
+      fprintf(fp, "    - coplanar set (furthest p%d):\n", qh_pointid(furthest));
+      FOREACHpoint_(facet->coplanarset)
+	qh_printpoint(fp, "     ", point);
+    }else if (qh_setsize (facet->coplanarset) < 21) {
+      qh_printpoints(fp, "    - coplanar set:", facet->coplanarset);
+    }else {
+      fprintf(fp, "    - coplanar set:  %d points.", qh_setsize(facet->coplanarset));
+      qh_printpoint(fp, "  Furthest", furthest);
+    }
+    zinc_(Zdistio);
+    qh_distplane (furthest, facet, &dist);
+    fprintf(fp, "      furthest distance= %2.2g\n", dist);
+  }
+  qh_printvertices (fp, "    - vertices:", facet->vertices);
+  fprintf(fp, "    - neighboring facets: ");
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge)
+      fprintf(fp, " MERGE");
+    else if (neighbor == qh_DUPLICATEridge)
+      fprintf(fp, " DUP");
+    else
+      fprintf(fp, " f%d", neighbor->id);
+  }
+  fprintf(fp, "\n");
+  qh RANDOMdist= qh old_randomdist;
+} /* printfacetheader */
+
+
+/*---------------------------------
+  
+  qh_printfacetridges( fp, facet )
+    prints ridges of a facet to fp
+
+  notes:
+    ridges printed in neighbor order
+    assumes the ridges exist
+    for 'f' output
+*/
+void qh_printfacetridges(FILE *fp, facetT *facet) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int numridges= 0;
+
+
+  if (facet->visible && qh NEWfacets) {
+    fprintf(fp, "    - ridges (ids may be garbage):");
+    FOREACHridge_(facet->ridges)
+      fprintf(fp, " r%d", ridge->id);
+    fprintf(fp, "\n");
+  }else {
+    fprintf(fp, "    - ridges:\n");
+    FOREACHridge_(facet->ridges)
+      ridge->seen= False;
+    if (qh hull_dim == 3) {
+      ridge= SETfirstt_(facet->ridges, ridgeT);
+      while (ridge && !ridge->seen) {
+	ridge->seen= True;
+	qh_printridge(fp, ridge);
+	numridges++;
+	ridge= qh_nextridge3d (ridge, facet, NULL);
+	}
+    }else {
+      FOREACHneighbor_(facet) {
+	FOREACHridge_(facet->ridges) {
+	  if (otherfacet_(ridge,facet) == neighbor) {
+	    ridge->seen= True;
+	    qh_printridge(fp, ridge);
+	    numridges++;
+	  }
+	}
+      }
+    }
+    if (numridges != qh_setsize (facet->ridges)) {
+      fprintf (fp, "     - all ridges:");
+      FOREACHridge_(facet->ridges) 
+	fprintf (fp, " r%d", ridge->id);
+        fprintf (fp, "\n");
+    }
+    FOREACHridge_(facet->ridges) {
+      if (!ridge->seen) 
+	qh_printridge(fp, ridge);
+    }
+  }
+} /* printfacetridges */
+
+/*---------------------------------
+  
+  qh_printfacets( fp, format, facetlist, facets, printall )
+    prints facetlist and/or facet set in output format
+  
+  notes:
+    also used for specialized formats ('FO' and summary)
+    turns off 'Rn' option since want actual numbers
+*/
+void qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+  facetT *facet, **facetp;
+  setT *vertices;
+  coordT *center;
+  realT outerplane, innerplane;
+
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  if (qh CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
+    fprintf (qh ferr, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
+  if (format == qh_PRINTnone)
+    ; /* print nothing */
+  else if (format == qh_PRINTaverage) {
+    vertices= qh_facetvertices (facetlist, facets, printall);
+    center= qh_getcenter (vertices);
+    fprintf (fp, "%d 1\n", qh hull_dim);
+    qh_printpointid (fp, NULL, qh hull_dim, center, -1);
+    qh_memfree (center, qh normal_size);
+    qh_settempfree (&vertices);
+  }else if (format == qh_PRINTextremes) {
+    if (qh DELAUNAY)
+      qh_printextremes_d (fp, facetlist, facets, printall);
+    else if (qh hull_dim == 2)
+      qh_printextremes_2d (fp, facetlist, facets, printall);
+    else 
+      qh_printextremes (fp, facetlist, facets, printall);
+  }else if (format == qh_PRINToptions)
+    fprintf(fp, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
+  else if (format == qh_PRINTpoints && !qh VORONOI)
+    qh_printpoints_out (fp, facetlist, facets, printall);
+  else if (format == qh_PRINTqhull)
+    fprintf (fp, "%s | %s\n", qh rbox_command, qh qhull_command);
+  else if (format == qh_PRINTsize) {
+    fprintf (fp, "0\n2 ");
+    fprintf (fp, qh_REAL_1, qh totarea);
+    fprintf (fp, qh_REAL_1, qh totvol);
+    fprintf (fp, "\n");
+  }else if (format == qh_PRINTsummary) {
+    qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, 
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+    vertices= qh_facetvertices (facetlist, facets, printall); 
+    fprintf (fp, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh hull_dim, 
+                qh num_points + qh_setsize (qh other_points),
+                qh num_vertices, qh num_facets - qh num_visible,
+                qh_setsize (vertices), numfacets, numcoplanars, 
+		numfacets - numsimplicial, zzval_(Zdelvertextot), 
+		numtricoplanars);
+    qh_settempfree (&vertices);
+    qh_outerinner (NULL, &outerplane, &innerplane);
+    fprintf (fp, qh_REAL_2n, outerplane, innerplane);
+  }else if (format == qh_PRINTvneighbors)
+    qh_printvneighbors (fp, facetlist, facets, printall);
+  else if (qh VORONOI && format == qh_PRINToff)
+    qh_printvoronoi (fp, format, facetlist, facets, printall);
+  else if (qh VORONOI && format == qh_PRINTgeom) {
+    qh_printbegin (fp, format, facetlist, facets, printall);
+    qh_printvoronoi (fp, format, facetlist, facets, printall);
+    qh_printend (fp, format, facetlist, facets, printall);
+  }else if (qh VORONOI 
+  && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
+    qh_printvdiagram (fp, format, facetlist, facets, printall);
+  else {
+    qh_printbegin (fp, format, facetlist, facets, printall);
+    FORALLfacet_(facetlist)
+      qh_printafacet (fp, format, facet, printall);
+    FOREACHfacet_(facets) 
+      qh_printafacet (fp, format, facet, printall);
+    qh_printend (fp, format, facetlist, facets, printall);
+  }
+  qh RANDOMdist= qh old_randomdist;
+} /* printfacets */
+
+
+/*---------------------------------
+  
+  qh_printhelp_degenerate( fp )
+    prints descriptive message for precision error
+
+  notes:
+    no message if qh_QUICKhelp
+*/
+void qh_printhelp_degenerate(FILE *fp) {
+  
+  if (qh MERGEexact || qh PREmerge || qh JOGGLEmax < REALmax/2) 
+    fprintf(fp, "\n\
+A Qhull error has occurred.  Qhull should have corrected the above\n\
+precision error.  Please send the input and all of the output to\n\
+qhull_bug at qhull.org\n");
+  else if (!qh_QUICKhelp) {
+    fprintf(fp, "\n\
+Precision problems were detected during construction of the convex hull.\n\
+This occurs because convex hull algorithms assume that calculations are\n\
+exact, but floating-point arithmetic has roundoff errors.\n\
+\n\
+To correct for precision problems, do not use 'Q0'.  By default, Qhull\n\
+selects 'C-0' or 'Qx' and merges non-convex facets.  With option 'QJ',\n\
+Qhull joggles the input to prevent precision problems.  See \"Imprecision\n\
+in Qhull\" (qh-impre.htm).\n\
+\n\
+If you use 'Q0', the output may include\n\
+coplanar ridges, concave ridges, and flipped facets.  In 4-d and higher,\n\
+Qhull may produce a ridge with four neighbors or two facets with the same \n\
+vertices.  Qhull reports these events when they occur.  It stops when a\n\
+concave ridge, flipped facet, or duplicate facet occurs.\n");
+#if REALfloat
+    fprintf (fp, "\
+\n\
+Qhull is currently using single precision arithmetic.  The following\n\
+will probably remove the precision problems:\n\
+  - recompile qhull for double precision (#define REALfloat 0 in user.h).\n");
+#endif
+    if (qh DELAUNAY && !qh SCALElast && qh MAXabs_coord > 1e4)
+      fprintf( fp, "\
+\n\
+When computing the Delaunay triangulation of coordinates > 1.0,\n\
+  - use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n");
+    if (qh DELAUNAY && !qh ATinfinity) 
+      fprintf( fp, "\
+When computing the Delaunay triangulation:\n\
+  - use 'Qz' to add a point at-infinity.  This reduces precision problems.\n");
+ 
+    fprintf(fp, "\
+\n\
+If you need triangular output:\n\
+  - use option 'Qt' to triangulate the output\n\
+  - use option 'QJ' to joggle the input points and remove precision errors\n\
+  - use option 'Ft'.  It triangulates non-simplicial facets with added points.\n\
+\n\
+If you must use 'Q0',\n\
+try one or more of the following options.  They can not guarantee an output.\n\
+  - use 'QbB' to scale the input to a cube.\n\
+  - use 'Po' to produce output and prevent partitioning for flipped facets\n\
+  - use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\
+  - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
+  - options 'Qf', 'Qbb', and 'QR0' may also help\n",
+               qh DISTround);
+    fprintf(fp, "\
+\n\
+To guarantee simplicial output:\n\
+  - use option 'Qt' to triangulate the output\n\
+  - use option 'QJ' to joggle the input points and remove precision errors\n\
+  - use option 'Ft' to triangulate the output by adding points\n\
+  - use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\
+");
+  }
+} /* printhelp_degenerate */
+
+
+/*---------------------------------
+  
+  qh_printhelp_singular( fp )
+    prints descriptive message for singular input
+*/
+void qh_printhelp_singular(FILE *fp) {
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+  realT min, max, *coord, dist;
+  int i,k;
+  
+  fprintf(fp, "\n\
+The input to qhull appears to be less than %d dimensional, or a\n\
+computation has overflowed.\n\n\
+Qhull could not construct a clearly convex simplex from points:\n",
+           qh hull_dim);
+  qh_printvertexlist (fp, "", qh facet_list, NULL, qh_ALL);
+  if (!qh_QUICKhelp)
+    fprintf(fp, "\n\
+The center point is coplanar with a facet, or a vertex is coplanar\n\
+with a neighboring facet.  The maximum round off error for\n\
+computing distances is %2.2g.  The center point, facets and distances\n\
+to the center point are as follows:\n\n", qh DISTround);
+  qh_printpointid (fp, "center point", qh hull_dim, qh interior_point, -1);
+  fprintf (fp, "\n");
+  FORALLfacets {
+    fprintf (fp, "facet");
+    FOREACHvertex_(facet->vertices)
+      fprintf (fp, " p%d", qh_pointid(vertex->point));
+    zinc_(Zdistio);
+    qh_distplane(qh interior_point, facet, &dist);
+    fprintf (fp, " distance= %4.2g\n", dist);
+  }
+  if (!qh_QUICKhelp) {
+    if (qh HALFspace) 
+      fprintf (fp, "\n\
+These points are the dual of the given halfspaces.  They indicate that\n\
+the intersection is degenerate.\n");
+    fprintf (fp,"\n\
+These points either have a maximum or minimum x-coordinate, or\n\
+they maximize the determinant for k coordinates.  Trial points\n\
+are first selected from points that maximize a coordinate.\n");
+    if (qh hull_dim >= qh_INITIALmax)
+      fprintf (fp, "\n\
+Because of the high dimension, the min x-coordinate and max-coordinate\n\
+points are used if the determinant is non-zero.  Option 'Qs' will\n\
+do a better, though much slower, job.  Instead of 'Qs', you can change\n\
+the points by randomly rotating the input with 'QR0'.\n");
+  }
+  fprintf (fp, "\nThe min and max coordinates for each dimension are:\n");
+  for (k=0; k < qh hull_dim; k++) {
+    min= REALmax;
+    max= -REALmin;
+    for (i=qh num_points, coord= qh first_point+k; i--; coord += qh hull_dim) {
+      maximize_(max, *coord);
+      minimize_(min, *coord);
+    }
+    fprintf (fp, "  %d:  %8.4g  %8.4g  difference= %4.4g\n", k, min, max, max-min);
+  }
+  if (!qh_QUICKhelp) {
+    fprintf (fp, "\n\
+If the input should be full dimensional, you have several options that\n\
+may determine an initial simplex:\n\
+  - use 'QJ'  to joggle the input and make it full dimensional\n\
+  - use 'QbB' to scale the points to the unit cube\n\
+  - use 'QR0' to randomly rotate the input for different maximum points\n\
+  - use 'Qs'  to search all points for the initial simplex\n\
+  - use 'En'  to specify a maximum roundoff error less than %2.2g.\n\
+  - trace execution with 'T3' to see the determinant for each point.\n",
+                     qh DISTround);
+#if REALfloat
+    fprintf (fp, "\
+  - recompile qhull for double precision (#define REALfloat 0 in qhull.h).\n");
+#endif
+    fprintf (fp, "\n\
+If the input is lower dimensional:\n\
+  - use 'QJ' to joggle the input and make it full dimensional\n\
+  - use 'Qbk:0Bk:0' to delete coordinate k from the input.  You should\n\
+    pick the coordinate with the least range.  The hull will have the\n\
+    correct topology.\n\
+  - determine the flat containing the points, rotate the points\n\
+    into a coordinate plane, and delete the other coordinates.\n\
+  - add one or more points to make the input full dimensional.\n\
+");
+    if (qh DELAUNAY && !qh ATinfinity)
+      fprintf (fp, "\n\n\
+This is a Delaunay triangulation and the input is co-circular or co-spherical:\n\
+  - use 'Qz' to add a point \"at infinity\" (i.e., above the paraboloid)\n\
+  - or use 'QJ' to joggle the input and avoid co-circular data\n");
+  }
+} /* printhelp_singular */
+
+/*---------------------------------
+  
+  qh_printhyperplaneintersection( fp, facet1, facet2, vertices, color )
+    print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
+*/
+void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
+		   setT *vertices, realT color[3]) {
+  realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
+  vertexT *vertex, **vertexp;
+  int i, k;
+  boolT nearzero1, nearzero2;
+  
+  costheta= qh_getangle(facet1->normal, facet2->normal);
+  denominator= 1 - costheta * costheta;
+  i= qh_setsize(vertices);
+  if (qh hull_dim == 3)
+    fprintf(fp, "VECT 1 %d 1 %d 1 ", i, i);
+  else if (qh hull_dim == 4 && qh DROPdim >= 0)
+    fprintf(fp, "OFF 3 1 1 ");
+  else
+    qh printoutvar++;
+  fprintf (fp, "# intersect f%d f%d\n", facet1->id, facet2->id);
+  mindenom= 1 / (10.0 * qh MAXabs_coord);
+  FOREACHvertex_(vertices) {
+    zadd_(Zdistio, 2);
+    qh_distplane(vertex->point, facet1, &dist1);
+    qh_distplane(vertex->point, facet2, &dist2);
+    s= qh_divzero (-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
+    t= qh_divzero (-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
+    if (nearzero1 || nearzero2)
+      s= t= 0.0;
+    for(k= qh hull_dim; k--; )
+      p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
+    if (qh PRINTdim <= 3) {
+      qh_projectdim3 (p, p);
+      fprintf(fp, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
+    }else 
+      fprintf(fp, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
+    if (nearzero1+nearzero2)
+      fprintf (fp, "p%d (coplanar facets)\n", qh_pointid (vertex->point));
+    else
+      fprintf (fp, "projected p%d\n", qh_pointid (vertex->point));
+  }
+  if (qh hull_dim == 3)
+    fprintf(fp, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]); 
+  else if (qh hull_dim == 4 && qh DROPdim >= 0)  
+    fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printhyperplaneintersection */
+
+/*---------------------------------
+  
+  qh_printline3geom( fp, pointA, pointB, color )
+    prints a line as a VECT
+    prints 0's for qh.DROPdim
+  
+  notes:
+    if pointA == pointB, 
+      it's a 1 point VECT
+*/
+void qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
+  int k;
+  realT pA[4], pB[4];
+
+  qh_projectdim3(pointA, pA);
+  qh_projectdim3(pointB, pB);
+  if ((fabs(pA[0] - pB[0]) > 1e-3) || 
+      (fabs(pA[1] - pB[1]) > 1e-3) || 
+      (fabs(pA[2] - pB[2]) > 1e-3)) {
+    fprintf (fp, "VECT 1 2 1 2 1\n");
+    for (k= 0; k < 3; k++)
+       fprintf (fp, "%8.4g ", pB[k]);
+    fprintf (fp, " # p%d\n", qh_pointid (pointB));
+  }else
+    fprintf (fp, "VECT 1 1 1 1 1\n");
+  for (k=0; k < 3; k++)
+    fprintf (fp, "%8.4g ", pA[k]);
+  fprintf (fp, " # p%d\n", qh_pointid (pointA));
+  fprintf (fp, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
+}
+
+/*---------------------------------
+  
+  qh_printneighborhood( fp, format, facetA, facetB, printall )
+    print neighborhood of one or two facets
+
+  notes:
+    calls qh_findgood_all() 
+    bumps qh.visit_id
+*/
+void qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall) {
+  facetT *neighbor, **neighborp, *facet;
+  setT *facets;
+
+  if (format == qh_PRINTnone)
+    return;
+  qh_findgood_all (qh facet_list);
+  if (facetA == facetB)
+    facetB= NULL;
+  facets= qh_settemp (2*(qh_setsize (facetA->neighbors)+1));
+  qh visit_id++;
+  for (facet= facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
+    if (facet->visitid != qh visit_id) {
+      facet->visitid= qh visit_id;
+      qh_setappend (&facets, facet);
+    }
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == qh visit_id)
+        continue;
+      neighbor->visitid= qh visit_id;
+      if (printall || !qh_skipfacet (neighbor))
+        qh_setappend (&facets, neighbor);
+    }
+  }
+  qh_printfacets (fp, format, NULL, facets, printall);
+  qh_settempfree (&facets);
+} /* printneighborhood */
+
+/*---------------------------------
+  
+  qh_printpoint( fp, string, point )
+  qh_printpointid( fp, string, dim, point, id )
+    prints the coordinates of a point
+
+  returns:
+    if string is defined
+      prints 'string p%d' (skips p%d if id=-1)
+
+  notes:
+    nop if point is NULL
+    prints id unless it is undefined (-1)
+*/
+void qh_printpoint(FILE *fp, char *string, pointT *point) {
+  int id= qh_pointid( point);
+
+  qh_printpointid( fp, string, qh hull_dim, point, id);
+} /* printpoint */
+
+void qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id) {
+  int k;
+  realT r; /*bug fix*/
+  
+  if (!point)
+    return;
+  if (string) {
+    fputs (string, fp);
+   if (id != -1)
+      fprintf(fp, " p%d: ", id);
+  }
+  for(k= dim; k--; ) {
+    r= *point++;
+    if (string)
+      fprintf(fp, " %8.4g", r);
+    else
+      fprintf(fp, qh_REAL_1, r);
+  }
+  fprintf(fp, "\n");
+} /* printpointid */
+
+/*---------------------------------
+  
+  qh_printpoint3( fp, point )
+    prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
+*/
+void qh_printpoint3 (FILE *fp, pointT *point) {
+  int k;
+  realT p[4];
+  
+  qh_projectdim3 (point, p);
+  for (k=0; k < 3; k++)
+    fprintf (fp, "%8.4g ", p[k]);
+  fprintf (fp, " # p%d\n", qh_pointid (point));
+} /* printpoint3 */
+
+/*----------------------------------------
+-printpoints- print pointids for a set of points starting at index 
+   see geom.c
+*/
+
+/*---------------------------------
+  
+  qh_printpoints_out( fp, facetlist, facets, printall )
+    prints vertices, coplanar/inside points, for facets by their point coordinates
+    allows qh.CDDoutput
+
+  notes:
+    same format as qhull input
+    if no coplanar/interior points,
+      same order as qh_printextremes
+*/
+void qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall) {
+  int allpoints= qh num_points + qh_setsize (qh other_points);
+  int numpoints=0, point_i, point_n;
+  setT *vertices, *points;
+  facetT *facet, **facetp;
+  pointT *point, **pointp;
+  vertexT *vertex, **vertexp;
+  int id;
+
+  points= qh_settemp (allpoints);
+  qh_setzero (points, 0, allpoints);
+  vertices= qh_facetvertices (facetlist, facets, printall);
+  FOREACHvertex_(vertices) {
+    id= qh_pointid (vertex->point);
+    if (id >= 0)
+      SETelem_(points, id)= vertex->point;
+  }
+  if (qh KEEPinside || qh KEEPcoplanar || qh KEEPnearinside) {
+    FORALLfacet_(facetlist) {
+      if (!printall && qh_skipfacet(facet))
+        continue;
+      FOREACHpoint_(facet->coplanarset) {
+        id= qh_pointid (point);
+        if (id >= 0)
+          SETelem_(points, id)= point;
+      }
+    }
+    FOREACHfacet_(facets) {
+      if (!printall && qh_skipfacet(facet))
+        continue;
+      FOREACHpoint_(facet->coplanarset) {
+        id= qh_pointid (point);
+        if (id >= 0)
+          SETelem_(points, id)= point;
+      }
+    }
+  }
+  qh_settempfree (&vertices);
+  FOREACHpoint_i_(points) {
+    if (point)
+      numpoints++;
+  }
+  if (qh CDDoutput)
+    fprintf (fp, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
+             qh qhull_command, numpoints, qh hull_dim + 1);
+  else
+    fprintf (fp, "%d\n%d\n", qh hull_dim, numpoints);
+  FOREACHpoint_i_(points) {
+    if (point) {
+      if (qh CDDoutput)
+	fprintf (fp, "1 ");
+      qh_printpoint (fp, NULL, point);
+    }
+  }
+  if (qh CDDoutput)
+    fprintf (fp, "end\n");
+  qh_settempfree (&points);
+} /* printpoints_out */
+  
+
+/*---------------------------------
+  
+  qh_printpointvect( fp, point, normal, center, radius, color )
+    prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
+*/
+void qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
+  realT diff[4], pointA[4];
+  int k;
+  
+  for (k= qh hull_dim; k--; ) {
+    if (center)
+      diff[k]= point[k]-center[k];
+    else if (normal) 
+      diff[k]= normal[k];
+    else
+      diff[k]= 0;
+  }
+  if (center)
+    qh_normalize2 (diff, qh hull_dim, True, NULL, NULL);
+  for (k= qh hull_dim; k--; ) 
+    pointA[k]= point[k]+diff[k] * radius;
+  qh_printline3geom (fp, point, pointA, color);
+} /* printpointvect */  
+
+/*---------------------------------
+  
+  qh_printpointvect2( fp, point, normal, center, radius )
+    prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
+*/
+void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
+  realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
+
+  qh_printpointvect (fp, point, normal, center, radius, red);
+  qh_printpointvect (fp, point, normal, center, -radius, yellow);
+} /* printpointvect2 */
+
+/*---------------------------------
+  
+  qh_printridge( fp, ridge )
+    prints the information in a ridge
+
+  notes:
+    for qh_printfacetridges()
+*/
+void qh_printridge(FILE *fp, ridgeT *ridge) {
+  
+  fprintf(fp, "     - r%d", ridge->id);
+  if (ridge->tested)
+    fprintf (fp, " tested");
+  if (ridge->nonconvex)
+    fprintf (fp, " nonconvex");
+  fprintf (fp, "\n");
+  qh_printvertices (fp, "           vertices:", ridge->vertices);
+  if (ridge->top && ridge->bottom)
+    fprintf(fp, "           between f%d and f%d\n",
+	    ridge->top->id, ridge->bottom->id);
+} /* printridge */
+
+/*---------------------------------
+  
+  qh_printspheres( fp, vertices, radius )
+    prints 3-d vertices as OFF spheres
+
+  notes:
+    inflated octahedron from Stuart Levy earth/mksphere2
+*/
+void qh_printspheres(FILE *fp, setT *vertices, realT radius) {
+  vertexT *vertex, **vertexp;
+
+  qh printoutnum++;
+  fprintf (fp, "{appearance {-edge -normal normscale 0} {\n\
+INST geom {define vsphere OFF\n\
+18 32 48\n\
+\n\
+0 0 1\n\
+1 0 0\n\
+0 1 0\n\
+-1 0 0\n\
+0 -1 0\n\
+0 0 -1\n\
+0.707107 0 0.707107\n\
+0 -0.707107 0.707107\n\
+0.707107 -0.707107 0\n\
+-0.707107 0 0.707107\n\
+-0.707107 -0.707107 0\n\
+0 0.707107 0.707107\n\
+-0.707107 0.707107 0\n\
+0.707107 0.707107 0\n\
+0.707107 0 -0.707107\n\
+0 0.707107 -0.707107\n\
+-0.707107 0 -0.707107\n\
+0 -0.707107 -0.707107\n\
+\n\
+3 0 6 11\n\
+3 0 7 6	\n\
+3 0 9 7	\n\
+3 0 11 9\n\
+3 1 6 8	\n\
+3 1 8 14\n\
+3 1 13 6\n\
+3 1 14 13\n\
+3 2 11 13\n\
+3 2 12 11\n\
+3 2 13 15\n\
+3 2 15 12\n\
+3 3 9 12\n\
+3 3 10 9\n\
+3 3 12 16\n\
+3 3 16 10\n\
+3 4 7 10\n\
+3 4 8 7\n\
+3 4 10 17\n\
+3 4 17 8\n\
+3 5 14 17\n\
+3 5 15 14\n\
+3 5 16 15\n\
+3 5 17 16\n\
+3 6 13 11\n\
+3 7 8 6\n\
+3 9 10 7\n\
+3 11 12 9\n\
+3 14 8 17\n\
+3 15 13 14\n\
+3 16 12 15\n\
+3 17 10 16\n} transforms { TLIST\n");
+  FOREACHvertex_(vertices) {
+    fprintf(fp, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
+      radius, vertex->id, radius, radius);
+    qh_printpoint3 (fp, vertex->point);
+    fprintf (fp, "1\n");
+  }
+  fprintf (fp, "}}}\n");
+} /* printspheres */
+
+
+/*----------------------------------------------
+-printsummary-
+                see qhull.c
+*/
+
+/*---------------------------------
+  
+  qh_printvdiagram( fp, format, facetlist, facets, printall )
+    print voronoi diagram
+      # of pairs of input sites
+      #indices site1 site2 vertex1 ...
+    
+    sites indexed by input point id
+      point 0 is the first input point
+    vertices indexed by 'o' and 'p' order
+      vertex 0 is the 'vertex-at-infinity'
+      vertex 1 is the first Voronoi vertex
+
+  see:
+    qh_printvoronoi()
+    qh_eachvoronoi_all()
+
+  notes:
+    if all facets are upperdelaunay, 
+      prints upper hull (furthest-site Voronoi diagram)
+*/
+void qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices;
+  int totcount, numcenters;
+  boolT islower;
+  qh_RIDGE innerouter= qh_RIDGEall;
+  printvridgeT printvridge= NULL;
+
+  if (format == qh_PRINTvertices) {
+    innerouter= qh_RIDGEall;
+    printvridge= qh_printvridge;
+  }else if (format == qh_PRINTinner) {
+    innerouter= qh_RIDGEinner;
+    printvridge= qh_printvnorm;
+  }else if (format == qh_PRINTouter) {
+    innerouter= qh_RIDGEouter;
+    printvridge= qh_printvnorm;
+  }else {
+    fprintf(qh ferr, "qh_printvdiagram: unknown print format %d.\n", format);
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  vertices= qh_markvoronoi (facetlist, facets, printall, &islower, &numcenters);
+  totcount= qh_printvdiagram2 (NULL, NULL, vertices, innerouter, False);
+  fprintf (fp, "%d\n", totcount);
+  totcount= qh_printvdiagram2 (fp, printvridge, vertices, innerouter, True /* inorder*/);
+  qh_settempfree (&vertices);
+#if 0  /* for testing qh_eachvoronoi_all */
+  fprintf (fp, "\n");
+  totcount= qh_eachvoronoi_all(fp, printvridge, qh UPPERdelaunay, innerouter, True /* inorder*/);
+  fprintf (fp, "%d\n", totcount);
+#endif
+} /* printvdiagram */
+  
+/*---------------------------------
+  
+  qh_printvdiagram2( fp, printvridge, vertices, innerouter, inorder )
+    visit all pairs of input sites (vertices) for selected Voronoi vertices
+    vertices may include NULLs
+  
+  innerouter:
+    qh_RIDGEall   print inner ridges (bounded) and outer ridges (unbounded)
+    qh_RIDGEinner print only inner ridges
+    qh_RIDGEouter print only outer ridges
+  
+  inorder:
+    print 3-d Voronoi vertices in order
+  
+  assumes:
+    qh_markvoronoi marked facet->visitid for Voronoi vertices
+    all facet->seen= False
+    all facet->seen2= True
+  
+  returns:
+    total number of Voronoi ridges 
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers) for each ridge
+      [see qh_eachvoronoi()]
+  
+  see:
+    qh_eachvoronoi_all()
+*/
+int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
+  int totcount= 0;
+  int vertex_i, vertex_n;
+  vertexT *vertex;
+
+  FORALLvertices 
+    vertex->seen= False;
+  FOREACHvertex_i_(vertices) {
+    if (vertex) {
+      if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
+	continue;
+      totcount += qh_eachvoronoi (fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
+    }
+  }
+  return totcount;
+} /* printvdiagram2 */
+  
+/*---------------------------------
+  
+  qh_printvertex( fp, vertex )
+    prints the information in a vertex
+*/
+void qh_printvertex(FILE *fp, vertexT *vertex) {
+  pointT *point;
+  int k, count= 0;
+  facetT *neighbor, **neighborp;
+  realT r; /*bug fix*/
+
+  if (!vertex) {
+    fprintf (fp, "  NULLvertex\n");
+    return;
+  }
+  fprintf(fp, "- p%d (v%d):", qh_pointid(vertex->point), vertex->id);
+  point= vertex->point;
+  if (point) {
+    for(k= qh hull_dim; k--; ) {
+      r= *point++;
+      fprintf(fp, " %5.2g", r);
+    }
+  }
+  if (vertex->deleted)
+    fprintf(fp, " deleted");
+  if (vertex->delridge)
+    fprintf (fp, " ridgedeleted");
+  fprintf(fp, "\n");
+  if (vertex->neighbors) {
+    fprintf(fp, "  neighbors:");
+    FOREACHneighbor_(vertex) {
+      if (++count % 100 == 0)
+	fprintf (fp, "\n     ");
+      fprintf(fp, " f%d", neighbor->id);
+    }
+    fprintf(fp, "\n");
+  }
+} /* printvertex */
+
+
+/*---------------------------------
+  
+  qh_printvertexlist( fp, string, facetlist, facets, printall )
+    prints vertices used by a facetlist or facet set
+    tests qh_skipfacet() if !printall
+*/
+void qh_printvertexlist (FILE *fp, char* string, facetT *facetlist, 
+                         setT *facets, boolT printall) {
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+  
+  vertices= qh_facetvertices (facetlist, facets, printall);
+  fputs (string, fp);
+  FOREACHvertex_(vertices)
+    qh_printvertex(fp, vertex);
+  qh_settempfree (&vertices);
+} /* printvertexlist */
+
+
+/*---------------------------------
+  
+  qh_printvertices( fp, string, vertices )
+    prints vertices in a set
+*/
+void qh_printvertices(FILE *fp, char* string, setT *vertices) {
+  vertexT *vertex, **vertexp;
+  
+  fputs (string, fp);
+  FOREACHvertex_(vertices) 
+    fprintf (fp, " p%d (v%d)", qh_pointid(vertex->point), vertex->id);
+  fprintf(fp, "\n");
+} /* printvertices */
+
+/*---------------------------------
+  
+  qh_printvneighbors( fp, facetlist, facets, printall )
+    print vertex neighbors of vertices in facetlist and facets ('FN')
+
+  notes:
+    qh_countfacets clears facet->visitid for non-printed facets
+
+  design:
+    collect facet count and related statistics
+    if necessary, build neighbor sets for each vertex
+    collect vertices in facetlist and facets
+    build a point array for point->vertex and point->coplanar facet
+    for each point
+      list vertex neighbors or coplanar facet
+*/
+void qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
+  setT *vertices, *vertex_points, *coplanar_points;
+  int numpoints= qh num_points + qh_setsize (qh other_points);
+  vertexT *vertex, **vertexp;
+  int vertex_i, vertex_n;
+  facetT *facet, **facetp, *neighbor, **neighborp;
+  pointT *point, **pointp;
+
+  qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, 
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);  /* sets facet->visitid */
+  fprintf (fp, "%d\n", numpoints);
+  qh_vertexneighbors();
+  vertices= qh_facetvertices (facetlist, facets, printall);
+  vertex_points= qh_settemp (numpoints);
+  coplanar_points= qh_settemp (numpoints);
+  qh_setzero (vertex_points, 0, numpoints);
+  qh_setzero (coplanar_points, 0, numpoints);
+  FOREACHvertex_(vertices)
+    qh_point_add (vertex_points, vertex->point, vertex);
+  FORALLfacet_(facetlist) {
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add (coplanar_points, point, facet);
+  }
+  FOREACHfacet_(facets) {
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add (coplanar_points, point, facet);
+  }
+  FOREACHvertex_i_(vertex_points) {
+    if (vertex) { 
+      numneighbors= qh_setsize (vertex->neighbors);
+      fprintf (fp, "%d", numneighbors);
+      if (qh hull_dim == 3)
+        qh_order_vertexneighbors (vertex);
+      else if (qh hull_dim >= 4)
+        qsort (SETaddr_(vertex->neighbors, facetT), numneighbors,
+             sizeof (facetT *), qh_compare_facetvisit);
+      FOREACHneighbor_(vertex) 
+        fprintf (fp, " %d", 
+		 neighbor->visitid ? neighbor->visitid - 1 : - neighbor->id);
+      fprintf (fp, "\n");
+    }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
+      fprintf (fp, "1 %d\n",
+                  facet->visitid ? facet->visitid - 1 : - facet->id);
+    else
+      fprintf (fp, "0\n");
+  }
+  qh_settempfree (&coplanar_points);
+  qh_settempfree (&vertex_points);
+  qh_settempfree (&vertices);
+} /* printvneighbors */
+
+/*---------------------------------
+  
+  qh_printvoronoi( fp, format, facetlist, facets, printall )
+    print voronoi diagram in 'o' or 'G' format
+    for 'o' format
+      prints voronoi centers for each facet and for infinity
+      for each vertex, lists ids of printed facets or infinity
+      assumes facetlist and facets are disjoint
+    for 'G' format
+      prints an OFF object
+      adds a 0 coordinate to center
+      prints infinity but does not list in vertices
+
+  see:
+    qh_printvdiagram()
+
+  notes:
+    if 'o', 
+      prints a line for each point except "at-infinity"
+    if all facets are upperdelaunay, 
+      reverses lower and upper hull
+*/
+void qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
+  int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
+  facetT *facet, **facetp, *neighbor, **neighborp;
+  setT *vertices;
+  vertexT *vertex;
+  boolT islower;
+  unsigned int numfacets= (unsigned int) qh num_facets;
+
+  vertices= qh_markvoronoi (facetlist, facets, printall, &islower, &numcenters);
+  FOREACHvertex_i_(vertices) {
+    if (vertex) {
+      numvertices++;
+      numneighbors = numinf = 0;
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visitid == 0)
+	  numinf= 1;
+        else if (neighbor->visitid < numfacets)
+          numneighbors++;
+      }
+      if (numinf && !numneighbors) {
+	SETelem_(vertices, vertex_i)= NULL;
+	numvertices--;
+      }
+    }
+  }
+  if (format == qh_PRINTgeom) 
+    fprintf (fp, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n", 
+                numcenters, numvertices);
+  else
+    fprintf (fp, "%d\n%d %d 1\n", qh hull_dim-1, numcenters, qh_setsize(vertices));
+  if (format == qh_PRINTgeom) {
+    for (k= qh hull_dim-1; k--; )
+      fprintf (fp, qh_REAL_1, 0.0);
+    fprintf (fp, " 0 # infinity not used\n");
+  }else {
+    for (k= qh hull_dim-1; k--; )
+      fprintf (fp, qh_REAL_1, qh_INFINITE);
+    fprintf (fp, "\n");
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->visitid && facet->visitid < numfacets) {
+      if (format == qh_PRINTgeom)
+        fprintf (fp, "# %d f%d\n", vid++, facet->id);
+      qh_printcenter (fp, format, NULL, facet);
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (facet->visitid && facet->visitid < numfacets) {
+      if (format == qh_PRINTgeom)
+        fprintf (fp, "# %d f%d\n", vid++, facet->id);
+      qh_printcenter (fp, format, NULL, facet);
+    }
+  }
+  FOREACHvertex_i_(vertices) {
+    numneighbors= 0;
+    numinf=0;
+    if (vertex) {
+      if (qh hull_dim == 3)
+        qh_order_vertexneighbors(vertex);
+      else if (qh hull_dim >= 4)
+        qsort (SETaddr_(vertex->neighbors, vertexT), 
+	     qh_setsize (vertex->neighbors),
+	     sizeof (facetT *), qh_compare_facetvisit);
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visitid == 0)
+	  numinf= 1;
+	else if (neighbor->visitid < numfacets)
+          numneighbors++;
+      }
+    }
+    if (format == qh_PRINTgeom) {
+      if (vertex) {
+	fprintf (fp, "%d", numneighbors);
+	if (vertex) {
+	  FOREACHneighbor_(vertex) {
+	    if (neighbor->visitid && neighbor->visitid < numfacets)
+	      fprintf (fp, " %d", neighbor->visitid);
+	  }
+	}
+	fprintf (fp, " # p%d (v%d)\n", vertex_i, vertex->id);
+      }else
+	fprintf (fp, " # p%d is coplanar or isolated\n", vertex_i);
+    }else {
+      if (numinf)
+	numneighbors++;
+      fprintf (fp, "%d", numneighbors);
+      if (vertex) {
+        FOREACHneighbor_(vertex) {
+  	  if (neighbor->visitid == 0) {
+  	    if (numinf) {
+  	      numinf= 0;
+	      fprintf (fp, " %d", neighbor->visitid);
+	    }
+	  }else if (neighbor->visitid < numfacets)
+	    fprintf (fp, " %d", neighbor->visitid);
+	}
+      }
+      fprintf (fp, "\n");
+    }
+  }
+  if (format == qh_PRINTgeom)
+    fprintf (fp, "}\n");
+  qh_settempfree (&vertices);
+} /* printvoronoi */
+  
+/*---------------------------------
+  
+  qh_printvnorm( fp, vertex, vertexA, centers, unbounded )
+    print one separating plane of the Voronoi diagram for a pair of input sites
+    unbounded==True if centers includes vertex-at-infinity
+  
+  assumes:
+    qh_ASvoronoi and qh_vertexneighbors() already set
+    
+  see:
+    qh_printvdiagram()
+    qh_eachvoronoi()
+*/
+void qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+  pointT *normal;
+  realT offset;
+  int k;
+  
+  normal= qh_detvnorm (vertex, vertexA, centers, &offset);
+  fprintf (fp, "%d %d %d ", 
+      2+qh hull_dim, qh_pointid (vertex->point), qh_pointid (vertexA->point));
+  for (k= 0; k< qh hull_dim-1; k++)
+    fprintf (fp, qh_REAL_1, normal[k]);
+  fprintf (fp, qh_REAL_1, offset);
+  fprintf (fp, "\n");
+} /* printvnorm */
+
+/*---------------------------------
+  
+  qh_printvridge( fp, vertex, vertexA, centers, unbounded )
+    print one ridge of the Voronoi diagram for a pair of input sites
+    unbounded==True if centers includes vertex-at-infinity
+  
+  see:
+    qh_printvdiagram()
+  
+  notes:
+    the user may use a different function
+*/
+void qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+  facetT *facet, **facetp;
+
+  fprintf (fp, "%d %d %d", qh_setsize (centers)+2, 
+       qh_pointid (vertex->point), qh_pointid (vertexA->point));
+  FOREACHfacet_(centers) 
+    fprintf (fp, " %d", facet->visitid);
+  fprintf (fp, "\n");
+} /* printvridge */
+
+/*---------------------------------
+  
+  qh_projectdim3( source, destination )
+    project 2-d 3-d or 4-d point to a 3-d point
+    uses qh.DROPdim and qh.hull_dim
+    source and destination may be the same
+    
+  notes:
+    allocate 4 elements to destination just in case
+*/
+void qh_projectdim3 (pointT *source, pointT *destination) {
+  int i,k;
+
+  for (k= 0, i=0; k < qh hull_dim; k++) {
+    if (qh hull_dim == 4) {
+      if (k != qh DROPdim)
+        destination[i++]= source[k];
+    }else if (k == qh DROPdim)
+      destination[i++]= 0;
+    else
+      destination[i++]= source[k];
+  }
+  while (i < 3)
+    destination[i++]= 0.0;
+} /* projectdim3 */
+
+/*---------------------------------
+  
+  qh_readfeasible( dim, remainder )
+    read feasible point from remainder string and qh.fin
+
+  returns:
+    number of lines read from qh.fin
+    sets qh.FEASIBLEpoint with malloc'd coordinates
+
+  notes:
+    checks for qh.HALFspace
+    assumes dim > 1
+
+  see:
+    qh_setfeasible
+*/
+int qh_readfeasible (int dim, char *remainder) {
+  boolT isfirst= True;
+  int linecount= 0, tokcount= 0;
+  char *s, *t, firstline[qh_MAXfirst+1];
+  coordT *coords, value;
+
+  if (!qh HALFspace) {
+    fprintf  (qh ferr, "qhull input error: feasible point (dim 1 coords) is only valid for halfspace intersection\n");
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }  
+  if (qh feasible_string)
+    fprintf  (qh ferr, "qhull input warning: feasible point (dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
+  if (!(qh feasible_point= (coordT*)malloc (dim* sizeof(coordT)))) {
+    fprintf(qh ferr, "qhull error: insufficient memory for feasible point\n");
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coords= qh feasible_point;
+  while ((s= (isfirst ?  remainder : fgets(firstline, qh_MAXfirst, qh fin)))) {
+    if (isfirst)
+      isfirst= False;
+    else
+      linecount++;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      value= qh_strtod (s, &t);
+      if (s == t)
+        break;
+      s= t;
+      *(coords++)= value;
+      if (++tokcount == dim) {
+        while (isspace (*s))
+          s++;
+        qh_strtod (s, &t);
+        if (s != t) {
+          fprintf (qh ferr, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
+               s);
+          qh_errexit (qh_ERRinput, NULL, NULL);
+        }
+        return linecount;
+      }
+    }
+  }
+  fprintf (qh ferr, "qhull input error: only %d coordinates.  Could not read %d-d feasible point.\n",
+           tokcount, dim);
+  qh_errexit (qh_ERRinput, NULL, NULL);
+  return 0;
+} /* readfeasible */
+
+/*---------------------------------
+  
+  qh_readpoints( numpoints, dimension, ismalloc )
+    read points from qh.fin into qh.first_point, qh.num_points
+    qh.fin is lines of coordinates, one per vertex, first line number of points
+    if 'rbox D4',
+      gives message
+    if qh.ATinfinity,
+      adds point-at-infinity for Delaunay triangulations
+
+  returns:
+    number of points, array of point coordinates, dimension, ismalloc True
+    if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
+        and clears qh.PROJECTdelaunay
+    if qh.HALFspace, reads optional feasible point, reads halfspaces,
+        converts to dual.
+
+  for feasible point in "cdd format" in 3-d:
+    3 1
+    coordinates
+    comments
+    begin
+    n 4 real/integer
+    ...
+    end
+
+  notes:
+    dimension will change in qh_initqhull_globals if qh.PROJECTinput
+    uses malloc() since qh_mem not initialized
+    FIXUP: this routine needs rewriting
+*/
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) {
+  coordT *points, *coords, *infinity= NULL;
+  realT paraboloid, maxboloid= -REALmax, value;
+  realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
+  char *s, *t, firstline[qh_MAXfirst+1];
+  int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
+  int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
+  int tokcount= 0, linecount=0, maxcount, coordcount=0;
+  boolT islong, isfirst= True, wasbegin= False;
+  boolT isdelaunay= qh DELAUNAY && !qh PROJECTinput;
+
+  if (qh CDDinput) {
+    while ((s= fgets(firstline, qh_MAXfirst, qh fin))) {
+      linecount++;
+      if (qh HALFspace && linecount == 1 && isdigit(*s)) {
+	dimfeasible= qh_strtol (s, &s);	
+	while (isspace(*s))
+          s++;
+        if (qh_strtol (s, &s) == 1)
+          linecount += qh_readfeasible (dimfeasible, s);
+        else
+          dimfeasible= 0;
+      }else if (!memcmp (firstline, "begin", 5) || !memcmp (firstline, "BEGIN", 5))
+        break;
+      else if (!*qh rbox_command)
+	strncat(qh rbox_command, s, sizeof (qh rbox_command)-1);
+    }
+    if (!s) {
+      fprintf (qh ferr, "qhull input error: missing \"begin\" for cdd-formated input\n");
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+  }
+  while(!numinput && (s= fgets(firstline, qh_MAXfirst, qh fin))) {
+    linecount++;
+    if (!memcmp (s, "begin", 5) || !memcmp (s, "BEGIN", 5))
+      wasbegin= True;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      if (!*s)
+        break;
+      if (!isdigit(*s)) {
+        if (!*qh rbox_command) {
+          strncat(qh rbox_command, s, sizeof (qh rbox_command)-1);
+	  firsttext= linecount;
+        }
+        break;
+      }
+      if (!diminput) 
+        diminput= qh_strtol (s, &s);
+      else {
+        numinput= qh_strtol (s, &s);
+        if (numinput == 1 && diminput >= 2 && qh HALFspace && !qh CDDinput) {
+          linecount += qh_readfeasible (diminput, s); /* checks if ok */
+          dimfeasible= diminput;
+          diminput= numinput= 0;
+        }else 
+          break;
+      }
+    }
+  }
+  if (!s) {
+    fprintf(qh ferr, "qhull input error: short input file.  Did not find dimension and number of points\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (diminput > numinput) {
+    tempi= diminput;	/* exchange dim and n, e.g., for cdd input format */
+    diminput= numinput;
+    numinput= tempi;
+  }
+  if (diminput < 2) {
+    fprintf(qh ferr,"qhull input error: dimension %d (first number) should be at least 2\n",
+	    diminput);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (isdelaunay) {
+    qh PROJECTdelaunay= False;
+    if (qh CDDinput)
+      *dimension= diminput;
+    else
+      *dimension= diminput+1;
+    *numpoints= numinput;
+    if (qh ATinfinity)
+      (*numpoints)++;
+  }else if (qh HALFspace) {
+    *dimension= diminput - 1;
+    *numpoints= numinput;
+    if (diminput < 3) {
+      fprintf(qh ferr,"qhull input error: dimension %d (first number, includes offset) should be at least 3 for halfspaces\n",
+  	    diminput);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (dimfeasible) {
+      if (dimfeasible != *dimension) {
+        fprintf(qh ferr,"qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
+          dimfeasible, diminput);
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+    }else 
+      qh_setfeasible (*dimension);
+  }else {
+    if (qh CDDinput) 
+      *dimension= diminput-1;
+    else
+      *dimension= diminput;
+    *numpoints= numinput;
+  }
+  qh normal_size= *dimension * sizeof(coordT); /* for tracing with qh_printpoint */
+  if (qh HALFspace) {
+    qh half_space= coordp= (coordT*) malloc (qh normal_size + sizeof(coordT));
+    if (qh CDDinput) {
+      offsetp= qh half_space;
+      normalp= offsetp + 1;
+    }else {
+      normalp= qh half_space;
+      offsetp= normalp + *dimension;
+    }
+  } 
+  qh maxline= diminput * (qh_REALdigits + 5);
+  maximize_(qh maxline, 500);
+  qh line= (char*)malloc ((qh maxline+1) * sizeof (char));
+  *ismalloc= True;  /* use malloc since memory not setup */
+  coords= points= qh temp_malloc= 
+        (coordT*)malloc((*numpoints)*(*dimension)*sizeof(coordT));
+  if (!coords || !qh line || (qh HALFspace && !qh half_space)) {
+    fprintf(qh ferr, "qhull error: insufficient memory to read %d points\n",
+	    numinput);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  if (isdelaunay && qh ATinfinity) {
+    infinity= points + numinput * (*dimension);
+    for (k= (*dimension) - 1; k--; )
+      infinity[k]= 0.0;
+  }
+  maxcount= numinput * diminput;
+  paraboloid= 0.0;
+  while ((s= (isfirst ?  s : fgets(qh line, qh maxline, qh fin)))) {
+    if (!isfirst) {
+      linecount++;
+      if (*s == 'e' || *s == 'E') {
+	if (!memcmp (s, "end", 3) || !memcmp (s, "END", 3)) {
+	  if (qh CDDinput )
+	    break;
+	  else if (wasbegin) 
+	    fprintf (qh ferr, "qhull input warning: the input appears to be in cdd format.  If so, use 'Fd'\n");
+	}
+      }
+    }
+    islong= False;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      value= qh_strtod (s, &t);
+      if (s == t) {
+        if (!*qh rbox_command)
+ 	 strncat(qh rbox_command, s, sizeof (qh rbox_command)-1);
+        if (*s && !firsttext) 
+          firsttext= linecount;
+        if (!islong && !firstshort && coordcount)
+          firstshort= linecount;
+        break;
+      }
+      if (!firstpoint)
+	firstpoint= linecount;
+      s= t;
+      if (++tokcount > maxcount)
+        continue;
+      if (qh HALFspace) {
+	if (qh CDDinput) 
+	  *(coordp++)= -value; /* both coefficients and offset */
+	else
+	  *(coordp++)= value;
+      }else {
+        *(coords++)= value;
+        if (qh CDDinput && !coordcount) {
+          if (value != 1.0) {
+            fprintf (qh ferr, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
+                   linecount);
+            qh_errexit (qh_ERRinput, NULL, NULL);
+          }
+          coords--;
+        }else if (isdelaunay) {
+	  paraboloid += value * value;
+	  if (qh ATinfinity) {
+	    if (qh CDDinput)
+	      infinity[coordcount-1] += value;
+	    else
+	      infinity[coordcount] += value;
+	  }
+	}
+      }
+      if (++coordcount == diminput) {
+        coordcount= 0;
+        if (isdelaunay) {
+          *(coords++)= paraboloid;
+          maximize_(maxboloid, paraboloid);
+          paraboloid= 0.0;
+        }else if (qh HALFspace) {
+          if (!qh_sethalfspace (*dimension, coords, &coords, normalp, offsetp, qh feasible_point)) {
+	    fprintf (qh ferr, "The halfspace was on line %d\n", linecount);
+	    if (wasbegin)
+	      fprintf (qh ferr, "The input appears to be in cdd format.  If so, you should use option 'Fd'\n");
+	    qh_errexit (qh_ERRinput, NULL, NULL);
+	  }
+          coordp= qh half_space;
+        }          
+        while (isspace(*s))
+          s++;
+        if (*s) {
+          islong= True;
+          if (!firstlong)
+            firstlong= linecount;
+	}
+      }
+    }
+    if (!islong && !firstshort && coordcount)
+      firstshort= linecount;
+    if (!isfirst && s - qh line >= qh maxline) {
+      fprintf(qh ferr, "qhull input error: line %d contained more than %d characters\n", 
+	      linecount, (int) (s - qh line));
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    isfirst= False;
+  }
+  if (tokcount != maxcount) {
+    newnum= fmin_(numinput, tokcount/diminput);
+    fprintf(qh ferr,"\
+qhull warning: instead of %d %d-dimensional points, input contains\n\
+%d points and %d extra coordinates.  Line %d is the first\npoint",
+       numinput, diminput, tokcount/diminput, tokcount % diminput, firstpoint);
+    if (firsttext)
+      fprintf(qh ferr, ", line %d is the first comment", firsttext);
+    if (firstshort)
+      fprintf(qh ferr, ", line %d is the first short\nline", firstshort);
+    if (firstlong)
+      fprintf(qh ferr, ", line %d is the first long line", firstlong);
+    fprintf(qh ferr, ".  Continue with %d points.\n", newnum);
+    numinput= newnum;
+    if (isdelaunay && qh ATinfinity) {
+      for (k= tokcount % diminput; k--; )
+	infinity[k] -= *(--coords);
+      *numpoints= newnum+1;
+    }else {
+      coords -= tokcount % diminput;
+      *numpoints= newnum;
+    }
+  }
+  if (isdelaunay && qh ATinfinity) {
+    for (k= (*dimension) -1; k--; )
+      infinity[k] /= numinput;
+    if (coords == infinity)
+      coords += (*dimension) -1;
+    else {
+      for (k= 0; k < (*dimension) -1; k++)
+	*(coords++)= infinity[k];
+    }
+    *(coords++)= maxboloid * 1.1;
+  }
+  if (qh rbox_command[0]) {
+    qh rbox_command[strlen(qh rbox_command)-1]= '\0';
+    if (!strcmp (qh rbox_command, "./rbox D4")) 
+      fprintf (qh ferr, "\n\
+This is the qhull test case.  If any errors or core dumps occur,\n\
+recompile qhull with 'make new'.  If errors still occur, there is\n\
+an incompatibility.  You should try a different compiler.  You can also\n\
+change the choices in user.h.  If you discover the source of the problem,\n\
+please send mail to qhull_bug at qhull.org.\n\
+\n\
+Type 'qhull' for a short list of options.\n");
+  }
+  free (qh line);
+  qh line= NULL;
+  if (qh half_space) {
+    free (qh half_space);
+    qh half_space= NULL;
+  }
+  qh temp_malloc= NULL;
+  trace1((qh ferr,"qh_readpoints: read in %d %d-dimensional points\n",
+	  numinput, diminput));
+  return(points);
+} /* readpoints */
+
+
+/*---------------------------------
+  
+  qh_setfeasible( dim )
+    set qh.FEASIBLEpoint from qh.feasible_string in "n,n,n" or "n n n" format
+
+  notes:
+    "n,n,n" already checked by qh_initflags()
+    see qh_readfeasible()
+*/
+void qh_setfeasible (int dim) {
+  int tokcount= 0;
+  char *s;
+  coordT *coords, value;
+
+  if (!(s= qh feasible_string)) {
+    fprintf(qh ferr, "\
+qhull input error: halfspace intersection needs a feasible point.\n\
+Either prepend the input with 1 point or use 'Hn,n,n'.  See manual.\n");
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  if (!(qh feasible_point= (pointT*)malloc (dim* sizeof(coordT)))) {
+    fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n");
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coords= qh feasible_point;
+  while (*s) {
+    value= qh_strtod (s, &s);
+    if (++tokcount > dim) {
+      fprintf (qh ferr, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
+          qh feasible_string, dim);
+      break;
+    }
+    *(coords++)= value;
+    if (*s)
+      s++;
+  }
+  while (++tokcount <= dim)    
+    *(coords++)= 0.0;
+} /* setfeasible */
+
+/*---------------------------------
+  
+  qh_skipfacet( facet )
+    returns 'True' if this facet is not to be printed 
+
+  notes:
+    based on the user provided slice thresholds and 'good' specifications
+*/
+boolT qh_skipfacet(facetT *facet) {
+  facetT *neighbor, **neighborp;
+
+  if (qh PRINTneighbors) {
+    if (facet->good)
+      return !qh PRINTgood;
+    FOREACHneighbor_(facet) {
+      if (neighbor->good)
+	return False;
+    }
+    return True;
+  }else if (qh PRINTgood)
+    return !facet->good;
+  else if (!facet->normal)
+    return True;
+  return (!qh_inthresholds (facet->normal, NULL));
+} /* skipfacet */
+

Added: trunk/scipy/spatial/qhull/src/io.h
===================================================================
--- trunk/scipy/spatial/qhull/src/io.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/io.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,154 @@
+/*
  ---------------------------------
+
+   io.h 
+   declarations of Input/Output functions
+
+   see README, qhull.h and io.c
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#ifndef qhDEFio
+#define qhDEFio 1
+
+/*============ constants and flags ==================*/
+
+/*----------------------------------
+  
+  qh_MAXfirst
+    maximum length of first two lines of stdin
+*/
+#define qh_MAXfirst  200
+
+/*----------------------------------
+  
+  qh_MINradius
+    min radius for Gp and Gv, fraction of maxcoord
+*/
+#define qh_MINradius 0.02
+
+/*----------------------------------
+  
+  qh_GEOMepsilon
+    adjust outer planes for 'lines closer' and geomview roundoff.  
+    This prevents bleed through.
+*/
+#define qh_GEOMepsilon 2e-3
+
+/*----------------------------------
+  
+  qh_WHITESPACE
+    possible values of white space
+*/
+#define qh_WHITESPACE " \n\t\v\r\f"
+
+
+/*----------------------------------
+  
+  qh_RIDGE
+    to select which ridges to print in qh_eachvoronoi
+*/
+typedef enum
+{
+    qh_RIDGEall = 0, qh_RIDGEinner, qh_RIDGEouter
+}
+qh_RIDGE;
+
+/*----------------------------------
+  
+  printvridgeT
+    prints results of qh_printvdiagram
+
+  see:
+    qh_printvridge for an example
+*/
+typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+
+/*============== -prototypes in alphabetical order =========*/
+
+void    dfacet( unsigned id);
+void    dvertex( unsigned id);
+int	qh_compare_facetarea(const void *p1, const void *p2);
+int	qh_compare_facetmerge(const void *p1, const void *p2);
+int	qh_compare_facetvisit(const void *p1, const void *p2);
+int	qh_compare_vertexpoint(const void *p1, const void *p2); /* not used */
+
+void    qh_countfacets (facetT *facetlist, setT *facets, boolT printall, 
+              int *numfacetsp, int *numsimplicialp, int *totneighborsp, 
+              int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
+pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
+setT   *qh_detvridge (vertexT *vertex);
+setT   *qh_detvridge3 (vertexT *atvertex, vertexT *vertex);
+int     qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
+int     qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder);
+void	qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist);
+setT   *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
+void    qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane);
+void    qh_markkeep (facetT *facetlist);
+setT   *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp);
+void    qh_order_vertexneighbors(vertexT *vertex);
+void	qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall);
+void    qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void 	qh_printcenter (FILE *fp, int format, char *string, facetT *facet);
+void    qh_printcentrum (FILE *fp, facetT *facet, realT radius);
+void    qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printend4geom (FILE *fp, facetT *facet, int *num, boolT printall);
+void    qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void    qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void    qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void	qh_printfacet(FILE *fp, facetT *facet);
+void	qh_printfacet2math(FILE *fp, facetT *facet, int format, int notfirst);
+void	qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
+			       facetT *facet, realT offset, realT color[3]);
+void	qh_printfacet3math (FILE *fp, facetT *facet, int format, int notfirst);
+void	qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void	qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
+void	qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void	qh_printfacet3vertex(FILE *fp, facetT *facet, int format);
+void	qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void	qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void	qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format);
+void	qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format);
+void    qh_printfacetheader(FILE *fp, facetT *facet);
+void    qh_printfacetridges(FILE *fp, facetT *facet);
+void	qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void	qh_printhelp_degenerate(FILE *fp);
+void	qh_printhelp_singular(FILE *fp);
+void	qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
+  		   setT *vertices, realT color[3]);
+void	qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
+void    qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
+void	qh_printpoint(FILE *fp, char *string, pointT *point);
+void	qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id);
+void    qh_printpoint3 (FILE *fp, pointT *point);
+void    qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall);
+void    qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
+void    qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
+void	qh_printridge(FILE *fp, ridgeT *ridge);
+void    qh_printspheres(FILE *fp, setT *vertices, realT radius);
+void    qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+int     qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
+void	qh_printvertex(FILE *fp, vertexT *vertex);
+void	qh_printvertexlist (FILE *fp, char* string, facetT *facetlist,
+                         setT *facets, boolT printall);
+void	qh_printvertices (FILE *fp, char* string, setT *vertices);
+void    qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall);
+void    qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void    qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void	qh_produce_output(void);
+void    qh_projectdim3 (pointT *source, pointT *destination);
+int     qh_readfeasible (int dim, char *remainder);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+void    qh_setfeasible (int dim);
+boolT	qh_skipfacet(facetT *facet);
+
+#endif /* qhDEFio */

Added: trunk/scipy/spatial/qhull/src/mem.c
===================================================================
--- trunk/scipy/spatial/qhull/src/mem.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/mem.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,450 @@
+/*
  ---------------------------------
+
+  mem.c 
+    memory management routines for qhull
+
+  This is a standalone program.
+   
+  To initialize memory:
+
+    qh_meminit (stderr);  
+    qh_meminitbuffers (qh IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
+    qh_memsize(sizeof(facetT));
+    qh_memsize(sizeof(facetT));
+    ...
+    qh_memsetup();
+    
+  To free up all memory buffers:
+    qh_memfreeshort (&curlong, &totlong);
+         
+  if qh_NOmem, 
+    malloc/free is used instead of mem.c
+
+  notes: 
+    uses Quickfit algorithm (freelists for commonly allocated sizes)
+    assumes small sizes for freelists (it discards the tail of memory buffers)
+   
+  see:
+    qh-mem.htm and mem.h
+    global.c (qh_initbuffers) for an example of using mem.c 
+   
+  copyright (c) 1993-2003 The Geometry Center
+*/
+
+#include 
+#include 
+#include 
+#include "mem.h"
+
+#ifndef qhDEFqhull
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+void    qh_errexit(int exitcode, facetT *, ridgeT *);
+#endif
+
+/*============ -global data structure ==============
+    see mem.h for definition
+*/
+
+qhmemT qhmem= {0};     /* remove "= {0}" if this causes a compiler error */
+
+#ifndef qh_NOmem
+
+/*============= internal functions ==============*/
+  
+static int qh_intcompare(const void *i, const void *j);
+
+/*========== functions in alphabetical order ======== */
+
+/*---------------------------------
+  
+  qh_intcompare( i, j )
+    used by qsort and bsearch to compare two integers
+*/
+static int qh_intcompare(const void *i, const void *j) {
+  return(*((int *)i) - *((int *)j));
+} /* intcompare */
+
+
+/*----------------------------------
+   
+  qh_memalloc( insize )  
+    returns object of insize bytes
+    qhmem is the global memory structure 
+    
+  returns:
+    pointer to allocated memory 
+    errors if insufficient memory
+
+  notes:
+    use explicit type conversion to avoid type warnings on some compilers
+    actual object may be larger than insize
+    use qh_memalloc_() for inline code for quick allocations
+    logs allocations if 'T5'
+  
+  design:
+    if size < qhmem.LASTsize
+      if qhmem.freelists[size] non-empty
+        return first object on freelist
+      else
+        round up request to size of qhmem.freelists[size]
+        allocate new allocation buffer if necessary
+        allocate object from allocation buffer
+    else
+      allocate object with malloc()
+*/
+void *qh_memalloc(int insize) {
+  void **freelistp, *newbuffer;
+  int index, size;
+  int outsize, bufsize;
+  void *object;
+
+  if ((unsigned) insize <= (unsigned) qhmem.LASTsize) {
+    index= qhmem.indextable[insize];
+    freelistp= qhmem.freelists+index;
+    if ((object= *freelistp)) {
+      qhmem.cntquick++;  
+      *freelistp= *((void **)*freelistp);  /* replace freelist with next object */
+      return (object);
+    }else {
+      outsize= qhmem.sizetable[index];
+      qhmem.cntshort++;
+      if (outsize > qhmem .freesize) {
+	if (!qhmem.curbuffer)
+	  bufsize= qhmem.BUFinit;
+        else
+	  bufsize= qhmem.BUFsize;
+        qhmem.totshort += bufsize;
+	if (!(newbuffer= malloc(bufsize))) {
+	  fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
+	  qh_errexit(qhmem_ERRmem, NULL, NULL);
+	} 
+	*((void **)newbuffer)= qhmem.curbuffer;  /* prepend newbuffer to curbuffer 
+						    list */
+	qhmem.curbuffer= newbuffer;
+        size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
+	qhmem.freemem= (void *)((char *)newbuffer+size);
+	qhmem.freesize= bufsize - size;
+      }
+      object= qhmem.freemem;
+      qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
+      qhmem.freesize -= outsize;
+      return object;
+    }
+  }else {                     /* long allocation */
+    if (!qhmem.indextable) {
+      fprintf (qhmem.ferr, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
+      qh_errexit(qhmem_ERRqhull, NULL, NULL);
+    }
+    outsize= insize;
+    qhmem .cntlong++;
+    qhmem .curlong++;
+    qhmem .totlong += outsize;
+    if (qhmem.maxlong < qhmem.totlong)
+      qhmem.maxlong= qhmem.totlong;
+    if (!(object= malloc(outsize))) {
+      fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
+      qh_errexit(qhmem_ERRmem, NULL, NULL);
+    }
+    if (qhmem.IStracing >= 5)
+      fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", outsize, object);
+  }
+  return (object);
+} /* memalloc */
+
+
+/*----------------------------------
+   
+  qh_memfree( object, size ) 
+    free up an object of size bytes
+    size is insize from qh_memalloc
+
+  notes:
+    object may be NULL
+    type checking warns if using (void **)object
+    use qh_memfree_() for quick free's of small objects
+ 
+  design:
+    if size <= qhmem.LASTsize
+      append object to corresponding freelist
+    else
+      call free(object)
+*/
+void qh_memfree(void *object, int size) {
+  void **freelistp;
+
+  if (!object)
+    return;
+  if (size <= qhmem.LASTsize) {
+    qhmem .freeshort++;
+    freelistp= qhmem.freelists + qhmem.indextable[size];
+    *((void **)object)= *freelistp;
+    *freelistp= object;
+  }else {
+    qhmem .freelong++;
+    qhmem .totlong -= size;
+    free (object);
+    if (qhmem.IStracing >= 5)
+      fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
+  }
+} /* memfree */
+
+
+/*---------------------------------
+  
+  qh_memfreeshort( curlong, totlong )
+    frees up all short and qhmem memory allocations
+
+  returns:
+    number and size of current long allocations
+*/
+void qh_memfreeshort (int *curlong, int *totlong) {
+  void *buffer, *nextbuffer;
+  FILE *ferr;
+
+  *curlong= qhmem .cntlong - qhmem .freelong;
+  *totlong= qhmem .totlong;
+  for(buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
+    nextbuffer= *((void **) buffer);
+    free(buffer);
+  }
+  qhmem.curbuffer= NULL;
+  if (qhmem .LASTsize) {
+    free (qhmem .indextable);
+    free (qhmem .freelists);
+    free (qhmem .sizetable);
+  }
+  ferr= qhmem.ferr;
+  memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
+  qhmem.ferr= ferr;
+} /* memfreeshort */
+
+
+/*----------------------------------
+   
+  qh_meminit( ferr )
+    initialize qhmem and test sizeof( void*)
+*/
+void qh_meminit (FILE *ferr) {
+  
+  memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
+  qhmem.ferr= ferr;
+  if (sizeof(void*) < sizeof(int)) {
+    fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int).  qset.c will not work\n");
+    exit (1);  /* can not use qh_errexit() */
+  }
+} /* meminit */
+
+/*---------------------------------
+  
+  qh_meminitbuffers( tracelevel, alignment, numsizes, bufsize, bufinit )
+    initialize qhmem
+    if tracelevel >= 5, trace memory allocations
+    alignment= desired address alignment for memory allocations
+    numsizes= number of freelists
+    bufsize=  size of additional memory buffers for short allocations
+    bufinit=  size of initial memory buffer for short allocations
+*/
+void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
+
+  qhmem.IStracing= tracelevel;
+  qhmem.NUMsizes= numsizes;
+  qhmem.BUFsize= bufsize;
+  qhmem.BUFinit= bufinit;
+  qhmem.ALIGNmask= alignment-1;
+  if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  qhmem.sizetable= (int *) calloc (numsizes, sizeof(int));
+  qhmem.freelists= (void **) calloc (numsizes, sizeof(void *));
+  if (!qhmem.sizetable || !qhmem.freelists) {
+    fprintf(qhmem.ferr, "qhull error (qh_meminit): insufficient memory\n");
+    qh_errexit (qhmem_ERRmem, NULL, NULL);
+  }
+  if (qhmem.IStracing >= 1)
+    fprintf (qhmem.ferr, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
+} /* meminitbuffers */
+
+/*---------------------------------
+  
+  qh_memsetup()
+    set up memory after running memsize()
+*/
+void qh_memsetup (void) {
+  int k,i;
+
+  qsort(qhmem.sizetable, qhmem.TABLEsize, sizeof(int), qh_intcompare);
+  qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
+  if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) {
+    fprintf (qhmem.ferr, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
+            qhmem .LASTsize, qhmem .BUFsize, qhmem .BUFinit);
+    qh_errexit(qhmem_ERRmem, NULL, NULL);
+  }
+  if (!(qhmem.indextable= (int *)malloc((qhmem.LASTsize+1) * sizeof(int)))) {
+    fprintf(qhmem.ferr, "qhull error (qh_memsetup): insufficient memory\n");
+    qh_errexit(qhmem_ERRmem, NULL, NULL);
+  }
+  for(k=qhmem.LASTsize+1; k--; )
+    qhmem.indextable[k]= k;
+  i= 0;
+  for(k= 0; k <= qhmem.LASTsize; k++) {
+    if (qhmem.indextable[k] <= qhmem.sizetable[i])
+      qhmem.indextable[k]= i;
+    else
+      qhmem.indextable[k]= ++i;
+  }
+} /* memsetup */
+
+/*---------------------------------
+  
+  qh_memsize( size )
+    define a free list for this size
+*/
+void qh_memsize(int size) {
+  int k;
+
+  if (qhmem .LASTsize) {
+    fprintf (qhmem .ferr, "qhull error (qh_memsize): called after qhmem_setup\n");
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
+  for(k= qhmem.TABLEsize; k--; ) {
+    if (qhmem.sizetable[k] == size)
+      return;
+  }
+  if (qhmem.TABLEsize < qhmem.NUMsizes)
+    qhmem.sizetable[qhmem.TABLEsize++]= size;
+  else
+    fprintf(qhmem.ferr, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
+} /* memsize */
+
+
+/*---------------------------------
+  
+  qh_memstatistics( fp )
+    print out memory statistics
+
+  notes:
+    does not account for wasted memory at the end of each block
+*/
+void qh_memstatistics (FILE *fp) {
+  int i, count, totfree= 0;
+  void *object;
+  
+  for (i=0; i < qhmem.TABLEsize; i++) {
+    count=0;
+    for (object= qhmem .freelists[i]; object; object= *((void **)object))
+      count++;
+    totfree += qhmem.sizetable[i] * count;
+  }
+  fprintf (fp, "\nmemory statistics:\n\
+%7d quick allocations\n\
+%7d short allocations\n\
+%7d long allocations\n\
+%7d short frees\n\
+%7d long frees\n\
+%7d bytes of short memory in use\n\
+%7d bytes of short memory in freelists\n\
+%7d bytes of long memory allocated (except for input)\n\
+%7d bytes of long memory in use (in %d pieces)\n\
+%7d bytes per memory buffer (initially %d bytes)\n",
+	   qhmem .cntquick, qhmem.cntshort, qhmem.cntlong,
+	   qhmem .freeshort, qhmem.freelong, 
+	   qhmem .totshort - qhmem .freesize - totfree,
+	   totfree,
+	   qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong,
+	   qhmem .BUFsize, qhmem .BUFinit);
+  if (qhmem.cntlarger) {
+    fprintf (fp, "%7d calls to qh_setlarger\n%7.2g     average copy size\n",
+	   qhmem.cntlarger, ((float) qhmem.totlarger)/ qhmem.cntlarger);
+    fprintf (fp, "  freelists (bytes->count):");
+  }
+  for (i=0; i < qhmem.TABLEsize; i++) {
+    count=0;
+    for (object= qhmem .freelists[i]; object; object= *((void **)object))
+      count++;
+    fprintf (fp, " %d->%d", qhmem.sizetable[i], count);
+  }
+  fprintf (fp, "\n\n");
+} /* memstatistics */
+
+
+/*---------------------------------
+  
+  qh_NOmem
+    turn off quick-fit memory allocation
+
+  notes:
+    uses malloc() and free() instead
+*/
+#else /* qh_NOmem */
+
+void *qh_memalloc(int insize) {
+  void *object;
+
+  if (!(object= malloc(insize))) {
+    fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
+    qh_errexit(qhmem_ERRmem, NULL, NULL);
+  }
+  if (qhmem.IStracing >= 5)
+    fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", insize, object);
+  return object;
+}
+
+void qh_memfree(void *object, int size) {
+
+  if (!object)
+    return;
+  free (object);
+  if (qhmem.IStracing >= 5)
+    fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
+}
+
+void qh_memfreeshort (int *curlong, int *totlong) {
+
+  memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
+  *curlong= 0;
+  *totlong= 0;
+}
+
+void qh_meminit (FILE *ferr) {
+
+  memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
+  qhmem.ferr= ferr;
+  if (sizeof(void*) < sizeof(int)) {
+    fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int).  qset.c will not work\n");
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+}
+
+void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
+
+  qhmem.IStracing= tracelevel;
+
+}
+
+void qh_memsetup (void) {
+
+}
+
+void qh_memsize(int size) {
+
+}
+
+void qh_memstatistics (FILE *fp) {
+
+}
+
+#endif /* qh_NOmem */

Added: trunk/scipy/spatial/qhull/src/mem.h
===================================================================
--- trunk/scipy/spatial/qhull/src/mem.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/mem.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,174 @@
+/*
  ---------------------------------
+
+   mem.h 
+     prototypes for memory management functions
+
+   see qh-mem.htm, mem.c and qset.h
+
+   for error handling, writes message and calls
+     qh_errexit (qhmem_ERRmem, NULL, NULL) if insufficient memory
+       and
+     qh_errexit (qhmem_ERRqhull, NULL, NULL) otherwise
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#ifndef qhDEFmem
+#define qhDEFmem
+
+/*---------------------------------
+  
+  qh_NOmem
+    turn off quick-fit memory allocation
+
+  notes:
+    mem.c implements Quickfit memory allocation for about 20% time
+    savings.  If it fails on your machine, try to locate the
+    problem, and send the answer to qhull at qhull.org.  If this can
+    not be done, define qh_NOmem to use malloc/free instead.
+
+   #define qh_NOmem
+*/
+
+/*-------------------------------------------
+    to avoid bus errors, memory allocation must consider alignment requirements.
+    malloc() automatically takes care of alignment.   Since mem.c manages
+    its own memory, we need to explicitly specify alignment in
+    qh_meminitbuffers().
+
+    A safe choice is sizeof(double).  sizeof(float) may be used if doubles 
+    do not occur in data structures and pointers are the same size.  Be careful
+    of machines (e.g., DEC Alpha) with large pointers.  If gcc is available, 
+    use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
+
+   see qh_MEMalign in user.h for qhull's alignment
+*/
+
+#define qhmem_ERRmem 4    /* matches qh_ERRmem in qhull.h */
+#define qhmem_ERRqhull 5  /* matches qh_ERRqhull in qhull.h */
+
+/*----------------------------------
+  
+  ptr_intT
+    for casting a void* to an integer-type
+  
+  notes:
+    On 64-bit machines, a pointer may be larger than an 'int'.  
+    qh_meminit() checks that 'long' holds a 'void*'
+*/
+typedef unsigned long ptr_intT;
+
+/*----------------------------------
+ 
+  qhmemT
+    global memory structure for mem.c
+ 
+ notes:
+   users should ignore qhmem except for writing extensions
+   qhmem is allocated in mem.c 
+   
+   qhmem could be swapable like qh and qhstat, but then
+   multiple qh's and qhmem's would need to keep in synch.  
+   A swapable qhmem would also waste memory buffers.  As long
+   as memory operations are atomic, there is no problem with
+   multiple qh structures being active at the same time.
+   If you need separate address spaces, you can swap the
+   contents of qhmem.
+*/
+typedef struct qhmemT qhmemT;
+extern qhmemT qhmem; 
+
+struct qhmemT {               /* global memory management variables */
+  int      BUFsize;	      /* size of memory allocation buffer */
+  int      BUFinit;	      /* initial size of memory allocation buffer */
+  int      TABLEsize;         /* actual number of sizes in free list table */
+  int      NUMsizes;          /* maximum number of sizes in free list table */
+  int      LASTsize;          /* last size in free list table */
+  int      ALIGNmask;         /* worst-case alignment, must be 2^n-1 */
+  void	 **freelists;          /* free list table, linked by offset 0 */
+  int     *sizetable;         /* size of each freelist */
+  int     *indextable;        /* size->index table */
+  void    *curbuffer;         /* current buffer, linked by offset 0 */
+  void    *freemem;           /*   free memory in curbuffer */
+  int 	   freesize;          /*   size of free memory in bytes */
+  void 	  *tempstack;         /* stack of temporary memory, managed by users */
+  FILE    *ferr;              /* file for reporting errors */
+  int      IStracing;         /* =5 if tracing memory allocations */
+  int      cntquick;          /* count of quick allocations */
+                              /* remove statistics doesn't effect speed */
+  int      cntshort;          /* count of short allocations */
+  int      cntlong;           /* count of long allocations */
+  int      curlong;           /* current count of inuse, long allocations */
+  int      freeshort;	      /* count of short memfrees */
+  int      freelong;	      /* count of long memfrees */
+  int      totshort;          /* total size of short allocations */
+  int      totlong;           /* total size of long allocations */
+  int      maxlong;           /* maximum totlong */
+  int      cntlarger;         /* count of setlarger's */
+  int      totlarger;         /* total copied by setlarger */
+};
+
+
+/*==================== -macros ====================*/
+
+/*----------------------------------
+   
+  qh_memalloc_(size, object, type)  
+    returns object of size bytes 
+	assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+
+#ifdef qh_NOmem
+#define qh_memalloc_(size, freelistp, object, type) {\
+  object= (type*)qh_memalloc (size); }
+#else /* !qh_NOmem */
+
+#define qh_memalloc_(size, freelistp, object, type) {\
+  freelistp= qhmem.freelists + qhmem.indextable[size];\
+  if ((object= (type*)*freelistp)) {\
+    qhmem.cntquick++;  \
+    *freelistp= *((void **)*freelistp);\
+  }else object= (type*)qh_memalloc (size);}
+#endif
+
+/*----------------------------------
+   
+  qh_memfree_(object, size) 
+    free up an object
+
+  notes:
+    object may be NULL
+    assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+#ifdef qh_NOmem
+#define qh_memfree_(object, size, freelistp) {\
+  qh_memfree (object, size); }
+#else /* !qh_NOmem */
+
+#define qh_memfree_(object, size, freelistp) {\
+  if (object) { \
+    qhmem .freeshort++;\
+    freelistp= qhmem.freelists + qhmem.indextable[size];\
+    *((void **)object)= *freelistp;\
+    *freelistp= object;}}
+#endif
+
+/*=============== prototypes in alphabetical order ============*/
+
+void *qh_memalloc(int insize);
+void qh_memfree (void *object, int size);
+void qh_memfreeshort (int *curlong, int *totlong);
+void qh_meminit (FILE *ferr);
+void qh_meminitbuffers (int tracelevel, int alignment, int numsizes,
+			int bufsize, int bufinit);
+void qh_memsetup (void);
+void qh_memsize(int size);
+void qh_memstatistics (FILE *fp);
+
+#endif /* qhDEFmem */

Added: trunk/scipy/spatial/qhull/src/merge.c
===================================================================
--- trunk/scipy/spatial/qhull/src/merge.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/merge.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,3619 @@
+/*
  ---------------------------------
+
+   merge.c 
+   merges non-convex facets
+
+   see qh-merge.htm and merge.h
+
+   other modules call qh_premerge() and qh_postmerge()
+
+   the user may call qh_postmerge() to perform additional merges.
+
+   To remove deleted facets and vertices (qhull() in qhull.c):
+     qh_partitionvisible (!qh_ALL, &numoutside);  // visible_list, newfacet_list
+     qh_deletevisible ();         // qh.visible_list
+     qh_resetlists (False, qh_RESETvisible);       // qh.visible_list newvertex_list newfacet_list 
+
+   assumes qh.CENTERtype= centrum
+
+   merges occur in qh_mergefacet and in qh_mergecycle
+   vertex->neighbors not set until the first merge occurs
+
+   copyright (c) 1993-2003 The Geometry Center        
+*/
+
+#include "qhull_a.h"
+
+#ifndef qh_NOmerge
+
+/*===== functions (alphabetical after premerge and postmerge) ======*/
+
+/*---------------------------------
+  
+  qh_premerge( apex, maxcentrum )
+    pre-merge nonconvex facets in qh.newfacet_list for apex
+    maxcentrum defines coplanar and concave (qh_test_appendmerge)
+
+  returns:
+    deleted facets added to qh.visible_list with facet->visible set
+
+  notes:
+    uses globals, qh.MERGEexact, qh.PREmerge
+
+  design:
+    mark duplicate ridges in qh.newfacet_list
+    merge facet cycles in qh.newfacet_list
+    merge duplicate ridges and concave facets in qh.newfacet_list
+    check merged facet cycles for degenerate and redundant facets
+    merge degenerate and redundant facets
+    collect coplanar and concave facets
+    merge concave, coplanar, degenerate, and redundant facets
+*/
+void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle) {
+  boolT othermerge= False;
+  facetT *newfacet;
+  
+  if (qh ZEROcentrum && qh_checkzero(!qh_ALL))
+    return;    
+  trace2((qh ferr, "qh_premerge: premerge centrum %2.2g angle %2.2g for apex v%d facetlist f%d\n",
+	    maxcentrum, maxangle, apex->id, getid_(qh newfacet_list)));
+  if (qh IStracing >= 4 && qh num_facets < 50)
+    qh_printlists();
+  qh centrum_radius= maxcentrum;
+  qh cos_max= maxangle;
+  qh degen_mergeset= qh_settemp (qh TEMPsize);
+  qh facet_mergeset= qh_settemp (qh TEMPsize);
+  if (qh hull_dim >=3) { 
+    qh_mark_dupridges (qh newfacet_list); /* facet_mergeset */
+    qh_mergecycle_all (qh newfacet_list, &othermerge);
+    qh_forcedmerges (&othermerge /* qh facet_mergeset */); 
+    FORALLnew_facets {  /* test samecycle merges */
+      if (!newfacet->simplicial && !newfacet->mergeridge)
+	qh_degen_redundant_neighbors (newfacet, NULL);
+    }
+    if (qh_merge_degenredundant())
+      othermerge= True;
+  }else /* qh hull_dim == 2 */
+    qh_mergecycle_all (qh newfacet_list, &othermerge);
+  qh_flippedmerges (qh newfacet_list, &othermerge);
+  if (!qh MERGEexact || zzval_(Ztotmerge)) {
+    zinc_(Zpremergetot);
+    qh POSTmerging= False;
+    qh_getmergeset_initial (qh newfacet_list);
+    qh_all_merges (othermerge, False);
+  }
+  qh_settempfree(&qh facet_mergeset);
+  qh_settempfree(&qh degen_mergeset);
+} /* premerge */
+  
+/*---------------------------------
+  
+  qh_postmerge( reason, maxcentrum, maxangle, vneighbors )
+    post-merge nonconvex facets as defined by maxcentrum and maxangle
+    'reason' is for reporting progress
+    if vneighbors, 
+      calls qh_test_vneighbors at end of qh_all_merge 
+    if firstmerge, 
+      calls qh_reducevertices before qh_getmergeset
+
+  returns:
+    if first call (qh.visible_list != qh.facet_list), 
+      builds qh.facet_newlist, qh.newvertex_list
+    deleted facets added to qh.visible_list with facet->visible
+    qh.visible_list == qh.facet_list
+
+  notes:
+
+
+  design:
+    if first call
+      set qh.visible_list and qh.newfacet_list to qh.facet_list
+      add all facets to qh.newfacet_list
+      mark non-simplicial facets, facet->newmerge
+      set qh.newvertext_list to qh.vertex_list
+      add all vertices to qh.newvertex_list
+      if a pre-merge occured
+        set vertex->delridge {will retest the ridge}
+        if qh.MERGEexact
+          call qh_reducevertices()
+      if no pre-merging 
+        merge flipped facets
+    determine non-convex facets
+    merge all non-convex facets
+*/
+void qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
+                      boolT vneighbors) {
+  facetT *newfacet;
+  boolT othermerges= False;
+  vertexT *vertex;
+
+  if (qh REPORTfreq || qh IStracing) {
+    qh_buildtracing (NULL, NULL);
+    qh_printsummary (qh ferr);
+    if (qh PRINTstatistics) 
+      qh_printallstatistics (qh ferr, "reason");
+    fprintf (qh ferr, "\n%s with 'C%.2g' and 'A%.2g'\n", 
+        reason, maxcentrum, maxangle);
+  }
+  trace2((qh ferr, "qh_postmerge: postmerge.  test vneighbors? %d\n",
+	    vneighbors));
+  qh centrum_radius= maxcentrum;
+  qh cos_max= maxangle;
+  qh POSTmerging= True;
+  qh degen_mergeset= qh_settemp (qh TEMPsize);
+  qh facet_mergeset= qh_settemp (qh TEMPsize);
+  if (qh visible_list != qh facet_list) {  /* first call */
+    qh NEWfacets= True;
+    qh visible_list= qh newfacet_list= qh facet_list;
+    FORALLnew_facets {
+      newfacet->newfacet= True;
+       if (!newfacet->simplicial)
+        newfacet->newmerge= True;
+     zinc_(Zpostfacets);
+    }
+    qh newvertex_list= qh vertex_list;
+    FORALLvertices
+      vertex->newlist= True;
+    if (qh VERTEXneighbors) { /* a merge has occurred */
+      FORALLvertices
+	vertex->delridge= True; /* test for redundant, needed? */
+      if (qh MERGEexact) {
+	if (qh hull_dim <= qh_DIMreduceBuild)
+	  qh_reducevertices(); /* was skipped during pre-merging */
+      }
+    }
+    if (!qh PREmerge && !qh MERGEexact) 
+      qh_flippedmerges (qh newfacet_list, &othermerges);
+  }
+  qh_getmergeset_initial (qh newfacet_list);
+  qh_all_merges (False, vneighbors);
+  qh_settempfree(&qh facet_mergeset);
+  qh_settempfree(&qh degen_mergeset);
+} /* post_merge */
+
+/*---------------------------------
+  
+  qh_all_merges( othermerge, vneighbors )
+    merge all non-convex facets
+    
+    set othermerge if already merged facets (for qh_reducevertices)
+    if vneighbors
+      tests vertex neighbors for convexity at end
+    qh.facet_mergeset lists the non-convex ridges in qh_newfacet_list
+    qh.degen_mergeset is defined
+    if qh.MERGEexact && !qh.POSTmerging, 
+      does not merge coplanar facets
+
+  returns:
+    deleted facets added to qh.visible_list with facet->visible
+    deleted vertices added qh.delvertex_list with vertex->delvertex
+  
+  notes:
+    unless !qh.MERGEindependent, 
+      merges facets in independent sets
+    uses qh.newfacet_list as argument since merges call qh_removefacet()
+
+  design:
+    while merges occur
+      for each merge in qh.facet_mergeset
+        unless one of the facets was already merged in this pass
+          merge the facets
+        test merged facets for additional merges
+        add merges to qh.facet_mergeset
+      if vertices record neighboring facets
+        rename redundant vertices
+          update qh.facet_mergeset
+    if vneighbors ??
+      tests vertex neighbors for convexity at end
+*/
+void qh_all_merges (boolT othermerge, boolT vneighbors) {
+  facetT *facet1, *facet2;
+  mergeT *merge;
+  boolT wasmerge= True, isreduce;
+  void **freelistp;  /* used !qh_NOmem */
+  vertexT *vertex;
+  mergeType mergetype;
+  int numcoplanar=0, numconcave=0, numdegenredun= 0, numnewmerges= 0;
+  
+  trace2((qh ferr, "qh_all_merges: starting to merge facets beginning from f%d\n",
+	    getid_(qh newfacet_list)));
+  while (True) {
+    wasmerge= False;
+    while (qh_setsize (qh facet_mergeset)) {
+      while ((merge= (mergeT*)qh_setdellast(qh facet_mergeset))) {
+	facet1= merge->facet1;
+	facet2= merge->facet2;
+	mergetype= merge->type;
+	qh_memfree_(merge, sizeof(mergeT), freelistp);
+	if (facet1->visible || facet2->visible) /*deleted facet*/
+	  continue;  
+	if ((facet1->newfacet && !facet1->tested)
+	        || (facet2->newfacet && !facet2->tested)) {
+	  if (qh MERGEindependent && mergetype <= MRGanglecoplanar)
+	    continue;      /* perform independent sets of merges */
+	}
+	qh_merge_nonconvex (facet1, facet2, mergetype);
+        numdegenredun += qh_merge_degenredundant();
+        numnewmerges++;
+        wasmerge= True;
+	if (mergetype == MRGconcave)
+	  numconcave++;
+	else /* MRGcoplanar or MRGanglecoplanar */
+	  numcoplanar++;
+      } /* while setdellast */
+      if (qh POSTmerging && qh hull_dim <= qh_DIMreduceBuild 
+      && numnewmerges > qh_MAXnewmerges) {
+	numnewmerges= 0;
+	qh_reducevertices();  /* otherwise large post merges too slow */
+      }
+      qh_getmergeset (qh newfacet_list); /* facet_mergeset */
+    } /* while mergeset */
+    if (qh VERTEXneighbors) {
+      isreduce= False;
+      if (qh hull_dim >=4 && qh POSTmerging) {
+	FORALLvertices  
+	  vertex->delridge= True;
+	isreduce= True;
+      }
+      if ((wasmerge || othermerge) && (!qh MERGEexact || qh POSTmerging) 
+	  && qh hull_dim <= qh_DIMreduceBuild) {
+	othermerge= False;
+	isreduce= True;
+      }
+      if (isreduce) {
+	if (qh_reducevertices()) {
+	  qh_getmergeset (qh newfacet_list); /* facet_mergeset */
+	  continue;
+	}
+      }
+    }
+    if (vneighbors && qh_test_vneighbors(/* qh newfacet_list */)) 
+      continue;
+    break;
+  } /* while (True) */
+  if (qh CHECKfrequently && !qh MERGEexact) {
+    qh old_randomdist= qh RANDOMdist;
+    qh RANDOMdist= False;
+    qh_checkconvex (qh newfacet_list, qh_ALGORITHMfault);
+    /* qh_checkconnect (); [this is slow and it changes the facet order] */
+    qh RANDOMdist= qh old_randomdist;
+  }
+  trace1((qh ferr, "qh_all_merges: merged %d coplanar facets %d concave facets and %d degen or redundant facets.\n",
+    numcoplanar, numconcave, numdegenredun));
+  if (qh IStracing >= 4 && qh num_facets < 50)
+    qh_printlists ();
+} /* all_merges */
+
+
+/*---------------------------------
+  
+  qh_appendmergeset( facet, neighbor, mergetype, angle )
+    appends an entry to qh.facet_mergeset or qh.degen_mergeset
+
+    angle ignored if NULL or !qh.ANGLEmerge
+
+  returns:
+    merge appended to facet_mergeset or degen_mergeset
+      sets ->degenerate or ->redundant if degen_mergeset
+  
+  see:
+    qh_test_appendmerge()
+
+  design:
+    allocate merge entry
+    if regular merge
+      append to qh.facet_mergeset
+    else if degenerate merge and qh.facet_mergeset is all degenerate
+      append to qh.degen_mergeset 
+    else if degenerate merge
+      prepend to qh.degen_mergeset 
+    else if redundant merge
+      append to qh.degen_mergeset 
+*/
+void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle) {
+  mergeT *merge, *lastmerge;
+  void **freelistp; /* used !qh_NOmem */
+
+  if (facet->redundant)
+    return;
+  if (facet->degenerate && mergetype == MRGdegen)
+    return;
+  qh_memalloc_(sizeof(mergeT), freelistp, merge, mergeT);
+  merge->facet1= facet;
+  merge->facet2= neighbor;
+  merge->type= mergetype;
+  if (angle && qh ANGLEmerge)
+    merge->angle= *angle;
+  if (mergetype < MRGdegen)
+    qh_setappend (&(qh facet_mergeset), merge);
+  else if (mergetype == MRGdegen) {
+    facet->degenerate= True;
+    if (!(lastmerge= (mergeT*)qh_setlast (qh degen_mergeset)) 
+    || lastmerge->type == MRGdegen)
+      qh_setappend (&(qh degen_mergeset), merge);
+    else
+      qh_setaddnth (&(qh degen_mergeset), 0, merge);
+  }else if (mergetype == MRGredundant) {
+    facet->redundant= True;
+    qh_setappend (&(qh degen_mergeset), merge);
+  }else /* mergetype == MRGmirror */ {
+    if (facet->redundant || neighbor->redundant) {
+      fprintf(qh ferr, "qhull error (qh_appendmergeset): facet f%d or f%d is already a mirrored facet\n",
+	   facet->id, neighbor->id);
+      qh_errexit2 (qh_ERRqhull, facet, neighbor);
+    }
+    if (!qh_setequal (facet->vertices, neighbor->vertices)) {
+      fprintf(qh ferr, "qhull error (qh_appendmergeset): mirrored facets f%d and f%d do not have the same vertices\n",
+	   facet->id, neighbor->id);
+      qh_errexit2 (qh_ERRqhull, facet, neighbor);
+    }
+    facet->redundant= True;
+    neighbor->redundant= True;
+    qh_setappend (&(qh degen_mergeset), merge);
+  }
+} /* appendmergeset */
+
+
+/*---------------------------------
+  
+  qh_basevertices( samecycle )
+    return temporary set of base vertices for samecycle
+    samecycle is first facet in the cycle
+    assumes apex is SETfirst_( samecycle->vertices )
+
+  returns:
+    vertices (settemp)
+    all ->seen are cleared
+
+  notes:
+    uses qh_vertex_visit;
+
+  design:
+    for each facet in samecycle
+      for each unseen vertex in facet->vertices
+        append to result  
+*/
+setT *qh_basevertices (facetT *samecycle) {
+  facetT *same;
+  vertexT *apex, *vertex, **vertexp;
+  setT *vertices= qh_settemp (qh TEMPsize);
+  
+  apex= SETfirstt_(samecycle->vertices, vertexT);
+  apex->visitid= ++qh vertex_visit;
+  FORALLsame_cycle_(samecycle) {
+    if (same->mergeridge)
+      continue;
+    FOREACHvertex_(same->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        qh_setappend (&vertices, vertex);
+        vertex->visitid= qh vertex_visit;
+        vertex->seen= False;
+      }
+    }
+  }
+  trace4((qh ferr, "qh_basevertices: found %d vertices\n", 
+         qh_setsize (vertices)));
+  return vertices;
+} /* basevertices */
+
+/*---------------------------------
+  
+  qh_checkconnect()
+    check that new facets are connected
+    new facets are on qh.newfacet_list
+    
+  notes:
+    this is slow and it changes the order of the facets
+    uses qh.visit_id
+
+  design:
+    move first new facet to end of qh.facet_list
+    for all newly appended facets
+      append unvisited neighbors to end of qh.facet_list
+    for all new facets
+      report error if unvisited
+*/
+void qh_checkconnect (void /* qh newfacet_list */) {
+  facetT *facet, *newfacet, *errfacet= NULL, *neighbor, **neighborp;
+
+  facet= qh newfacet_list;
+  qh_removefacet (facet);
+  qh_appendfacet (facet);
+  facet->visitid= ++qh visit_id;
+  FORALLfacet_(facet) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+        qh_removefacet (neighbor);
+        qh_appendfacet (neighbor);
+        neighbor->visitid= qh visit_id;
+      }
+    }
+  }
+  FORALLnew_facets {
+    if (newfacet->visitid == qh visit_id)
+      break;
+    fprintf(qh ferr, "qhull error: f%d is not attached to the new facets\n",
+         newfacet->id);
+    errfacet= newfacet;
+  }
+  if (errfacet)
+    qh_errexit (qh_ERRqhull, errfacet, NULL);
+} /* checkconnect */
+
+/*---------------------------------
+  
+  qh_checkzero( testall )
+    check that facets are clearly convex for qh.DISTround with qh.MERGEexact
+
+    if testall, 
+      test all facets for qh.MERGEexact post-merging
+    else 
+      test qh.newfacet_list
+      
+    if qh.MERGEexact, 
+      allows coplanar ridges
+      skips convexity test while qh.ZEROall_ok
+
+  returns:
+    True if all facets !flipped, !dupridge, normal
+         if all horizon facets are simplicial
+         if all vertices are clearly below neighbor
+         if all opposite vertices of horizon are below 
+    clears qh.ZEROall_ok if any problems or coplanar facets
+
+  notes:
+    uses qh.vertex_visit
+    horizon facets may define multiple new facets
+
+  design:
+    for all facets in qh.newfacet_list or qh.facet_list
+      check for flagged faults (flipped, etc.)
+    for all facets in qh.newfacet_list or qh.facet_list
+      for each neighbor of facet
+        skip horizon facets for qh.newfacet_list
+        test the opposite vertex
+      if qh.newfacet_list
+        test the other vertices in the facet's horizon facet
+*/
+boolT qh_checkzero (boolT testall) {
+  facetT *facet, *neighbor, **neighborp;
+  facetT *horizon, *facetlist;
+  int neighbor_i;
+  vertexT *vertex, **vertexp;
+  realT dist;
+
+  if (testall) 
+    facetlist= qh facet_list;
+  else {
+    facetlist= qh newfacet_list;
+    FORALLfacet_(facetlist) {
+      horizon= SETfirstt_(facet->neighbors, facetT);
+      if (!horizon->simplicial)
+        goto LABELproblem;
+      if (facet->flipped || facet->dupridge || !facet->normal)
+        goto LABELproblem;
+    }
+    if (qh MERGEexact && qh ZEROall_ok) {
+      trace2((qh ferr, "qh_checkzero: skip convexity check until first pre-merge\n"));
+      return True;
+    }
+  }
+  FORALLfacet_(facetlist) {
+    qh vertex_visit++;
+    neighbor_i= 0;
+    horizon= NULL;
+    FOREACHneighbor_(facet) {
+      if (!neighbor_i && !testall) {
+        horizon= neighbor;
+	neighbor_i++;
+        continue; /* horizon facet tested in qh_findhorizon */
+      }
+      vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
+      vertex->visitid= qh vertex_visit;
+      zzinc_(Zdistzero);
+      qh_distplane (vertex->point, neighbor, &dist);
+      if (dist >= -qh DISTround) {
+        qh ZEROall_ok= False;
+        if (!qh MERGEexact || testall || dist > qh DISTround)
+          goto LABELnonconvex;
+      }
+    }
+    if (!testall) {
+      FOREACHvertex_(horizon->vertices) {
+	if (vertex->visitid != qh vertex_visit) {
+	  zzinc_(Zdistzero);
+	  qh_distplane (vertex->point, facet, &dist);
+	  if (dist >= -qh DISTround) {
+	    qh ZEROall_ok= False;
+	    if (!qh MERGEexact || dist > qh DISTround)
+	      goto LABELnonconvex;
+	  }
+	  break;
+	}
+      }
+    }
+  }
+  trace2((qh ferr, "qh_checkzero: testall %d, facets are %s\n", testall,
+        (qh MERGEexact && !testall) ? 
+           "not concave, flipped, or duplicate ridged" : "clearly convex"));
+  return True;
+
+ LABELproblem:
+  qh ZEROall_ok= False;
+  trace2((qh ferr, "qh_checkzero: facet f%d needs pre-merging\n",
+       facet->id));
+  return False;
+
+ LABELnonconvex:
+  trace2((qh ferr, "qh_checkzero: facet f%d and f%d are not clearly convex.  v%d dist %.2g\n",
+         facet->id, neighbor->id, vertex->id, dist));
+  return False;
+} /* checkzero */
+
+/*---------------------------------
+  
+  qh_compareangle( angle1, angle2 )
+    used by qsort() to order merges by angle
+*/
+int qh_compareangle(const void *p1, const void *p2) {
+  mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2);
+ 
+  return ((a->angle > b->angle) ? 1 : -1);
+} /* compareangle */
+
+/*---------------------------------
+  
+  qh_comparemerge( merge1, merge2 )
+    used by qsort() to order merges
+*/
+int qh_comparemerge(const void *p1, const void *p2) {
+  mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2);
+ 
+  return (a->type - b->type);
+} /* comparemerge */
+
+/*---------------------------------
+  
+  qh_comparevisit( vertex1, vertex2 )
+    used by qsort() to order vertices by their visitid
+*/
+int qh_comparevisit (const void *p1, const void *p2) {
+  vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2);
+ 
+  return (a->visitid - b->visitid);
+} /* comparevisit */
+
+/*---------------------------------
+  
+  qh_copynonconvex( atridge )
+    set non-convex flag on other ridges (if any) between same neighbors
+
+  notes:
+    may be faster if use smaller ridge set
+
+  design:
+    for each ridge of atridge's top facet
+      if ridge shares the same neighbor
+        set nonconvex flag
+*/
+void qh_copynonconvex (ridgeT *atridge) {
+  facetT *facet, *otherfacet;
+  ridgeT *ridge, **ridgep;
+
+  facet= atridge->top;
+  otherfacet= atridge->bottom;
+  FOREACHridge_(facet->ridges) {
+    if (otherfacet == otherfacet_(ridge, facet) && ridge != atridge) {
+      ridge->nonconvex= True;
+      trace4((qh ferr, "qh_copynonconvex: moved nonconvex flag from r%d to r%d\n",
+	      atridge->id, ridge->id));
+      break;
+    }
+  }
+} /* copynonconvex */
+
+/*---------------------------------
+  
+  qh_degen_redundant_facet( facet )
+    check facet for degen. or redundancy
+
+  notes:
+    bumps vertex_visit
+    called if a facet was redundant but no longer is (qh_merge_degenredundant)
+    qh_appendmergeset() only appends first reference to facet (i.e., redundant)
+
+  see:
+    qh_degen_redundant_neighbors()
+
+  design:
+    test for redundant neighbor
+    test for degenerate facet
+*/
+void qh_degen_redundant_facet (facetT *facet) {
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+
+  trace4((qh ferr, "qh_degen_redundant_facet: test facet f%d for degen/redundant\n",
+	  facet->id));
+  FOREACHneighbor_(facet) {
+    qh vertex_visit++;
+    FOREACHvertex_(neighbor->vertices)
+      vertex->visitid= qh vertex_visit;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit)
+	break;
+    }
+    if (!vertex) {
+      qh_appendmergeset (facet, neighbor, MRGredundant, NULL);
+      trace2((qh ferr, "qh_degen_redundant_facet: f%d is contained in f%d.  merge\n", facet->id, neighbor->id)); 
+      return;
+    }
+  }
+  if (qh_setsize (facet->neighbors) < qh hull_dim) {
+    qh_appendmergeset (facet, facet, MRGdegen, NULL);
+    trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate.\n", facet->id));
+  }
+} /* degen_redundant_facet */
+
+
+/*---------------------------------
+  
+  qh_degen_redundant_neighbors( facet, delfacet,  )
+    append degenerate and redundant neighbors to facet_mergeset
+    if delfacet, 
+      only checks neighbors of both delfacet and facet
+    also checks current facet for degeneracy
+
+  notes:
+    bumps vertex_visit
+    called for each qh_mergefacet() and qh_mergecycle()
+    merge and statistics occur in merge_nonconvex
+    qh_appendmergeset() only appends first reference to facet (i.e., redundant)
+      it appends redundant facets after degenerate ones
+
+    a degenerate facet has fewer than hull_dim neighbors
+    a redundant facet's vertices is a subset of its neighbor's vertices
+    tests for redundant merges first (appendmergeset is nop for others)
+    in a merge, only needs to test neighbors of merged facet
+  
+  see:
+    qh_merge_degenredundant() and qh_degen_redundant_facet()
+
+  design:
+    test for degenerate facet
+    test for redundant neighbor
+    test for degenerate neighbor
+*/
+void qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet) {
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+  int size;
+
+  trace4((qh ferr, "qh_degen_redundant_neighbors: test neighbors of f%d with delfacet f%d\n", 
+	  facet->id, getid_(delfacet)));
+  if ((size= qh_setsize (facet->neighbors)) < qh hull_dim) {
+    qh_appendmergeset (facet, facet, MRGdegen, NULL);
+    trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.\n", facet->id, size));
+  }
+  if (!delfacet)
+    delfacet= facet;
+  qh vertex_visit++;
+  FOREACHvertex_(facet->vertices)
+    vertex->visitid= qh vertex_visit;
+  FOREACHneighbor_(delfacet) {
+    /* uses early out instead of checking vertex count */
+    if (neighbor == facet)
+      continue;
+    FOREACHvertex_(neighbor->vertices) {
+      if (vertex->visitid != qh vertex_visit)
+        break;
+    }
+    if (!vertex) {
+      qh_appendmergeset (neighbor, facet, MRGredundant, NULL);
+      trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is contained in f%d.  merge\n", neighbor->id, facet->id)); 
+    }
+  }
+  FOREACHneighbor_(delfacet) {   /* redundant merges occur first */
+    if (neighbor == facet)
+      continue;
+    if ((size= qh_setsize (neighbor->neighbors)) < qh hull_dim) {
+      qh_appendmergeset (neighbor, neighbor, MRGdegen, NULL);
+      trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.  Neighbor of f%d.\n", neighbor->id, size, facet->id)); 
+    }
+  }
+} /* degen_redundant_neighbors */
+
+
+/*---------------------------------
+  
+  qh_find_newvertex( oldvertex, vertices, ridges )
+    locate new vertex for renaming old vertex
+    vertices is a set of possible new vertices
+      vertices sorted by number of deleted ridges
+
+  returns:
+    newvertex or NULL
+      each ridge includes both vertex and oldvertex
+    vertices sorted by number of deleted ridges
+      
+  notes:
+    modifies vertex->visitid
+    new vertex is in one of the ridges
+    renaming will not cause a duplicate ridge
+    renaming will minimize the number of deleted ridges
+    newvertex may not be adjacent in the dual (though unlikely)
+
+  design:
+    for each vertex in vertices
+      set vertex->visitid to number of references in ridges
+    remove unvisited vertices 
+    set qh.vertex_visit above all possible values
+    sort vertices by number of references in ridges
+    add each ridge to qh.hash_table
+    for each vertex in vertices
+      look for a vertex that would not cause a duplicate ridge after a rename
+*/
+vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges) {
+  vertexT *vertex, **vertexp;
+  setT *newridges;
+  ridgeT *ridge, **ridgep;
+  int size, hashsize;
+  int hash;
+
+#ifndef qh_NOtrace
+  if (qh IStracing >= 4) {
+    fprintf (qh ferr, "qh_find_newvertex: find new vertex for v%d from ",
+	     oldvertex->id);
+    FOREACHvertex_(vertices) 
+      fprintf (qh ferr, "v%d ", vertex->id);
+    FOREACHridge_(ridges)
+      fprintf (qh ferr, "r%d ", ridge->id);
+    fprintf (qh ferr, "\n");
+  }
+#endif
+  FOREACHvertex_(vertices) 
+    vertex->visitid= 0;
+  FOREACHridge_(ridges) {
+    FOREACHvertex_(ridge->vertices) 
+      vertex->visitid++;
+  }
+  FOREACHvertex_(vertices) {
+    if (!vertex->visitid) {
+      qh_setdelnth (vertices, SETindex_(vertices,vertex));
+      vertexp--; /* repeat since deleted this vertex */
+    }
+  }
+  qh vertex_visit += qh_setsize (ridges);
+  if (!qh_setsize (vertices)) {
+    trace4((qh ferr, "qh_find_newvertex: vertices not in ridges for v%d\n",
+	    oldvertex->id));
+    return NULL;
+  }
+  qsort (SETaddr_(vertices, vertexT), qh_setsize (vertices),
+	        sizeof (vertexT *), qh_comparevisit);
+  /* can now use qh vertex_visit */
+  if (qh PRINTstatistics) {
+    size= qh_setsize (vertices);
+    zinc_(Zintersect);
+    zadd_(Zintersecttot, size);
+    zmax_(Zintersectmax, size);
+  }
+  hashsize= qh_newhashtable (qh_setsize (ridges));
+  FOREACHridge_(ridges)
+    qh_hashridge (qh hash_table, hashsize, ridge, oldvertex);
+  FOREACHvertex_(vertices) {
+    newridges= qh_vertexridges (vertex);
+    FOREACHridge_(newridges) {
+      if (qh_hashridge_find (qh hash_table, hashsize, ridge, vertex, oldvertex, &hash)) {
+	zinc_(Zdupridge);
+	break;
+      }
+    }
+    qh_settempfree (&newridges);
+    if (!ridge)
+      break;  /* found a rename */
+  }
+  if (vertex) {
+    /* counted in qh_renamevertex */
+    trace2((qh ferr, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n",
+      vertex->id, oldvertex->id, qh_setsize (vertices), qh_setsize (ridges)));
+  }else {
+    zinc_(Zfindfail);
+    trace0((qh ferr, "qh_find_newvertex: no vertex for renaming v%d (all duplicated ridges) during p%d\n",
+      oldvertex->id, qh furthest_id));
+  }
+  qh_setfree (&qh hash_table);
+  return vertex;
+} /* find_newvertex */
+
+/*---------------------------------
+  
+  qh_findbest_test( testcentrum, facet, neighbor, bestfacet, dist, mindist, maxdist )
+    test neighbor of facet for qh_findbestneighbor()
+    if testcentrum,
+      tests centrum (assumes it is defined)
+    else 
+      tests vertices
+
+  returns:
+    if a better facet (i.e., vertices/centrum of facet closer to neighbor)
+      updates bestfacet, dist, mindist, and maxdist
+*/
+void qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
+      facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) {
+  realT dist, mindist, maxdist;
+
+  if (testcentrum) {
+    zzinc_(Zbestdist);
+    qh_distplane(facet->center, neighbor, &dist);
+    dist *= qh hull_dim; /* estimate furthest vertex */
+    if (dist < 0) {
+      maxdist= 0;
+      mindist= dist;
+      dist= -dist;
+    }else
+      maxdist= dist;
+  }else
+    dist= qh_getdistance (facet, neighbor, &mindist, &maxdist);
+  if (dist < *distp) {
+    *bestfacet= neighbor;
+    *mindistp= mindist;
+    *maxdistp= maxdist;
+    *distp= dist;
+  }
+} /* findbest_test */
+
+/*---------------------------------
+  
+  qh_findbestneighbor( facet, dist, mindist, maxdist )
+    finds best neighbor (least dist) of a facet for merging
+
+  returns:
+    returns min and max distances and their max absolute value
+  
+  notes:
+    avoids merging old into new
+    assumes ridge->nonconvex only set on one ridge between a pair of facets
+    could use an early out predicate but not worth it
+
+  design:
+    if a large facet
+      will test centrum
+    else
+      will test vertices
+    if a large facet
+      test nonconvex neighbors for best merge
+    else
+      test all neighbors for the best merge
+    if testing centrum
+      get distance information
+*/
+facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) {
+  facetT *neighbor, **neighborp, *bestfacet= NULL;
+  ridgeT *ridge, **ridgep;
+  boolT nonconvex= True, testcentrum= False;
+  int size= qh_setsize (facet->vertices);
+
+  *distp= REALmax;
+  if (size > qh_BESTcentrum2 * qh hull_dim + qh_BESTcentrum) {
+    testcentrum= True;
+    zinc_(Zbestcentrum);
+    if (!facet->center)
+       facet->center= qh_getcentrum (facet);
+  }
+  if (size > qh hull_dim + qh_BESTnonconvex) {
+    FOREACHridge_(facet->ridges) {
+      if (ridge->nonconvex) {
+        neighbor= otherfacet_(ridge, facet);
+	qh_findbest_test (testcentrum, facet, neighbor,
+			  &bestfacet, distp, mindistp, maxdistp);
+      }
+    }
+  }
+  if (!bestfacet) {     
+    nonconvex= False;
+    FOREACHneighbor_(facet)
+      qh_findbest_test (testcentrum, facet, neighbor,
+			&bestfacet, distp, mindistp, maxdistp);
+  }
+  if (!bestfacet) {
+    fprintf (qh ferr, "qhull internal error (qh_findbestneighbor): no neighbors for f%d\n", facet->id);
+    
+    qh_errexit (qh_ERRqhull, facet, NULL);
+  }
+  if (testcentrum) 
+    qh_getdistance (facet, bestfacet, mindistp, maxdistp);
+  trace3((qh ferr, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n",
+     bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp));
+  return(bestfacet);
+} /* findbestneighbor */
+
+
+/*---------------------------------
+  
+  qh_flippedmerges( facetlist, wasmerge )
+    merge flipped facets into best neighbor
+    assumes qh.facet_mergeset at top of temporary stack
+
+  returns:
+    no flipped facets on facetlist
+    sets wasmerge if merge occurred
+    degen/redundant merges passed through
+
+  notes:
+    othermerges not needed since qh.facet_mergeset is empty before & after
+      keep it in case of change
+
+  design:
+    append flipped facets to qh.facetmergeset
+    for each flipped merge
+      find best neighbor
+      merge facet into neighbor
+      merge degenerate and redundant facets
+    remove flipped merges from qh.facet_mergeset
+*/
+void qh_flippedmerges(facetT *facetlist, boolT *wasmerge) {
+  facetT *facet, *neighbor, *facet1;
+  realT dist, mindist, maxdist;
+  mergeT *merge, **mergep;
+  setT *othermerges;
+  int nummerge=0;
+
+  trace4((qh ferr, "qh_flippedmerges: begin\n"));
+  FORALLfacet_(facetlist) {
+    if (facet->flipped && !facet->visible) 
+      qh_appendmergeset (facet, facet, MRGflip, NULL);
+  }
+  othermerges= qh_settemppop(); /* was facet_mergeset */
+  qh facet_mergeset= qh_settemp (qh TEMPsize);
+  qh_settemppush (othermerges);
+  FOREACHmerge_(othermerges) {
+    facet1= merge->facet1;
+    if (merge->type != MRGflip || facet1->visible) 
+      continue;
+    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+      qhmem.IStracing= qh IStracing= qh TRACElevel;
+    neighbor= qh_findbestneighbor (facet1, &dist, &mindist, &maxdist);
+    trace0((qh ferr, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g during p%d\n",
+      facet1->id, neighbor->id, dist, qh furthest_id));
+    qh_mergefacet (facet1, neighbor, &mindist, &maxdist, !qh_MERGEapex);
+    nummerge++;
+    if (qh PRINTstatistics) {
+      zinc_(Zflipped);
+      wadd_(Wflippedtot, dist);
+      wmax_(Wflippedmax, dist);
+    }
+    qh_merge_degenredundant();
+  }
+  FOREACHmerge_(othermerges) {
+    if (merge->facet1->visible || merge->facet2->visible)
+      qh_memfree (merge, sizeof(mergeT));
+    else
+      qh_setappend (&qh facet_mergeset, merge);
+  }
+  qh_settempfree (&othermerges);
+  if (nummerge)
+    *wasmerge= True;
+  trace1((qh ferr, "qh_flippedmerges: merged %d flipped facets into a good neighbor\n", nummerge));
+} /* flippedmerges */
+
+
+/*---------------------------------
+  
+  qh_forcedmerges( wasmerge )
+    merge duplicated ridges
+
+  returns:
+    removes all duplicate ridges on facet_mergeset
+    wasmerge set if merge
+    qh.facet_mergeset may include non-forced merges (none for now)
+    qh.degen_mergeset includes degen/redun merges
+
+  notes: 
+    duplicate ridges occur when the horizon is pinched,
+        i.e. a subridge occurs in more than two horizon ridges.
+     could rename vertices that pinch the horizon
+    assumes qh_merge_degenredundant() has not be called
+    othermerges isn't needed since facet_mergeset is empty afterwards
+      keep it in case of change
+
+  design:
+    for each duplicate ridge
+      find current facets by chasing f.replace links
+      determine best direction for facet
+      merge one facet into the other
+      remove duplicate ridges from qh.facet_mergeset
+*/
+void qh_forcedmerges(boolT *wasmerge) {
+  facetT *facet1, *facet2;
+  mergeT *merge, **mergep;
+  realT dist1, dist2, mindist1, mindist2, maxdist1, maxdist2;
+  setT *othermerges;
+  int nummerge=0, numflip=0;
+
+  if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+    qhmem.IStracing= qh IStracing= qh TRACElevel;
+  trace4((qh ferr, "qh_forcedmerges: begin\n"));  
+  othermerges= qh_settemppop(); /* was facet_mergeset */
+  qh facet_mergeset= qh_settemp (qh TEMPsize);
+  qh_settemppush (othermerges);
+  FOREACHmerge_(othermerges) {
+    if (merge->type != MRGridge) 
+    	continue;
+    facet1= merge->facet1;
+    facet2= merge->facet2;
+    while (facet1->visible)    	 /* must exist, no qh_merge_degenredunant */
+      facet1= facet1->f.replace; /* previously merged facet */
+    while (facet2->visible)
+      facet2= facet2->f.replace; /* previously merged facet */
+    if (facet1 == facet2)
+      continue;
+    if (!qh_setin (facet2->neighbors, facet1)) {
+      fprintf (qh ferr, "qhull internal error (qh_forcedmerges): f%d and f%d had a duplicate ridge but as f%d and f%d they are no longer neighbors\n",
+	       merge->facet1->id, merge->facet2->id, facet1->id, facet2->id);
+      qh_errexit2 (qh_ERRqhull, facet1, facet2);
+    }
+    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+      qhmem.IStracing= qh IStracing= qh TRACElevel;
+    dist1= qh_getdistance (facet1, facet2, &mindist1, &maxdist1);
+    dist2= qh_getdistance (facet2, facet1, &mindist2, &maxdist2);
+    trace0((qh ferr, "qh_forcedmerges: duplicate ridge between f%d and f%d, dist %2.2g and reverse dist %2.2g during p%d\n",
+	    facet1->id, facet2->id, dist1, dist2, qh furthest_id));
+    if (dist1 < dist2) 
+      qh_mergefacet (facet1, facet2, &mindist1, &maxdist1, !qh_MERGEapex);
+    else {
+      qh_mergefacet (facet2, facet1, &mindist2, &maxdist2, !qh_MERGEapex);
+      dist1= dist2;
+      facet1= facet2;
+    }
+    if (facet1->flipped) {
+      zinc_(Zmergeflipdup);
+      numflip++;
+    }else
+      nummerge++;
+    if (qh PRINTstatistics) {
+      zinc_(Zduplicate);
+      wadd_(Wduplicatetot, dist1);
+      wmax_(Wduplicatemax, dist1);
+    }
+  }
+  FOREACHmerge_(othermerges) {
+    if (merge->type == MRGridge)
+      qh_memfree (merge, sizeof(mergeT));
+    else
+      qh_setappend (&qh facet_mergeset, merge);
+  }
+  qh_settempfree (&othermerges);
+  if (nummerge)
+    *wasmerge= True;
+  trace1((qh ferr, "qh_forcedmerges: merged %d facets and %d flipped facets across duplicated ridges\n", 
+                nummerge, numflip));
+} /* forcedmerges */
+
+
+/*---------------------------------
+  
+  qh_getmergeset( facetlist )
+    determines nonconvex facets on facetlist
+    tests !tested ridges and nonconvex ridges of !tested facets
+
+  returns:
+    returns sorted qh.facet_mergeset of facet-neighbor pairs to be merged
+    all ridges tested
+  
+  notes:
+    assumes no nonconvex ridges with both facets tested
+    uses facet->tested/ridge->tested to prevent duplicate tests
+    can not limit tests to modified ridges since the centrum changed
+    uses qh.visit_id
+  
+  see:
+    qh_getmergeset_initial()
+
+  design:
+    for each facet on facetlist
+      for each ridge of facet
+        if untested ridge
+          test ridge for convexity
+          if non-convex
+            append ridge to qh.facet_mergeset
+    sort qh.facet_mergeset by angle  
+*/
+void qh_getmergeset(facetT *facetlist) {
+  facetT *facet, *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int nummerges;
+  
+  nummerges= qh_setsize (qh facet_mergeset);
+  trace4((qh ferr, "qh_getmergeset: started.\n"));
+  qh visit_id++;
+  FORALLfacet_(facetlist) {
+    if (facet->tested)
+      continue;
+    facet->visitid= qh visit_id;
+    facet->tested= True;  /* must be non-simplicial due to merge */
+    FOREACHneighbor_(facet)
+      neighbor->seen= False;
+    FOREACHridge_(facet->ridges) {
+      if (ridge->tested && !ridge->nonconvex)
+	continue;
+      /* if tested & nonconvex, need to append merge */
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->seen) {
+	ridge->tested= True;
+	ridge->nonconvex= False;
+      }else if (neighbor->visitid != qh visit_id) {
+        ridge->tested= True;
+        ridge->nonconvex= False;
+	neighbor->seen= True;      /* only one ridge is marked nonconvex */
+	if (qh_test_appendmerge (facet, neighbor))
+	  ridge->nonconvex= True;
+      }
+    }
+  }
+  nummerges= qh_setsize (qh facet_mergeset);
+  if (qh ANGLEmerge)
+    qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
+  else
+    qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_comparemerge);
+  if (qh POSTmerging) {
+    zadd_(Zmergesettot2, nummerges);
+  }else {
+    zadd_(Zmergesettot, nummerges);
+    zmax_(Zmergesetmax, nummerges);
+  }
+  trace2((qh ferr, "qh_getmergeset: %d merges found\n", nummerges));
+} /* getmergeset */
+
+
+/*---------------------------------
+  
+  qh_getmergeset_initial( facetlist )
+    determine initial qh.facet_mergeset for facets
+    tests all facet/neighbor pairs on facetlist
+
+  returns:
+    sorted qh.facet_mergeset with nonconvex ridges
+    sets facet->tested, ridge->tested, and ridge->nonconvex
+
+  notes:
+    uses visit_id, assumes ridge->nonconvex is False
+
+  see:
+    qh_getmergeset()
+
+  design:
+    for each facet on facetlist
+      for each untested neighbor of facet
+        test facet and neighbor for convexity
+        if non-convex
+          append merge to qh.facet_mergeset
+          mark one of the ridges as nonconvex
+    sort qh.facet_mergeset by angle
+*/
+void qh_getmergeset_initial (facetT *facetlist) {
+  facetT *facet, *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int nummerges;
+
+  qh visit_id++;
+  FORALLfacet_(facetlist) {
+    facet->visitid= qh visit_id;
+    facet->tested= True;
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+        if (qh_test_appendmerge (facet, neighbor)) {
+          FOREACHridge_(neighbor->ridges) {
+            if (facet == otherfacet_(ridge, neighbor)) {
+              ridge->nonconvex= True;
+              break;	/* only one ridge is marked nonconvex */
+            }
+          }
+        }
+      }
+    }
+    FOREACHridge_(facet->ridges)
+      ridge->tested= True;
+  }
+  nummerges= qh_setsize (qh facet_mergeset);
+  if (qh ANGLEmerge)
+    qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
+  else
+    qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_comparemerge);
+  if (qh POSTmerging) {
+    zadd_(Zmergeinittot2, nummerges);
+  }else {
+    zadd_(Zmergeinittot, nummerges);
+    zmax_(Zmergeinitmax, nummerges);
+  }
+  trace2((qh ferr, "qh_getmergeset_initial: %d merges found\n", nummerges));
+} /* getmergeset_initial */
+
+
+/*---------------------------------
+  
+  qh_hashridge( hashtable, hashsize, ridge, oldvertex )
+    add ridge to hashtable without oldvertex
+
+  notes:
+    assumes hashtable is large enough
+
+  design:
+    determine hash value for ridge without oldvertex
+    find next empty slot for ridge
+*/
+void qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) {
+  int hash;
+  ridgeT *ridgeA;
+
+  hash= (int)qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex);
+  while (True) {
+    if (!(ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
+      SETelem_(hashtable, hash)= ridge;
+      break;
+    }else if (ridgeA == ridge)
+      break;
+    if (++hash == hashsize)
+      hash= 0;
+  }
+} /* hashridge */
+
+
+/*---------------------------------
+  
+  qh_hashridge_find( hashtable, hashsize, ridge, vertex, oldvertex, hashslot )
+    returns matching ridge without oldvertex in hashtable 
+      for ridge without vertex
+    if oldvertex is NULL 
+      matches with any one skip
+
+  returns:
+    matching ridge or NULL
+    if no match,
+      if ridge already in   table
+        hashslot= -1 
+      else 
+        hashslot= next NULL index
+        
+  notes:
+    assumes hashtable is large enough
+    can't match ridge to itself
+
+  design:
+    get hash value for ridge without vertex
+    for each hashslot
+      return match if ridge matches ridgeA without oldvertex
+*/
+ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge, 
+              vertexT *vertex, vertexT *oldvertex, int *hashslot) {
+  int hash;
+  ridgeT *ridgeA;
+
+  *hashslot= 0;
+  zinc_(Zhashridge);
+  hash= (int)qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, vertex);
+  while ((ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
+    if (ridgeA == ridge)
+      *hashslot= -1;      
+    else {
+      zinc_(Zhashridgetest);
+      if (qh_setequal_except (ridge->vertices, vertex, ridgeA->vertices, oldvertex))
+        return ridgeA;
+    }
+    if (++hash == hashsize)
+      hash= 0;
+  }
+  if (!*hashslot)
+    *hashslot= hash;
+  return NULL;
+} /* hashridge_find */
+
+
+/*---------------------------------
+  
+  qh_makeridges( facet )
+    creates explicit ridges between simplicial facets
+
+  returns:
+    facet with ridges and without qh_MERGEridge
+    ->simplicial is False
+  
+  notes:
+    allows qh_MERGEridge flag
+    uses existing ridges
+    duplicate neighbors ok if ridges already exist (qh_mergecycle_ridges)
+
+  see:
+    qh_mergecycle_ridges()
+
+  design:
+    look for qh_MERGEridge neighbors
+    mark neighbors that already have ridges
+    for each unprocessed neighbor of facet    
+      create a ridge for neighbor and facet
+    if any qh_MERGEridge neighbors
+      delete qh_MERGEridge flags (already handled by qh_mark_dupridges)
+*/
+void qh_makeridges(facetT *facet) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int neighbor_i, neighbor_n;
+  boolT toporient, mergeridge= False;
+  
+  if (!facet->simplicial)
+    return;
+  trace4((qh ferr, "qh_makeridges: make ridges for f%d\n", facet->id));
+  facet->simplicial= False;
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge)
+      mergeridge= True;
+    else
+      neighbor->seen= False;
+  }
+  FOREACHridge_(facet->ridges)
+    otherfacet_(ridge, facet)->seen= True;
+  FOREACHneighbor_i_(facet) {
+    if (neighbor == qh_MERGEridge)
+      continue;  /* fixed by qh_mark_dupridges */
+    else if (!neighbor->seen) {  /* no current ridges */
+      ridge= qh_newridge();
+      ridge->vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
+					                  neighbor_i, 0);
+      toporient= facet->toporient ^ (neighbor_i & 0x1);
+      if (toporient) {
+        ridge->top= facet;
+        ridge->bottom= neighbor;
+      }else {
+        ridge->top= neighbor;
+        ridge->bottom= facet;
+      }
+#if 0 /* this also works */
+      flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1);
+      if (facet->toporient ^ (skip1 & 0x1) ^ flip) {
+        ridge->top= neighbor;
+        ridge->bottom= facet;
+      }else {
+        ridge->top= facet;
+        ridge->bottom= neighbor;
+      }
+#endif
+      qh_setappend(&(facet->ridges), ridge);
+      qh_setappend(&(neighbor->ridges), ridge);
+    }
+  }
+  if (mergeridge) {
+    while (qh_setdel (facet->neighbors, qh_MERGEridge))
+      ; /* delete each one */
+  }
+} /* makeridges */
+
+
+/*---------------------------------
+  
+  qh_mark_dupridges( facetlist )
+    add duplicated ridges to qh.facet_mergeset
+    facet->dupridge is true
+
+  returns:
+    duplicate ridges on qh.facet_mergeset
+    ->mergeridge/->mergeridge2 set
+    duplicate ridges marked by qh_MERGEridge and both sides facet->dupridge
+    no MERGEridges in neighbor sets
+    
+  notes:
+    duplicate ridges occur when the horizon is pinched,
+        i.e. a subridge occurs in more than two horizon ridges.
+    could rename vertices that pinch the horizon
+    uses qh.visit_id
+
+  design:
+    for all facets on facetlist
+      if facet contains a duplicate ridge
+        for each neighbor of facet
+          if neighbor marked qh_MERGEridge (one side of the merge)
+            set facet->mergeridge      
+          else
+            if neighbor contains a duplicate ridge 
+            and the back link is qh_MERGEridge
+              append duplicate ridge to qh.facet_mergeset
+   for each duplicate ridge
+     make ridge sets in preparation for merging
+     remove qh_MERGEridge from neighbor set
+   for each duplicate ridge
+     restore the missing neighbor from the neighbor set that was qh_MERGEridge
+     add the missing ridge for this neighbor
+*/
+void qh_mark_dupridges(facetT *facetlist) {
+  facetT *facet, *neighbor, **neighborp;
+  int nummerge=0;
+  mergeT *merge, **mergep;
+  
+
+  trace4((qh ferr, "qh_mark_dupridges: identify duplicate ridges\n"));  
+  FORALLfacet_(facetlist) {
+    if (facet->dupridge) {
+      FOREACHneighbor_(facet) {
+        if (neighbor == qh_MERGEridge) {
+	  facet->mergeridge= True;
+	  continue;
+	}
+        if (neighbor->dupridge
+	&& !qh_setin (neighbor->neighbors, facet)) { /* qh_MERGEridge */
+	  qh_appendmergeset (facet, neighbor, MRGridge, NULL);
+	  facet->mergeridge2= True;
+	  facet->mergeridge= True;
+	  nummerge++;
+	}
+      }
+    }
+  }
+  if (!nummerge)
+    return;
+  FORALLfacet_(facetlist) {            /* gets rid of qh_MERGEridge */
+    if (facet->mergeridge && !facet->mergeridge2)   
+      qh_makeridges (facet);
+  }
+  FOREACHmerge_(qh facet_mergeset) {   /* restore the missing neighbors */
+    if (merge->type == MRGridge) {
+      qh_setappend (&merge->facet2->neighbors, merge->facet1);
+      qh_makeridges (merge->facet1);   /* and the missing ridges */
+    }
+  }
+  trace1((qh ferr, "qh_mark_dupridges: found %d duplicated ridges\n", 
+                nummerge));
+} /* mark_dupridges */
+
+/*---------------------------------
+  
+  qh_maydropneighbor( facet )
+    drop neighbor relationship if no ridge between facet and neighbor
+
+  returns:
+    neighbor sets updated
+    appends degenerate facets to qh.facet_mergeset
+  
+  notes:
+    won't cause redundant facets since vertex inclusion is the same
+    may drop vertex and neighbor if no ridge
+    uses qh.visit_id
+
+  design:
+    visit all neighbors with ridges
+    for each unvisited neighbor of facet
+      delete neighbor and facet from the neighbor sets
+      if neighbor becomes degenerate
+        append neighbor to qh.degen_mergeset
+    if facet is degenerate
+      append facet to qh.degen_mergeset
+*/
+void qh_maydropneighbor (facetT *facet) {
+  ridgeT *ridge, **ridgep;
+  realT angledegen= qh_ANGLEdegen;
+  facetT *neighbor, **neighborp;
+
+  qh visit_id++;
+  trace4((qh ferr, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n",
+	  facet->id));
+  FOREACHridge_(facet->ridges) {
+    ridge->top->visitid= qh visit_id;
+    ridge->bottom->visitid= qh visit_id;
+  }
+  FOREACHneighbor_(facet) {
+    if (neighbor->visitid != qh visit_id) {
+      trace0((qh ferr, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors during p%d\n",
+	    facet->id, neighbor->id, qh furthest_id));
+      zinc_(Zdropneighbor);
+      qh_setdel (facet->neighbors, neighbor);
+      neighborp--;  /* repeat, deleted a neighbor */
+      qh_setdel (neighbor->neighbors, facet);
+      if (qh_setsize (neighbor->neighbors) < qh hull_dim) {
+        zinc_(Zdropdegen);
+        qh_appendmergeset (neighbor, neighbor, MRGdegen, &angledegen);
+        trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id));
+      }
+    }
+  }
+  if (qh_setsize (facet->neighbors) < qh hull_dim) {
+    zinc_(Zdropdegen);
+    qh_appendmergeset (facet, facet, MRGdegen, &angledegen);
+    trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", facet->id));
+  }
+} /* maydropneighbor */
+
+
+/*---------------------------------
+  
+  qh_merge_degenredundant()
+    merge all degenerate and redundant facets
+    qh.degen_mergeset contains merges from qh_degen_redundant_neighbors()
+
+  returns:
+    number of merges performed
+    resets facet->degenerate/redundant
+    if deleted (visible) facet has no neighbors
+      sets ->f.replace to NULL
+
+  notes:
+    redundant merges happen before degenerate ones
+    merging and renaming vertices can result in degen/redundant facets
+
+  design:
+    for each merge on qh.degen_mergeset
+      if redundant merge
+        if non-redundant facet merged into redundant facet
+          recheck facet for redundancy
+        else
+          merge redundant facet into other facet
+*/
+int qh_merge_degenredundant (void) {
+  int size;
+  mergeT *merge;
+  facetT *bestneighbor, *facet1, *facet2;
+  realT dist, mindist, maxdist;
+  vertexT *vertex, **vertexp;
+  int nummerges= 0;
+  mergeType mergetype;
+
+  while ((merge= (mergeT*)qh_setdellast (qh degen_mergeset))) {
+    facet1= merge->facet1;
+    facet2= merge->facet2;
+    mergetype= merge->type;
+    qh_memfree (merge, sizeof(mergeT));
+    if (facet1->visible)
+      continue;
+    facet1->degenerate= False; 
+    facet1->redundant= False; 
+    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+      qhmem.IStracing= qh IStracing= qh TRACElevel;
+    if (mergetype == MRGredundant) {
+      zinc_(Zneighbor);
+      while (facet2->visible) {
+        if (!facet2->f.replace) {
+          fprintf (qh ferr, "qhull internal error (qh_merge_degenredunant): f%d redundant but f%d has no replacement\n",
+	       facet1->id, facet2->id);
+          qh_errexit2 (qh_ERRqhull, facet1, facet2);
+        }
+        facet2= facet2->f.replace;
+      }
+      if (facet1 == facet2) {
+	qh_degen_redundant_facet (facet1); /* in case of others */
+	continue;
+      }
+      trace2((qh ferr, "qh_merge_degenredundant: facet f%d is contained in f%d, will merge\n",
+	    facet1->id, facet2->id));
+      qh_mergefacet(facet1, facet2, NULL, NULL, !qh_MERGEapex);
+      /* merge distance is already accounted for */
+      nummerges++;
+    }else {  /* mergetype == MRGdegen, other merges may have fixed */
+      if (!(size= qh_setsize (facet1->neighbors))) {
+        zinc_(Zdelfacetdup);
+        trace2((qh ferr, "qh_merge_degenredundant: facet f%d has no neighbors.  Deleted\n", facet1->id));
+        qh_willdelete (facet1, NULL);
+        FOREACHvertex_(facet1->vertices) {
+  	  qh_setdel (vertex->neighbors, facet1);
+	  if (!SETfirst_(vertex->neighbors)) {
+	    zinc_(Zdegenvertex);
+	    trace2((qh ferr, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n",
+         	 vertex->id, facet1->id));
+	    vertex->deleted= True;
+	    qh_setappend (&qh del_vertices, vertex);
+	  }
+        }
+        nummerges++;
+      }else if (size < qh hull_dim) {
+        bestneighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
+        trace2((qh ferr, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n",
+	      facet1->id, size, bestneighbor->id, dist));
+        qh_mergefacet(facet1, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
+        nummerges++;
+        if (qh PRINTstatistics) {
+	  zinc_(Zdegen);
+	  wadd_(Wdegentot, dist);
+	  wmax_(Wdegenmax, dist);
+        }
+      }	/* else, another merge fixed the degeneracy and redundancy tested */
+    }
+  }
+  return nummerges;
+} /* merge_degenredundant */
+
+/*---------------------------------
+  
+  qh_merge_nonconvex( facet1, facet2, mergetype )
+    remove non-convex ridge between facet1 into facet2 
+    mergetype gives why the facet's are non-convex
+
+  returns:
+    merges one of the facets into the best neighbor
+    
+  design:
+    if one of the facets is a new facet
+      prefer merging new facet into old facet
+    find best neighbors for both facets
+    merge the nearest facet into its best neighbor
+    update the statistics
+*/
+void qh_merge_nonconvex (facetT *facet1, facetT *facet2, mergeType mergetype) {
+  facetT *bestfacet, *bestneighbor, *neighbor;
+  realT dist, dist2, mindist, mindist2, maxdist, maxdist2;
+
+  if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+    qhmem.IStracing= qh IStracing= qh TRACElevel;
+  trace3((qh ferr, "qh_merge_nonconvex: merge #%d for f%d and f%d type %d\n",
+      zzval_(Ztotmerge) + 1, facet1->id, facet2->id, mergetype));
+  /* concave or coplanar */
+  if (!facet1->newfacet) {
+    bestfacet= facet2;   /* avoid merging old facet if new is ok */
+    facet2= facet1;
+    facet1= bestfacet;
+  }else
+    bestfacet= facet1;
+  bestneighbor= qh_findbestneighbor(bestfacet, &dist, &mindist, &maxdist);
+  neighbor= qh_findbestneighbor(facet2, &dist2, &mindist2, &maxdist2);
+  if (dist < dist2) {
+    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
+  }else if (qh AVOIDold && !facet2->newfacet
+  && ((mindist >= -qh MAXcoplanar && maxdist <= qh max_outside)
+       || dist * 1.5 < dist2)) {
+    zinc_(Zavoidold);
+    wadd_(Wavoidoldtot, dist);
+    wmax_(Wavoidoldmax, dist);
+    trace2((qh ferr, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g.  Use f%d dist %2.2g instead\n",
+           facet2->id, dist2, facet1->id, dist2));
+    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
+  }else {
+    qh_mergefacet(facet2, neighbor, &mindist2, &maxdist2, !qh_MERGEapex);
+    dist= dist2;
+  }
+  if (qh PRINTstatistics) {
+    if (mergetype == MRGanglecoplanar) {
+      zinc_(Zacoplanar);
+      wadd_(Wacoplanartot, dist);
+      wmax_(Wacoplanarmax, dist);
+    }else if (mergetype == MRGconcave) {
+      zinc_(Zconcave);
+      wadd_(Wconcavetot, dist);
+      wmax_(Wconcavemax, dist);
+    }else { /* MRGcoplanar */
+      zinc_(Zcoplanar);
+      wadd_(Wcoplanartot, dist);
+      wmax_(Wcoplanarmax, dist);
+    }
+  }
+} /* merge_nonconvex */
+
+/*---------------------------------
+  
+  qh_mergecycle( samecycle, newfacet )
+    merge a cycle of facets starting at samecycle into a newfacet 
+    newfacet is a horizon facet with ->normal
+    samecycle facets are simplicial from an apex
+
+  returns:
+    initializes vertex neighbors on first merge
+    samecycle deleted (placed on qh.visible_list)
+    newfacet at end of qh.facet_list
+    deleted vertices on qh.del_vertices
+
+  see:
+    qh_mergefacet()
+    called by qh_mergecycle_all() for multiple, same cycle facets
+
+  design:
+    make vertex neighbors if necessary
+    make ridges for newfacet
+    merge neighbor sets of samecycle into newfacet
+    merge ridges of samecycle into newfacet
+    merge vertex neighbors of samecycle into newfacet
+    make apex of samecycle the apex of newfacet
+    if newfacet wasn't a new facet
+      add its vertices to qh.newvertex_list
+    delete samecycle facets a make newfacet a newfacet
+*/
+void qh_mergecycle (facetT *samecycle, facetT *newfacet) {
+  int traceonce= False, tracerestore= 0;
+  vertexT *apex;
+#ifndef qh_NOtrace
+  facetT *same;
+#endif
+
+  if (newfacet->tricoplanar) {
+    if (!qh TRInormals) {
+      fprintf (qh ferr, "qh_mergecycle: does not work for tricoplanar facets.  Use option 'Q11'\n");
+      qh_errexit (qh_ERRqhull, newfacet, NULL);
+    }
+    newfacet->tricoplanar= False;
+    newfacet->keepcentrum= False;
+  }
+  if (!qh VERTEXneighbors)
+    qh_vertexneighbors();
+  zzinc_(Ztotmerge);
+  if (qh REPORTfreq2 && qh POSTmerging) {
+    if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
+      qh_tracemerging();
+  }
+#ifndef qh_NOtrace
+  if (qh TRACEmerge == zzval_(Ztotmerge))
+    qhmem.IStracing= qh IStracing= qh TRACElevel;
+  trace2((qh ferr, "qh_mergecycle: merge #%d for facets from cycle f%d into coplanar horizon f%d\n", 
+        zzval_(Ztotmerge), samecycle->id, newfacet->id));
+  if (newfacet == qh tracefacet) {
+    tracerestore= qh IStracing;
+    qh IStracing= 4;
+    fprintf (qh ferr, "qh_mergecycle: ========= trace merge %d of samecycle %d into trace f%d, furthest is p%d\n",
+	       zzval_(Ztotmerge), samecycle->id, newfacet->id,  qh furthest_id);
+    traceonce= True;
+  }
+  if (qh IStracing >=4) {
+    fprintf (qh ferr, "  same cycle:");
+    FORALLsame_cycle_(samecycle)
+      fprintf(qh ferr, " f%d", same->id);
+    fprintf (qh ferr, "\n");
+  }
+  if (qh IStracing >=4)
+    qh_errprint ("MERGING CYCLE", samecycle, newfacet, NULL, NULL);
+#endif /* !qh_NOtrace */
+  apex= SETfirstt_(samecycle->vertices, vertexT);
+  qh_makeridges (newfacet);
+  qh_mergecycle_neighbors (samecycle, newfacet);
+  qh_mergecycle_ridges (samecycle, newfacet);
+  qh_mergecycle_vneighbors (samecycle, newfacet);
+  if (SETfirstt_(newfacet->vertices, vertexT) != apex) 
+    qh_setaddnth (&newfacet->vertices, 0, apex);  /* apex has last id */
+  if (!newfacet->newfacet)
+    qh_newvertices (newfacet->vertices);
+  qh_mergecycle_facets (samecycle, newfacet);
+  qh_tracemerge (samecycle, newfacet);
+  /* check for degen_redundant_neighbors after qh_forcedmerges() */
+  if (traceonce) {
+    fprintf (qh ferr, "qh_mergecycle: end of trace facet\n");
+    qh IStracing= tracerestore;
+  }
+} /* mergecycle */
+
+/*---------------------------------
+  
+  qh_mergecycle_all( facetlist, wasmerge )
+    merge all samecycles of coplanar facets into horizon
+    don't merge facets with ->mergeridge (these already have ->normal)
+    all facets are simplicial from apex
+    all facet->cycledone == False
+
+  returns:
+    all newfacets merged into coplanar horizon facets
+    deleted vertices on  qh.del_vertices
+    sets wasmerge if any merge
+
+  see:
+    calls qh_mergecycle for multiple, same cycle facets
+
+  design:
+    for each facet on facetlist
+      skip facets with duplicate ridges and normals
+      check that facet is in a samecycle (->mergehorizon)
+      if facet only member of samecycle
+	sets vertex->delridge for all vertices except apex
+        merge facet into horizon
+      else
+        mark all facets in samecycle
+        remove facets with duplicate ridges from samecycle
+        merge samecycle into horizon (deletes facets from facetlist)
+*/
+void qh_mergecycle_all (facetT *facetlist, boolT *wasmerge) {
+  facetT *facet, *same, *prev, *horizon;
+  facetT *samecycle= NULL, *nextfacet, *nextsame;
+  vertexT *apex, *vertex, **vertexp;
+  int cycles=0, total=0, facets, nummerge;
+
+  trace2((qh ferr, "qh_mergecycle_all: begin\n"));
+  for (facet= facetlist; facet && (nextfacet= facet->next); facet= nextfacet) {
+    if (facet->normal)
+      continue;
+    if (!facet->mergehorizon) {
+      fprintf (qh ferr, "qh_mergecycle_all: f%d without normal\n", facet->id);
+      qh_errexit (qh_ERRqhull, facet, NULL);
+    }
+    horizon= SETfirstt_(facet->neighbors, facetT);
+    if (facet->f.samecycle == facet) {
+      zinc_(Zonehorizon);  
+      /* merge distance done in qh_findhorizon */
+      apex= SETfirstt_(facet->vertices, vertexT);
+      FOREACHvertex_(facet->vertices) {
+	if (vertex != apex)
+          vertex->delridge= True;
+      }
+      horizon->f.newcycle= NULL;
+      qh_mergefacet (facet, horizon, NULL, NULL, qh_MERGEapex);
+    }else {
+      samecycle= facet;
+      facets= 0;
+      prev= facet;
+      for (same= facet->f.samecycle; same;  /* FORALLsame_cycle_(facet) */
+	   same= (same == facet ? NULL :nextsame)) { /* ends at facet */
+	nextsame= same->f.samecycle;
+        if (same->cycledone || same->visible)
+          qh_infiniteloop (same);
+        same->cycledone= True;
+        if (same->normal) { 
+          prev->f.samecycle= same->f.samecycle; /* unlink ->mergeridge */
+	  same->f.samecycle= NULL;
+        }else {
+          prev= same;
+	  facets++;
+	}
+      }
+      while (nextfacet && nextfacet->cycledone)  /* will delete samecycle */
+	nextfacet= nextfacet->next;
+      horizon->f.newcycle= NULL;
+      qh_mergecycle (samecycle, horizon);
+      nummerge= horizon->nummerge + facets;
+      if (nummerge > qh_MAXnummerge) 
+      	horizon->nummerge= qh_MAXnummerge;
+      else
+        horizon->nummerge= nummerge;
+      zzinc_(Zcyclehorizon);
+      total += facets;
+      zzadd_(Zcyclefacettot, facets);
+      zmax_(Zcyclefacetmax, facets);
+    }
+    cycles++;
+  }
+  if (cycles)
+    *wasmerge= True;
+  trace1((qh ferr, "qh_mergecycle_all: merged %d same cycles or facets into coplanar horizons\n", cycles));
+} /* mergecycle_all */
+
+/*---------------------------------
+  
+  qh_mergecycle_facets( samecycle, newfacet )
+    finish merge of samecycle into newfacet
+
+  returns:
+    samecycle prepended to visible_list for later deletion and partitioning
+      each facet->f.replace == newfacet
+      
+    newfacet moved to end of qh.facet_list
+      makes newfacet a newfacet (get's facet1->id if it was old)
+      sets newfacet->newmerge
+      clears newfacet->center (unless merging into a large facet)
+      clears newfacet->tested and ridge->tested for facet1
+      
+    adds neighboring facets to facet_mergeset if redundant or degenerate
+
+  design:
+    make newfacet a new facet and set its flags
+    move samecycle facets to qh.visible_list for later deletion
+    unless newfacet is large
+      remove its centrum
+*/
+void qh_mergecycle_facets (facetT *samecycle, facetT *newfacet) {
+  facetT *same, *next;
+  
+  trace4((qh ferr, "qh_mergecycle_facets: make newfacet new and samecycle deleted\n"));  
+  qh_removefacet(newfacet);  /* append as a newfacet to end of qh facet_list */
+  qh_appendfacet(newfacet);
+  newfacet->newfacet= True;
+  newfacet->simplicial= False;
+  newfacet->newmerge= True;
+  
+  for (same= samecycle->f.samecycle; same; same= (same == samecycle ?  NULL : next)) {
+    next= same->f.samecycle;  /* reused by willdelete */
+    qh_willdelete (same, newfacet);
+  }
+  if (newfacet->center 
+      && qh_setsize (newfacet->vertices) <= qh hull_dim + qh_MAXnewcentrum) {
+    qh_memfree (newfacet->center, qh normal_size);
+    newfacet->center= NULL;
+  }
+  trace3((qh ferr, "qh_mergecycle_facets: merged facets from cycle f%d into f%d\n", 
+             samecycle->id, newfacet->id));
+} /* mergecycle_facets */
+
+/*---------------------------------
+  
+  qh_mergecycle_neighbors( samecycle, newfacet )
+    add neighbors for samecycle facets to newfacet
+
+  returns:
+    newfacet with updated neighbors and vice-versa
+    newfacet has ridges
+    all neighbors of newfacet marked with qh.visit_id
+    samecycle facets marked with qh.visit_id-1
+    ridges updated for simplicial neighbors of samecycle with a ridge
+
+  notes:
+    assumes newfacet not in samecycle
+    usually, samecycle facets are new, simplicial facets without internal ridges 
+      not so if horizon facet is coplanar to two different samecycles
+  
+  see:
+    qh_mergeneighbors()
+
+  design:
+    check samecycle
+    delete neighbors from newfacet that are also in samecycle
+    for each neighbor of a facet in samecycle
+      if neighbor is simplicial
+        if first visit
+          move the neighbor relation to newfacet
+          update facet links for its ridges
+        else
+          make ridges for neighbor
+          remove samecycle reference
+      else
+        update neighbor sets
+*/
+void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet) {
+  facetT *same, *neighbor, **neighborp;
+  int delneighbors= 0, newneighbors= 0;
+  unsigned int samevisitid;
+  ridgeT *ridge, **ridgep;
+
+  samevisitid= ++qh visit_id;
+  FORALLsame_cycle_(samecycle) {
+    if (same->visitid == samevisitid || same->visible)
+      qh_infiniteloop (samecycle);
+    same->visitid= samevisitid;
+  }
+  newfacet->visitid= ++qh visit_id;
+  trace4((qh ferr, "qh_mergecycle_neighbors: delete shared neighbors from newfacet\n"));  
+  FOREACHneighbor_(newfacet) {
+    if (neighbor->visitid == samevisitid) {
+      SETref_(neighbor)= NULL;  /* samecycle neighbors deleted */
+      delneighbors++;
+    }else
+      neighbor->visitid= qh visit_id;
+  }
+  qh_setcompact (newfacet->neighbors);
+
+  trace4((qh ferr, "qh_mergecycle_neighbors: update neighbors\n"));  
+  FORALLsame_cycle_(samecycle) {
+    FOREACHneighbor_(same) {
+      if (neighbor->visitid == samevisitid)
+	continue;
+      if (neighbor->simplicial) {
+	if (neighbor->visitid != qh visit_id) {
+	  qh_setappend (&newfacet->neighbors, neighbor);
+	  qh_setreplace (neighbor->neighbors, same, newfacet);
+	  newneighbors++;
+	  neighbor->visitid= qh visit_id;
+	  FOREACHridge_(neighbor->ridges) { /* update ridge in case of qh_makeridges */
+	    if (ridge->top == same) {
+	      ridge->top= newfacet;
+	      break;
+	    }else if (ridge->bottom == same) {
+	      ridge->bottom= newfacet;
+	      break;
+	    }
+	  }
+	}else {
+	  qh_makeridges (neighbor);
+	  qh_setdel (neighbor->neighbors, same);
+	  /* same can't be horizon facet for neighbor */
+	}
+      }else { /* non-simplicial neighbor */
+        qh_setdel (neighbor->neighbors, same);
+        if (neighbor->visitid != qh visit_id) {
+          qh_setappend (&neighbor->neighbors, newfacet);
+          qh_setappend (&newfacet->neighbors, neighbor);
+          neighbor->visitid= qh visit_id;
+          newneighbors++;
+        } 
+      }
+    }
+  }
+  trace2((qh ferr, "qh_mergecycle_neighbors: deleted %d neighbors and added %d\n", 
+             delneighbors, newneighbors));
+} /* mergecycle_neighbors */
+
+/*---------------------------------
+  
+  qh_mergecycle_ridges( samecycle, newfacet )
+    add ridges/neighbors for facets in samecycle to newfacet
+    all new/old neighbors of newfacet marked with qh.visit_id
+    facets in samecycle marked with qh.visit_id-1
+    newfacet marked with qh.visit_id
+
+  returns:
+    newfacet has merged ridges
+  
+  notes:
+    ridge already updated for simplicial neighbors of samecycle with a ridge
+
+  see:
+    qh_mergeridges()
+    qh_makeridges()
+
+  design:
+    remove ridges between newfacet and samecycle
+    for each facet in samecycle
+      for each ridge in facet
+        update facet pointers in ridge
+        skip ridges processed in qh_mergecycle_neighors
+        free ridges between newfacet and samecycle
+        free ridges between facets of samecycle (on 2nd visit)
+        append remaining ridges to newfacet
+      if simpilicial facet
+        for each neighbor of facet
+          if simplicial facet
+          and not samecycle facet or newfacet
+            make ridge between neighbor and newfacet
+*/
+void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet) {
+  facetT *same, *neighbor= NULL;
+  int numold=0, numnew=0;
+  int neighbor_i, neighbor_n;
+  unsigned int samevisitid;
+  ridgeT *ridge, **ridgep;
+  boolT toporient;
+  void **freelistp; /* used !qh_NOmem */
+
+  trace4((qh ferr, "qh_mergecycle_ridges: delete shared ridges from newfacet\n"));  
+  samevisitid= qh visit_id -1;
+  FOREACHridge_(newfacet->ridges) {
+    neighbor= otherfacet_(ridge, newfacet);
+    if (neighbor->visitid == samevisitid)
+      SETref_(ridge)= NULL; /* ridge free'd below */  
+  }
+  qh_setcompact (newfacet->ridges);
+  
+  trace4((qh ferr, "qh_mergecycle_ridges: add ridges to newfacet\n"));  
+  FORALLsame_cycle_(samecycle) {
+    FOREACHridge_(same->ridges) {
+      if (ridge->top == same) {
+        ridge->top= newfacet;
+	neighbor= ridge->bottom;
+      }else if (ridge->bottom == same) {
+	ridge->bottom= newfacet;
+	neighbor= ridge->top;
+      }else if (ridge->top == newfacet || ridge->bottom == newfacet) {
+        qh_setappend (&newfacet->ridges, ridge);
+        numold++;  /* already set by qh_mergecycle_neighbors */
+	continue;  
+      }else {
+	fprintf (qh ferr, "qhull internal error (qh_mergecycle_ridges): bad ridge r%d\n", ridge->id);
+	qh_errexit (qh_ERRqhull, NULL, ridge);
+      }
+      if (neighbor == newfacet) {
+        qh_setfree(&(ridge->vertices)); 
+        qh_memfree_(ridge, sizeof(ridgeT), freelistp);
+        numold++;
+      }else if (neighbor->visitid == samevisitid) {
+	qh_setdel (neighbor->ridges, ridge);
+	qh_setfree(&(ridge->vertices)); 
+	qh_memfree_(ridge, sizeof(ridgeT), freelistp);
+	numold++;
+      }else {
+        qh_setappend (&newfacet->ridges, ridge);
+        numold++;
+      }
+    }
+    if (same->ridges)
+      qh_settruncate (same->ridges, 0);
+    if (!same->simplicial)
+      continue;
+    FOREACHneighbor_i_(same) {       /* note: !newfact->simplicial */
+      if (neighbor->visitid != samevisitid && neighbor->simplicial) {
+        ridge= qh_newridge();
+        ridge->vertices= qh_setnew_delnthsorted (same->vertices, qh hull_dim,
+  					                  neighbor_i, 0);
+        toporient= same->toporient ^ (neighbor_i & 0x1);
+        if (toporient) {
+          ridge->top= newfacet;
+          ridge->bottom= neighbor;
+        }else {
+          ridge->top= neighbor;
+          ridge->bottom= newfacet;
+        }
+        qh_setappend(&(newfacet->ridges), ridge);
+        qh_setappend(&(neighbor->ridges), ridge);
+        numnew++;
+      }
+    }
+  }
+
+  trace2((qh ferr, "qh_mergecycle_ridges: found %d old ridges and %d new ones\n", 
+             numold, numnew));
+} /* mergecycle_ridges */
+
+/*---------------------------------
+  
+  qh_mergecycle_vneighbors( samecycle, newfacet )
+    create vertex neighbors for newfacet from vertices of facets in samecycle
+    samecycle marked with visitid == qh.visit_id - 1
+
+  returns:
+    newfacet vertices with updated neighbors
+    marks newfacet with qh.visit_id-1
+    deletes vertices that are merged away
+    sets delridge on all vertices (faster here than in mergecycle_ridges)
+
+  see:
+    qh_mergevertex_neighbors()
+
+  design:
+    for each vertex of samecycle facet
+      set vertex->delridge
+      delete samecycle facets from vertex neighbors
+      append newfacet to vertex neighbors
+      if vertex only in newfacet
+        delete it from newfacet
+        add it to qh.del_vertices for later deletion
+*/
+void qh_mergecycle_vneighbors (facetT *samecycle, facetT *newfacet) {
+  facetT *neighbor, **neighborp;
+  unsigned int mergeid;
+  vertexT *vertex, **vertexp, *apex;
+  setT *vertices;
+  
+  trace4((qh ferr, "qh_mergecycle_vneighbors: update vertex neighbors for newfacet\n"));  
+  mergeid= qh visit_id - 1;
+  newfacet->visitid= mergeid;
+  vertices= qh_basevertices (samecycle); /* temp */
+  apex= SETfirstt_(samecycle->vertices, vertexT);
+  qh_setappend (&vertices, apex);
+  FOREACHvertex_(vertices) {
+    vertex->delridge= True;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->visitid == mergeid)
+        SETref_(neighbor)= NULL;
+    }
+    qh_setcompact (vertex->neighbors);
+    qh_setappend (&vertex->neighbors, newfacet);
+    if (!SETsecond_(vertex->neighbors)) {
+      zinc_(Zcyclevertex);
+      trace2((qh ferr, "qh_mergecycle_vneighbors: deleted v%d when merging cycle f%d into f%d\n",
+        vertex->id, samecycle->id, newfacet->id));
+      qh_setdelsorted (newfacet->vertices, vertex);
+      vertex->deleted= True;
+      qh_setappend (&qh del_vertices, vertex);
+    }
+  }
+  qh_settempfree (&vertices);
+  trace3((qh ferr, "qh_mergecycle_vneighbors: merged vertices from cycle f%d into f%d\n", 
+             samecycle->id, newfacet->id));
+} /* mergecycle_vneighbors */
+
+/*---------------------------------
+  
+  qh_mergefacet( facet1, facet2, mindist, maxdist, mergeapex )
+    merges facet1 into facet2
+    mergeapex==qh_MERGEapex if merging new facet into coplanar horizon
+    
+  returns:
+    qh.max_outside and qh.min_vertex updated
+    initializes vertex neighbors on first merge
+
+  returns:
+    facet2 contains facet1's vertices, neighbors, and ridges
+      facet2 moved to end of qh.facet_list
+      makes facet2 a newfacet
+      sets facet2->newmerge set
+      clears facet2->center (unless merging into a large facet)
+      clears facet2->tested and ridge->tested for facet1
+
+    facet1 prepended to visible_list for later deletion and partitioning
+      facet1->f.replace == facet2
+
+    adds neighboring facets to facet_mergeset if redundant or degenerate
+
+  notes: 
+    mindist/maxdist may be NULL
+    traces merge if fmax_(maxdist,-mindist) > TRACEdist
+
+  see: 
+    qh_mergecycle()
+
+  design:
+    trace merge and check for degenerate simplex
+    make ridges for both facets
+    update qh.max_outside, qh.max_vertex, qh.min_vertex
+    update facet2->maxoutside and keepcentrum
+    update facet2->nummerge
+    update tested flags for facet2
+    if facet1 is simplicial
+      merge facet1 into facet2
+    else
+      merge facet1's neighbors into facet2
+      merge facet1's ridges into facet2
+      merge facet1's vertices into facet2
+      merge facet1's vertex neighbors into facet2
+      add facet2's vertices to qh.new_vertexlist
+      unless qh_MERGEapex
+        test facet2 for degenerate or redundant neighbors
+      move facet1 to qh.visible_list for later deletion
+      move facet2 to end of qh.newfacet_list
+*/
+void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex) {
+  boolT traceonce= False;
+  vertexT *vertex, **vertexp;
+  int tracerestore=0, nummerge;
+
+  if (facet1->tricoplanar || facet2->tricoplanar) {
+    if (!qh TRInormals) {
+      fprintf (qh ferr, "qh_mergefacet: does not work for tricoplanar facets.  Use option 'Q11'\n");
+      qh_errexit2 (qh_ERRqhull, facet1, facet2);
+    }
+    if (facet2->tricoplanar) {
+      facet2->tricoplanar= False;
+      facet2->keepcentrum= False;
+    }
+  }
+  zzinc_(Ztotmerge);
+  if (qh REPORTfreq2 && qh POSTmerging) {
+    if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
+      qh_tracemerging();
+  }
+#ifndef qh_NOtrace
+  if (qh build_cnt >= qh RERUN) {
+    if (mindist && (-*mindist > qh TRACEdist || *maxdist > qh TRACEdist)) {
+      tracerestore= 0;
+      qh IStracing= qh TRACElevel;
+      traceonce= True;
+      fprintf (qh ferr, "qh_mergefacet: ========= trace wide merge #%d (%2.2g) for f%d into f%d, last point was p%d\n", zzval_(Ztotmerge),
+	     fmax_(-*mindist, *maxdist), facet1->id, facet2->id, qh furthest_id);
+    }else if (facet1 == qh tracefacet || facet2 == qh tracefacet) {
+      tracerestore= qh IStracing;
+      qh IStracing= 4;
+      traceonce= True;
+      fprintf (qh ferr, "qh_mergefacet: ========= trace merge #%d involving f%d, furthest is p%d\n",
+		 zzval_(Ztotmerge), qh tracefacet_id,  qh furthest_id);
+    }
+  }
+  if (qh IStracing >= 2) {
+    realT mergemin= -2;
+    realT mergemax= -2;
+    
+    if (mindist) {
+      mergemin= *mindist;
+      mergemax= *maxdist;
+    }
+    fprintf (qh ferr, "qh_mergefacet: #%d merge f%d into f%d, mindist= %2.2g, maxdist= %2.2g\n", 
+    zzval_(Ztotmerge), facet1->id, facet2->id, mergemin, mergemax);
+  }
+#endif /* !qh_NOtrace */
+  if (facet1 == facet2 || facet1->visible || facet2->visible) {
+    fprintf (qh ferr, "qhull internal error (qh_mergefacet): either f%d and f%d are the same or one is a visible facet\n",
+	     facet1->id, facet2->id);
+    qh_errexit2 (qh_ERRqhull, facet1, facet2);
+  }
+  if (qh num_facets - qh num_visible <= qh hull_dim + 1) {
+    fprintf(qh ferr, "\n\
+qhull precision error: Only %d facets remain.  Can not merge another\n\
+pair.  The input is too degenerate or the convexity constraints are\n\
+too strong.\n", qh hull_dim+1);
+    if (qh hull_dim >= 5 && !qh MERGEexact)
+      fprintf(qh ferr, "Option 'Qx' may avoid this problem.\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (!qh VERTEXneighbors)
+    qh_vertexneighbors();
+  qh_makeridges(facet1);
+  qh_makeridges(facet2);
+  if (qh IStracing >=4)
+    qh_errprint ("MERGING", facet1, facet2, NULL, NULL);
+  if (mindist) {
+    maximize_(qh max_outside, *maxdist);
+    maximize_(qh max_vertex, *maxdist);
+#if qh_MAXoutside
+    maximize_(facet2->maxoutside, *maxdist);
+#endif
+    minimize_(qh min_vertex, *mindist);
+    if (!facet2->keepcentrum 
+    && (*maxdist > qh WIDEfacet || *mindist < -qh WIDEfacet)) {
+      facet2->keepcentrum= True;
+      zinc_(Zwidefacet);
+    }
+  }
+  nummerge= facet1->nummerge + facet2->nummerge + 1;
+  if (nummerge >= qh_MAXnummerge) 
+    facet2->nummerge= qh_MAXnummerge;
+  else
+    facet2->nummerge= nummerge;
+  facet2->newmerge= True;
+  facet2->dupridge= False;
+  qh_updatetested  (facet1, facet2);
+  if (qh hull_dim > 2 && qh_setsize (facet1->vertices) == qh hull_dim)
+    qh_mergesimplex (facet1, facet2, mergeapex);
+  else {
+    qh vertex_visit++;
+    FOREACHvertex_(facet2->vertices)
+      vertex->visitid= qh vertex_visit;
+    if (qh hull_dim == 2) 
+      qh_mergefacet2d(facet1, facet2);
+    else {
+      qh_mergeneighbors(facet1, facet2);
+      qh_mergevertices(facet1->vertices, &facet2->vertices);
+    }
+    qh_mergeridges(facet1, facet2);
+    qh_mergevertex_neighbors(facet1, facet2);
+    if (!facet2->newfacet)
+      qh_newvertices (facet2->vertices);
+  }
+  if (!mergeapex)
+    qh_degen_redundant_neighbors (facet2, facet1);
+  if (facet2->coplanar || !facet2->newfacet) {
+    zinc_(Zmergeintohorizon);
+  }else if (!facet1->newfacet && facet2->newfacet) {
+    zinc_(Zmergehorizon);
+  }else {
+    zinc_(Zmergenew);
+  }
+  qh_willdelete (facet1, facet2);
+  qh_removefacet(facet2);  /* append as a newfacet to end of qh facet_list */
+  qh_appendfacet(facet2);
+  facet2->newfacet= True;
+  facet2->tested= False;
+  qh_tracemerge (facet1, facet2);
+  if (traceonce) {
+    fprintf (qh ferr, "qh_mergefacet: end of wide tracing\n");
+    qh IStracing= tracerestore;
+  }
+} /* mergefacet */
+
+
+/*---------------------------------
+  
+  qh_mergefacet2d( facet1, facet2 )
+    in 2d, merges neighbors and vertices of facet1 into facet2
+    
+  returns:
+    build ridges for neighbors if necessary
+    facet2 looks like a simplicial facet except for centrum, ridges
+      neighbors are opposite the corresponding vertex
+      maintains orientation of facet2
+
+  notes:
+    qh_mergefacet() retains non-simplicial structures
+      they are not needed in 2d, but later routines may use them
+    preserves qh.vertex_visit for qh_mergevertex_neighbors()
+  
+  design:
+    get vertices and neighbors
+    determine new vertices and neighbors
+    set new vertices and neighbors and adjust orientation
+    make ridges for new neighbor if needed
+*/
+void qh_mergefacet2d (facetT *facet1, facetT *facet2) {
+  vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB;
+  facetT *neighbor1A, *neighbor1B, *neighbor2A, *neighbor2B, *neighborA, *neighborB;
+
+  vertex1A= SETfirstt_(facet1->vertices, vertexT);
+  vertex1B= SETsecondt_(facet1->vertices, vertexT);
+  vertex2A= SETfirstt_(facet2->vertices, vertexT);
+  vertex2B= SETsecondt_(facet2->vertices, vertexT);
+  neighbor1A= SETfirstt_(facet1->neighbors, facetT);
+  neighbor1B= SETsecondt_(facet1->neighbors, facetT);
+  neighbor2A= SETfirstt_(facet2->neighbors, facetT);
+  neighbor2B= SETsecondt_(facet2->neighbors, facetT);
+  if (vertex1A == vertex2A) {
+    vertexA= vertex1B;
+    vertexB= vertex2B;
+    neighborA= neighbor2A;
+    neighborB= neighbor1A;
+  }else if (vertex1A == vertex2B) {
+    vertexA= vertex1B;
+    vertexB= vertex2A;
+    neighborA= neighbor2B;
+    neighborB= neighbor1A;
+  }else if (vertex1B == vertex2A) {
+    vertexA= vertex1A;
+    vertexB= vertex2B;
+    neighborA= neighbor2A;
+    neighborB= neighbor1B;
+  }else { /* 1B == 2B */
+    vertexA= vertex1A;
+    vertexB= vertex2A;
+    neighborA= neighbor2B;
+    neighborB= neighbor1B;
+  }
+  /* vertexB always from facet2, neighborB always from facet1 */
+  if (vertexA->id > vertexB->id) {
+    SETfirst_(facet2->vertices)= vertexA;
+    SETsecond_(facet2->vertices)= vertexB;
+    if (vertexB == vertex2A)
+      facet2->toporient= !facet2->toporient;
+    SETfirst_(facet2->neighbors)= neighborA;
+    SETsecond_(facet2->neighbors)= neighborB;
+  }else {
+    SETfirst_(facet2->vertices)= vertexB;
+    SETsecond_(facet2->vertices)= vertexA;
+    if (vertexB == vertex2B)
+      facet2->toporient= !facet2->toporient;
+    SETfirst_(facet2->neighbors)= neighborB;
+    SETsecond_(facet2->neighbors)= neighborA;
+  }
+  qh_makeridges (neighborB);
+  qh_setreplace(neighborB->neighbors, facet1, facet2);
+  trace4((qh ferr, "qh_mergefacet2d: merged v%d and neighbor f%d of f%d into f%d\n",
+       vertexA->id, neighborB->id, facet1->id, facet2->id));
+} /* mergefacet2d */
+
+
+/*---------------------------------
+  
+  qh_mergeneighbors( facet1, facet2 )
+    merges the neighbors of facet1 into facet2
+
+  see: 
+    qh_mergecycle_neighbors()
+
+  design:
+    for each neighbor of facet1
+      if neighbor is also a neighbor of facet2
+        if neighbor is simpilicial
+          make ridges for later deletion as a degenerate facet
+        update its neighbor set
+      else
+        move the neighbor relation to facet2
+    remove the neighbor relation for facet1 and facet2
+*/
+void qh_mergeneighbors(facetT *facet1, facetT *facet2) {
+  facetT *neighbor, **neighborp;
+
+  trace4((qh ferr, "qh_mergeneighbors: merge neighbors of f%d and f%d\n",
+	  facet1->id, facet2->id));
+  qh visit_id++;
+  FOREACHneighbor_(facet2) {
+    neighbor->visitid= qh visit_id;
+  }
+  FOREACHneighbor_(facet1) {
+    if (neighbor->visitid == qh visit_id) {
+      if (neighbor->simplicial)    /* is degen, needs ridges */
+	qh_makeridges (neighbor);
+      if (SETfirstt_(neighbor->neighbors, facetT) != facet1) /*keep newfacet->horizon*/
+	qh_setdel (neighbor->neighbors, facet1);
+      else {
+        qh_setdel(neighbor->neighbors, facet2);
+        qh_setreplace(neighbor->neighbors, facet1, facet2);
+      }
+    }else if (neighbor != facet2) {
+      qh_setappend(&(facet2->neighbors), neighbor);
+      qh_setreplace(neighbor->neighbors, facet1, facet2);
+    }
+  }
+  qh_setdel(facet1->neighbors, facet2);  /* here for makeridges */
+  qh_setdel(facet2->neighbors, facet1);
+} /* mergeneighbors */
+
+
+/*---------------------------------
+  
+  qh_mergeridges( facet1, facet2 )
+    merges the ridge set of facet1 into facet2
+
+  returns:
+    may delete all ridges for a vertex
+    sets vertex->delridge on deleted ridges
+
+  see:
+    qh_mergecycle_ridges()
+
+  design:
+    delete ridges between facet1 and facet2
+      mark (delridge) vertices on these ridges for later testing   
+    for each remaining ridge
+      rename facet1 to facet2  
+*/
+void qh_mergeridges(facetT *facet1, facetT *facet2) {
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, **vertexp;
+
+  trace4((qh ferr, "qh_mergeridges: merge ridges of f%d and f%d\n",
+	  facet1->id, facet2->id));
+  FOREACHridge_(facet2->ridges) {
+    if ((ridge->top == facet1) || (ridge->bottom == facet1)) {
+      FOREACHvertex_(ridge->vertices)
+        vertex->delridge= True;
+      qh_delridge(ridge);  /* expensive in high-d, could rebuild */
+      ridgep--; /*repeat*/
+    }
+  }
+  FOREACHridge_(facet1->ridges) {
+    if (ridge->top == facet1)
+      ridge->top= facet2;
+    else
+      ridge->bottom= facet2;
+    qh_setappend(&(facet2->ridges), ridge);
+  }
+} /* mergeridges */
+
+
+/*---------------------------------
+  
+  qh_mergesimplex( facet1, facet2, mergeapex )
+    merge simplicial facet1 into facet2
+    mergeapex==qh_MERGEapex if merging samecycle into horizon facet
+      vertex id is latest (most recently created)
+    facet1 may be contained in facet2
+    ridges exist for both facets
+
+  returns:
+    facet2 with updated vertices, ridges, neighbors
+    updated neighbors for facet1's vertices
+    facet1 not deleted
+    sets vertex->delridge on deleted ridges
+  
+  notes:
+    special case code since this is the most common merge
+    called from qh_mergefacet()
+
+  design:
+    if qh_MERGEapex
+      add vertices of facet2 to qh.new_vertexlist if necessary
+      add apex to facet2
+    else
+      for each ridge between facet1 and facet2
+        set vertex->delridge
+      determine the apex for facet1 (i.e., vertex to be merged)
+      unless apex already in facet2
+        insert apex into vertices for facet2
+      add vertices of facet2 to qh.new_vertexlist if necessary
+      add apex to qh.new_vertexlist if necessary
+      for each vertex of facet1
+        if apex
+          rename facet1 to facet2 in its vertex neighbors
+        else
+          delete facet1 from vertex neighors
+          if only in facet2
+            add vertex to qh.del_vertices for later deletion
+      for each ridge of facet1
+        delete ridges between facet1 and facet2
+        append other ridges to facet2 after renaming facet to facet2
+*/
+void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex) {
+  vertexT *vertex, **vertexp, *apex;
+  ridgeT *ridge, **ridgep;
+  boolT issubset= False;
+  int vertex_i= -1, vertex_n;
+  facetT *neighbor, **neighborp, *otherfacet;
+
+  if (mergeapex) {
+    if (!facet2->newfacet)
+      qh_newvertices (facet2->vertices);  /* apex is new */
+    apex= SETfirstt_(facet1->vertices, vertexT);
+    if (SETfirstt_(facet2->vertices, vertexT) != apex) 
+      qh_setaddnth (&facet2->vertices, 0, apex);  /* apex has last id */
+    else
+      issubset= True;
+  }else {
+    zinc_(Zmergesimplex);
+    FOREACHvertex_(facet1->vertices)
+      vertex->seen= False;
+    FOREACHridge_(facet1->ridges) {
+      if (otherfacet_(ridge, facet1) == facet2) {
+	FOREACHvertex_(ridge->vertices) {
+	  vertex->seen= True;
+	  vertex->delridge= True;
+	}
+	break;
+      }
+    }
+    FOREACHvertex_(facet1->vertices) {
+      if (!vertex->seen)
+	break;  /* must occur */
+    }
+    apex= vertex;
+    trace4((qh ferr, "qh_mergesimplex: merge apex v%d of f%d into facet f%d\n",
+	  apex->id, facet1->id, facet2->id));
+    FOREACHvertex_i_(facet2->vertices) {
+      if (vertex->id < apex->id) {
+	break;
+      }else if (vertex->id == apex->id) {
+	issubset= True;
+	break;
+      }
+    }
+    if (!issubset)
+      qh_setaddnth (&facet2->vertices, vertex_i, apex);
+    if (!facet2->newfacet)
+      qh_newvertices (facet2->vertices);
+    else if (!apex->newlist) {
+      qh_removevertex (apex);
+      qh_appendvertex (apex);
+    }
+  }
+  trace4((qh ferr, "qh_mergesimplex: update vertex neighbors of f%d\n",
+	  facet1->id));
+  FOREACHvertex_(facet1->vertices) {
+    if (vertex == apex && !issubset)
+      qh_setreplace (vertex->neighbors, facet1, facet2);
+    else {
+      qh_setdel (vertex->neighbors, facet1);
+      if (!SETsecond_(vertex->neighbors))
+	qh_mergevertex_del (vertex, facet1, facet2);
+    }
+  }
+  trace4((qh ferr, "qh_mergesimplex: merge ridges and neighbors of f%d into f%d\n",
+	  facet1->id, facet2->id));
+  qh visit_id++;
+  FOREACHneighbor_(facet2)
+    neighbor->visitid= qh visit_id;
+  FOREACHridge_(facet1->ridges) {
+    otherfacet= otherfacet_(ridge, facet1);
+    if (otherfacet == facet2) {
+      qh_setdel (facet2->ridges, ridge);
+      qh_setfree(&(ridge->vertices)); 
+      qh_memfree (ridge, sizeof(ridgeT));
+      qh_setdel (facet2->neighbors, facet1);
+    }else {
+      qh_setappend (&facet2->ridges, ridge);
+      if (otherfacet->visitid != qh visit_id) {
+	qh_setappend (&facet2->neighbors, otherfacet);
+	qh_setreplace (otherfacet->neighbors, facet1, facet2);
+	otherfacet->visitid= qh visit_id;
+      }else {
+	if (otherfacet->simplicial)    /* is degen, needs ridges */
+	  qh_makeridges (otherfacet);
+	if (SETfirstt_(otherfacet->neighbors, facetT) != facet1)
+	  qh_setdel (otherfacet->neighbors, facet1);
+	else {   /*keep newfacet->neighbors->horizon*/
+	  qh_setdel(otherfacet->neighbors, facet2);
+	  qh_setreplace(otherfacet->neighbors, facet1, facet2);
+	}
+      }
+      if (ridge->top == facet1) /* wait until after qh_makeridges */
+	ridge->top= facet2;
+      else 
+	ridge->bottom= facet2;
+    }
+  }
+  SETfirst_(facet1->ridges)= NULL; /* it will be deleted */
+  trace3((qh ferr, "qh_mergesimplex: merged simplex f%d apex v%d into facet f%d\n",
+	  facet1->id, getid_(apex), facet2->id));
+} /* mergesimplex */
+
+/*---------------------------------
+  
+  qh_mergevertex_del( vertex, facet1, facet2 )
+    delete a vertex because of merging facet1 into facet2
+
+  returns:
+    deletes vertex from facet2
+    adds vertex to qh.del_vertices for later deletion 
+*/
+void qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2) {
+
+  zinc_(Zmergevertex);
+  trace2((qh ferr, "qh_mergevertex_del: deleted v%d when merging f%d into f%d\n",
+          vertex->id, facet1->id, facet2->id));
+  qh_setdelsorted (facet2->vertices, vertex);
+  vertex->deleted= True;
+  qh_setappend (&qh del_vertices, vertex);
+} /* mergevertex_del */
+
+/*---------------------------------
+  
+  qh_mergevertex_neighbors( facet1, facet2 )
+    merge the vertex neighbors of facet1 to facet2
+
+  returns:
+    if vertex is current qh.vertex_visit
+      deletes facet1 from vertex->neighbors
+    else
+      renames facet1 to facet2 in vertex->neighbors 
+    deletes vertices if only one neighbor
+  
+  notes:
+    assumes vertex neighbor sets are good
+*/
+void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2) {
+  vertexT *vertex, **vertexp;
+
+  trace4((qh ferr, "qh_mergevertex_neighbors: merge vertex neighbors of f%d and f%d\n",
+	  facet1->id, facet2->id));
+  if (qh tracevertex) {
+    fprintf (qh ferr, "qh_mergevertex_neighbors: of f%d and f%d at furthest p%d f0= %p\n",
+	     facet1->id, facet2->id, qh furthest_id, qh tracevertex->neighbors->e[0].p);
+    qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
+  }
+  FOREACHvertex_(facet1->vertices) {
+    if (vertex->visitid != qh vertex_visit) 
+      qh_setreplace(vertex->neighbors, facet1, facet2);
+    else {
+      qh_setdel(vertex->neighbors, facet1);
+      if (!SETsecond_(vertex->neighbors))
+	qh_mergevertex_del (vertex, facet1, facet2);
+    }
+  }
+  if (qh tracevertex) 
+    qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
+} /* mergevertex_neighbors */
+
+
+/*---------------------------------
+  
+  qh_mergevertices( vertices1, vertices2 )
+    merges the vertex set of facet1 into facet2
+
+  returns:
+    replaces vertices2 with merged set
+    preserves vertex_visit for qh_mergevertex_neighbors
+    updates qh.newvertex_list
+
+  design:
+    create a merged set of both vertices (in inverse id order)
+*/
+void qh_mergevertices(setT *vertices1, setT **vertices2) {
+  int newsize= qh_setsize(vertices1)+qh_setsize(*vertices2) - qh hull_dim + 1;
+  setT *mergedvertices;
+  vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT);
+
+  mergedvertices= qh_settemp (newsize);
+  FOREACHvertex_(vertices1) {
+    if (!*vertex2 || vertex->id > (*vertex2)->id)
+      qh_setappend (&mergedvertices, vertex);
+    else {
+      while (*vertex2 && (*vertex2)->id > vertex->id)
+	qh_setappend (&mergedvertices, *vertex2++);
+      if (!*vertex2 || (*vertex2)->id < vertex->id)
+	qh_setappend (&mergedvertices, vertex);
+      else
+	qh_setappend (&mergedvertices, *vertex2++);
+    }
+  }
+  while (*vertex2)
+    qh_setappend (&mergedvertices, *vertex2++);
+  if (newsize < qh_setsize (mergedvertices)) {
+    fprintf (qh ferr, "qhull internal error (qh_mergevertices): facets did not share a ridge\n");
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  qh_setfree(vertices2);
+  *vertices2= mergedvertices;
+  qh_settemppop ();
+} /* mergevertices */
+
+
+/*---------------------------------
+  
+  qh_neighbor_intersections( vertex )
+    return intersection of all vertices in vertex->neighbors except for vertex
+
+  returns:
+    returns temporary set of vertices
+    does not include vertex
+    NULL if a neighbor is simplicial
+    NULL if empty set
+    
+  notes:
+    used for renaming vertices
+
+  design:
+    initialize the intersection set with vertices of the first two neighbors
+    delete vertex from the intersection
+    for each remaining neighbor
+      intersect its vertex set with the intersection set
+      return NULL if empty
+    return the intersection set  
+*/
+setT *qh_neighbor_intersections (vertexT *vertex) {
+  facetT *neighbor, **neighborp, *neighborA, *neighborB;
+  setT *intersect;
+  int neighbor_i, neighbor_n;
+
+  FOREACHneighbor_(vertex) {
+    if (neighbor->simplicial)
+      return NULL;
+  }
+  neighborA= SETfirstt_(vertex->neighbors, facetT);
+  neighborB= SETsecondt_(vertex->neighbors, facetT);
+  zinc_(Zintersectnum);
+  if (!neighborA)
+    return NULL;
+  if (!neighborB)
+    intersect= qh_setcopy (neighborA->vertices, 0);
+  else
+    intersect= qh_vertexintersect_new (neighborA->vertices, neighborB->vertices);
+  qh_settemppush (intersect);
+  qh_setdelsorted (intersect, vertex);
+  FOREACHneighbor_i_(vertex) {
+    if (neighbor_i >= 2) {
+      zinc_(Zintersectnum);
+      qh_vertexintersect (&intersect, neighbor->vertices);
+      if (!SETfirst_(intersect)) {
+        zinc_(Zintersectfail);
+        qh_settempfree (&intersect);
+        return NULL;
+      }
+    }
+  }
+  trace3((qh ferr, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n", 
+          qh_setsize (intersect), vertex->id));
+  return intersect;
+} /* neighbor_intersections */
+
+/*---------------------------------
+  
+  qh_newvertices( vertices )
+    add vertices to end of qh.vertex_list (marks as new vertices)
+
+  returns:
+    vertices on qh.newvertex_list
+    vertex->newlist set
+*/
+void qh_newvertices (setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (!vertex->newlist) {
+      qh_removevertex (vertex);
+      qh_appendvertex (vertex);
+    }
+  }
+} /* newvertices */
+
+/*---------------------------------
+  
+  qh_reducevertices()
+    reduce extra vertices, shared vertices, and redundant vertices
+    facet->newmerge is set if merged since last call
+    if !qh.MERGEvertices, only removes extra vertices
+
+  returns:
+    True if also merged degen_redundant facets
+    vertices are renamed if possible
+    clears facet->newmerge and vertex->delridge
+
+  notes:
+    ignored if 2-d
+
+  design:
+    merge any degenerate or redundant facets
+    for each newly merged facet
+      remove extra vertices
+    if qh.MERGEvertices
+      for each newly merged facet
+        for each vertex
+          if vertex was on a deleted ridge
+            rename vertex if it is shared
+      remove delridge flag from new vertices
+*/
+boolT qh_reducevertices (void) {
+  int numshare=0, numrename= 0;
+  boolT degenredun= False;
+  facetT *newfacet;
+  vertexT *vertex, **vertexp;
+
+  if (qh hull_dim == 2) 
+    return False;
+  if (qh_merge_degenredundant())
+    degenredun= True;
+ LABELrestart:
+  FORALLnew_facets {
+    if (newfacet->newmerge) { 
+      if (!qh MERGEvertices)
+        newfacet->newmerge= False;
+      qh_remove_extravertices (newfacet);
+    }
+  }
+  if (!qh MERGEvertices)
+    return False;
+  FORALLnew_facets {
+    if (newfacet->newmerge) {
+      newfacet->newmerge= False;
+      FOREACHvertex_(newfacet->vertices) {
+	if (vertex->delridge) {
+	  if (qh_rename_sharedvertex (vertex, newfacet)) {
+	    numshare++;
+	    vertexp--; /* repeat since deleted vertex */
+	  }
+        }
+      }
+    }
+  }
+  FORALLvertex_(qh newvertex_list) {
+    if (vertex->delridge && !vertex->deleted) {
+      vertex->delridge= False;
+      if (qh hull_dim >= 4 && qh_redundant_vertex (vertex)) {
+	numrename++;
+	if (qh_merge_degenredundant()) {
+	  degenredun= True;
+	  goto LABELrestart;
+	}
+      }
+    }
+  }
+  trace1((qh ferr, "qh_reducevertices: renamed %d shared vertices and %d redundant vertices. Degen? %d\n",
+	  numshare, numrename, degenredun));
+  return degenredun;
+} /* reducevertices */
+      
+/*---------------------------------
+  
+  qh_redundant_vertex( vertex )
+    detect and rename a redundant vertex
+    vertices have full vertex->neighbors 
+
+  returns:
+    returns true if find a redundant vertex
+      deletes vertex (vertex->deleted)
+  
+  notes:
+    only needed if vertex->delridge and hull_dim >= 4
+    may add degenerate facets to qh.facet_mergeset
+    doesn't change vertex->neighbors or create redundant facets
+
+  design:
+    intersect vertices of all facet neighbors of vertex
+    determine ridges for these vertices
+    if find a new vertex for vertex amoung these ridges and vertices
+      rename vertex to the new vertex
+*/
+vertexT *qh_redundant_vertex (vertexT *vertex) {
+  vertexT *newvertex= NULL;
+  setT *vertices, *ridges;
+
+  trace3((qh ferr, "qh_redundant_vertex: check if v%d can be renamed\n", vertex->id));  
+  if ((vertices= qh_neighbor_intersections (vertex))) {
+    ridges= qh_vertexridges (vertex);
+    if ((newvertex= qh_find_newvertex (vertex, vertices, ridges)))
+      qh_renamevertex (vertex, newvertex, ridges, NULL, NULL);
+    qh_settempfree (&ridges);
+    qh_settempfree (&vertices);
+  }
+  return newvertex;
+} /* redundant_vertex */
+
+/*---------------------------------
+  
+  qh_remove_extravertices( facet )
+    remove extra vertices from non-simplicial facets
+
+  returns:
+    returns True if it finds them
+
+  design:
+    for each vertex in facet
+      if vertex not in a ridge (i.e., no longer used)
+        delete vertex from facet
+        delete facet from vertice's neighbors
+        unless vertex in another facet
+          add vertex to qh.del_vertices for later deletion
+*/
+boolT qh_remove_extravertices (facetT *facet) {
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, **vertexp;
+  boolT foundrem= False;
+
+  trace4((qh ferr, "qh_remove_extravertices: test f%d for extra vertices\n",
+	  facet->id));
+  FOREACHvertex_(facet->vertices)
+    vertex->seen= False;
+  FOREACHridge_(facet->ridges) { 
+    FOREACHvertex_(ridge->vertices)
+      vertex->seen= True;
+  }
+  FOREACHvertex_(facet->vertices) {
+    if (!vertex->seen) {
+      foundrem= True;
+      zinc_(Zremvertex);
+      qh_setdelsorted (facet->vertices, vertex);
+      qh_setdel (vertex->neighbors, facet);
+      if (!qh_setsize (vertex->neighbors)) {
+	vertex->deleted= True;
+	qh_setappend (&qh del_vertices, vertex);
+	zinc_(Zremvertexdel);
+	trace2((qh ferr, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id));
+      }else
+	trace3((qh ferr, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id));
+      vertexp--; /*repeat*/
+    }
+  }
+  return foundrem;
+} /* remove_extravertices */
+
+/*---------------------------------
+  
+  qh_rename_sharedvertex( vertex, facet )
+    detect and rename if shared vertex in facet
+    vertices have full ->neighbors
+
+  returns:
+    newvertex or NULL
+    the vertex may still exist in other facets (i.e., a neighbor was pinched)
+    does not change facet->neighbors
+    updates vertex->neighbors
+  
+  notes:
+    a shared vertex for a facet is only in ridges to one neighbor
+    this may undo a pinched facet
+ 
+    it does not catch pinches involving multiple facets.  These appear
+      to be difficult to detect, since an exhaustive search is too expensive.
+
+  design:
+    if vertex only has two neighbors
+      determine the ridges that contain the vertex
+      determine the vertices shared by both neighbors
+      if can find a new vertex in this set
+        rename the vertex to the new vertex
+*/
+vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet) {
+  facetT *neighbor, **neighborp, *neighborA= NULL;
+  setT *vertices, *ridges;
+  vertexT *newvertex;
+
+  if (qh_setsize (vertex->neighbors) == 2) {
+    neighborA= SETfirstt_(vertex->neighbors, facetT);
+    if (neighborA == facet)
+      neighborA= SETsecondt_(vertex->neighbors, facetT);
+  }else if (qh hull_dim == 3)
+    return NULL;
+  else {
+    qh visit_id++;
+    FOREACHneighbor_(facet)
+      neighbor->visitid= qh visit_id;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->visitid == qh visit_id) {
+        if (neighborA)
+          return NULL;
+        neighborA= neighbor;
+      }
+    }
+    if (!neighborA) {
+      fprintf (qh ferr, "qhull internal error (qh_rename_sharedvertex): v%d's neighbors not in f%d\n",
+        vertex->id, facet->id);
+      qh_errprint ("ERRONEOUS", facet, NULL, NULL, vertex);
+      qh_errexit (qh_ERRqhull, NULL, NULL);
+    }
+  }
+  /* the vertex is shared by facet and neighborA */
+  ridges= qh_settemp (qh TEMPsize);
+  neighborA->visitid= ++qh visit_id;
+  qh_vertexridges_facet (vertex, facet, &ridges);
+  trace2((qh ferr, "qh_rename_sharedvertex: p%d (v%d) is shared by f%d (%d ridges) and f%d\n",
+    qh_pointid(vertex->point), vertex->id, facet->id, qh_setsize (ridges), neighborA->id));
+  zinc_(Zintersectnum);
+  vertices= qh_vertexintersect_new (facet->vertices, neighborA->vertices);
+  qh_setdel (vertices, vertex);
+  qh_settemppush (vertices);
+  if ((newvertex= qh_find_newvertex (vertex, vertices, ridges))) 
+    qh_renamevertex (vertex, newvertex, ridges, facet, neighborA);
+  qh_settempfree (&vertices);
+  qh_settempfree (&ridges);
+  return newvertex;
+} /* rename_sharedvertex */
+
+/*---------------------------------
+  
+  qh_renameridgevertex( ridge, oldvertex, newvertex )
+    renames oldvertex as newvertex in ridge
+
+  returns:
+  
+  design:
+    delete oldvertex from ridge
+    if newvertex already in ridge
+      copy ridge->noconvex to another ridge if possible
+      delete the ridge
+    else
+      insert newvertex into the ridge
+      adjust the ridge's orientation
+*/
+void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) {
+  int nth= 0, oldnth;
+  facetT *temp;
+  vertexT *vertex, **vertexp;
+
+  oldnth= qh_setindex (ridge->vertices, oldvertex);
+  qh_setdelnthsorted (ridge->vertices, oldnth);
+  FOREACHvertex_(ridge->vertices) {
+    if (vertex == newvertex) {
+      zinc_(Zdelridge);
+      if (ridge->nonconvex) /* only one ridge has nonconvex set */
+	qh_copynonconvex (ridge);
+      qh_delridge (ridge);
+      trace2((qh ferr, "qh_renameridgevertex: ridge r%d deleted.  It contained both v%d and v%d\n",
+        ridge->id, oldvertex->id, newvertex->id));
+      return;
+    }
+    if (vertex->id < newvertex->id)
+      break;
+    nth++;
+  }
+  qh_setaddnth(&ridge->vertices, nth, newvertex);
+  if (abs(oldnth - nth)%2) {
+    trace3((qh ferr, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n", 
+	    ridge->id));
+    temp= ridge->top;
+    ridge->top= ridge->bottom;
+    ridge->bottom= temp;
+  }
+} /* renameridgevertex */
+
+
+/*---------------------------------
+  
+  qh_renamevertex( oldvertex, newvertex, ridges, oldfacet, neighborA )
+    renames oldvertex as newvertex in ridges 
+    gives oldfacet/neighborA if oldvertex is shared between two facets
+
+  returns:
+    oldvertex may still exist afterwards
+    
+
+  notes:
+    can not change neighbors of newvertex (since it's a subset)
+
+  design:
+    for each ridge in ridges
+      rename oldvertex to newvertex and delete degenerate ridges
+    if oldfacet not defined
+      for each neighbor of oldvertex
+        delete oldvertex from neighbor's vertices
+        remove extra vertices from neighbor
+      add oldvertex to qh.del_vertices
+    else if oldvertex only between oldfacet and neighborA
+      delete oldvertex from oldfacet and neighborA
+      add oldvertex to qh.del_vertices
+    else oldvertex is in oldfacet and neighborA and other facets (i.e., pinched)
+      delete oldvertex from oldfacet
+      delete oldfacet from oldvertice's neighbors
+      remove extra vertices (e.g., oldvertex) from neighborA
+*/
+void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  boolT istrace= False;
+
+  if (qh IStracing >= 2 || oldvertex->id == qh tracevertex_id ||
+	newvertex->id == qh tracevertex_id)
+    istrace= True;
+  FOREACHridge_(ridges) 
+    qh_renameridgevertex (ridge, oldvertex, newvertex);
+  if (!oldfacet) {
+    zinc_(Zrenameall);
+    if (istrace)
+      fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in several facets\n",
+               oldvertex->id, newvertex->id);
+    FOREACHneighbor_(oldvertex) {
+      qh_maydropneighbor (neighbor);
+      qh_setdelsorted (neighbor->vertices, oldvertex);
+      if (qh_remove_extravertices (neighbor))
+        neighborp--; /* neighbor may be deleted */
+    }
+    if (!oldvertex->deleted) {
+      oldvertex->deleted= True;
+      qh_setappend (&qh del_vertices, oldvertex);
+    }
+  }else if (qh_setsize (oldvertex->neighbors) == 2) {
+    zinc_(Zrenameshare);
+    if (istrace)
+      fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in oldfacet f%d\n", 
+               oldvertex->id, newvertex->id, oldfacet->id);
+    FOREACHneighbor_(oldvertex)
+      qh_setdelsorted (neighbor->vertices, oldvertex);
+    oldvertex->deleted= True;
+    qh_setappend (&qh del_vertices, oldvertex);
+  }else {
+    zinc_(Zrenamepinch);
+    if (istrace || qh IStracing)
+      fprintf (qh ferr, "qh_renamevertex: renamed pinched v%d to v%d between f%d and f%d\n", 
+               oldvertex->id, newvertex->id, oldfacet->id, neighborA->id);
+    qh_setdelsorted (oldfacet->vertices, oldvertex);
+    qh_setdel (oldvertex->neighbors, oldfacet);
+    qh_remove_extravertices (neighborA);
+  }
+} /* renamevertex */
+
+
+/*---------------------------------
+  
+  qh_test_appendmerge( facet, neighbor )
+    tests facet/neighbor for convexity
+    appends to mergeset if non-convex
+    if pre-merging, 
+      nop if qh.SKIPconvex, or qh.MERGEexact and coplanar
+
+  returns:
+    true if appends facet/neighbor to mergeset
+    sets facet->center as needed
+    does not change facet->seen
+
+  design:
+    if qh.cos_max is defined
+      if the angle between facet normals is too shallow
+        append an angle-coplanar merge to qh.mergeset
+        return True
+    make facet's centrum if needed
+    if facet's centrum is above the neighbor
+      set isconcave
+    else
+      if facet's centrum is not below the neighbor
+        set iscoplanar
+      make neighbor's centrum if needed
+      if neighbor's centrum is above the facet
+        set isconcave
+      else if neighbor's centrum is not below the facet
+        set iscoplanar
+   if isconcave or iscoplanar
+     get angle if needed
+     append concave or coplanar merge to qh.mergeset
+*/
+boolT qh_test_appendmerge (facetT *facet, facetT *neighbor) {
+  realT dist, dist2= -REALmax, angle= -REALmax;
+  boolT isconcave= False, iscoplanar= False, okangle= False;
+
+  if (qh SKIPconvex && !qh POSTmerging)
+    return False;
+  if ((!qh MERGEexact || qh POSTmerging) && qh cos_max < REALmax/2) {
+    angle= qh_getangle(facet->normal, neighbor->normal);
+    zinc_(Zangletests);
+    if (angle > qh cos_max) {
+      zinc_(Zcoplanarangle);
+      qh_appendmergeset(facet, neighbor, MRGanglecoplanar, &angle);
+      trace2((qh ferr, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n",
+         angle, facet->id, neighbor->id));
+      return True;
+    }else
+      okangle= True;
+  }
+  if (!facet->center)
+    facet->center= qh_getcentrum (facet);
+  zzinc_(Zcentrumtests);
+  qh_distplane(facet->center, neighbor, &dist);
+  if (dist > qh centrum_radius)
+    isconcave= True;
+  else {
+    if (dist > -qh centrum_radius)
+      iscoplanar= True;
+    if (!neighbor->center)
+      neighbor->center= qh_getcentrum (neighbor);
+    zzinc_(Zcentrumtests);
+    qh_distplane(neighbor->center, facet, &dist2);
+    if (dist2 > qh centrum_radius)
+      isconcave= True;
+    else if (!iscoplanar && dist2 > -qh centrum_radius)
+      iscoplanar= True;
+  }
+  if (!isconcave && (!iscoplanar || (qh MERGEexact && !qh POSTmerging)))
+    return False;
+  if (!okangle && qh ANGLEmerge) {
+    angle= qh_getangle(facet->normal, neighbor->normal);
+    zinc_(Zangletests);
+  }
+  if (isconcave) {
+    zinc_(Zconcaveridge);
+    if (qh ANGLEmerge)
+      angle += qh_ANGLEconcave + 0.5;
+    qh_appendmergeset(facet, neighbor, MRGconcave, &angle);
+    trace0((qh ferr, "qh_test_appendmerge: concave f%d to f%d dist %4.4g and reverse dist %4.4g angle %4.4g during p%d\n",
+	   facet->id, neighbor->id, dist, dist2, angle, qh furthest_id));
+  }else /* iscoplanar */ {
+    zinc_(Zcoplanarcentrum);
+    qh_appendmergeset(facet, neighbor, MRGcoplanar, &angle);
+    trace2((qh ferr, "qh_test_appendmerge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n",
+	      facet->id, neighbor->id, dist, dist2, angle));
+  }
+  return True;
+} /* test_appendmerge */
+
+/*---------------------------------
+  
+  qh_test_vneighbors()
+    test vertex neighbors for convexity
+    tests all facets on qh.newfacet_list
+
+  returns:
+    true if non-convex vneighbors appended to qh.facet_mergeset
+    initializes vertex neighbors if needed
+
+  notes:
+    assumes all facet neighbors have been tested
+    this can be expensive
+    this does not guarantee that a centrum is below all facets
+      but it is unlikely
+    uses qh.visit_id
+
+  design:
+    build vertex neighbors if necessary
+    for all new facets
+      for all vertices
+        for each unvisited facet neighbor of the vertex
+          test new facet and neighbor for convexity
+*/
+boolT qh_test_vneighbors (void /* qh newfacet_list */) {
+  facetT *newfacet, *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  int nummerges= 0;
+
+  trace1((qh ferr, "qh_test_vneighbors: testing vertex neighbors for convexity\n"));
+  if (!qh VERTEXneighbors)
+    qh_vertexneighbors();
+  FORALLnew_facets 
+    newfacet->seen= False;
+  FORALLnew_facets {
+    newfacet->seen= True;
+    newfacet->visitid= qh visit_id++;
+    FOREACHneighbor_(newfacet)
+      newfacet->visitid= qh visit_id;
+    FOREACHvertex_(newfacet->vertices) {
+      FOREACHneighbor_(vertex) {
+      	if (neighbor->seen || neighbor->visitid == qh visit_id)
+      	  continue;
+      	if (qh_test_appendmerge (newfacet, neighbor))
+          nummerges++;
+      }
+    }
+  }
+  zadd_(Ztestvneighbor, nummerges);
+  trace1((qh ferr, "qh_test_vneighbors: found %d non-convex, vertex neighbors\n",
+           nummerges));
+  return (nummerges > 0);    
+} /* test_vneighbors */
+
+/*---------------------------------
+  
+  qh_tracemerge( facet1, facet2 )
+    print trace message after merge
+*/
+void qh_tracemerge (facetT *facet1, facetT *facet2) {
+  boolT waserror= False;
+
+#ifndef qh_NOtrace
+  if (qh IStracing >= 4) 
+    qh_errprint ("MERGED", facet2, NULL, NULL, NULL);
+  if (facet2 == qh tracefacet || (qh tracevertex && qh tracevertex->newlist)) {
+    fprintf (qh ferr, "qh_tracemerge: trace facet and vertex after merge of f%d and f%d, furthest p%d\n", facet1->id, facet2->id, qh furthest_id);
+    if (facet2 != qh tracefacet)
+      qh_errprint ("TRACE", qh tracefacet, 
+        (qh tracevertex && qh tracevertex->neighbors) ? 
+           SETfirstt_(qh tracevertex->neighbors, facetT) : NULL,
+        NULL, qh tracevertex);      
+  }
+  if (qh tracevertex) {
+    if (qh tracevertex->deleted)
+      fprintf (qh ferr, "qh_tracemerge: trace vertex deleted at furthest p%d\n",
+	    qh furthest_id);
+    else
+      qh_checkvertex (qh tracevertex);
+  }
+  if (qh tracefacet) {
+    qh_checkfacet (qh tracefacet, True, &waserror);
+    if (waserror)
+      qh_errexit (qh_ERRqhull, qh tracefacet, NULL);
+  }
+#endif /* !qh_NOtrace */
+  if (qh CHECKfrequently || qh IStracing >= 4) { /* can't check polygon here */
+    qh_checkfacet (facet2, True, &waserror);
+    if (waserror)
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+} /* tracemerge */
+
+/*---------------------------------
+  
+  qh_tracemerging()
+    print trace message during POSTmerging
+
+  returns:
+    updates qh.mergereport
+  
+  notes:
+    called from qh_mergecycle() and qh_mergefacet()
+  
+  see:
+    qh_buildtracing()
+*/
+void qh_tracemerging (void) {
+  realT cpu;
+  int total;
+  time_t timedata;
+  struct tm *tp;
+
+  qh mergereport= zzval_(Ztotmerge);
+  time (&timedata);
+  tp= localtime (&timedata);
+  cpu= qh_CPUclock;
+  cpu /= qh_SECticks;
+  total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+  fprintf (qh ferr, "\n\
+At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets.  The hull\n\
+  contains %d facets and %d vertices.\n",
+      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu,
+      total, qh num_facets - qh num_visible,
+      qh num_vertices-qh_setsize (qh del_vertices));
+} /* tracemerging */
+
+/*---------------------------------
+  
+  qh_updatetested( facet1, facet2 )
+    clear facet2->tested and facet1->ridge->tested for merge
+
+  returns:
+    deletes facet2->center unless it's already large
+      if so, clears facet2->ridge->tested
+
+  design:
+    clear facet2->tested
+    clear ridge->tested for facet1's ridges
+    if facet2 has a centrum
+      if facet2 is large
+        set facet2->keepcentrum 
+      else if facet2 has 3 vertices due to many merges, or not large and post merging
+        clear facet2->keepcentrum
+      unless facet2->keepcentrum
+        clear facet2->center to recompute centrum later
+        clear ridge->tested for facet2's ridges
+*/
+void qh_updatetested (facetT *facet1, facetT *facet2) {
+  ridgeT *ridge, **ridgep;
+  int size;
+  
+  facet2->tested= False;
+  FOREACHridge_(facet1->ridges)
+    ridge->tested= False;
+  if (!facet2->center)
+    return;
+  size= qh_setsize (facet2->vertices);
+  if (!facet2->keepcentrum) {
+    if (size > qh hull_dim + qh_MAXnewcentrum) {
+      facet2->keepcentrum= True;
+      zinc_(Zwidevertices);
+    }
+  }else if (size <= qh hull_dim + qh_MAXnewcentrum) {
+    /* center and keepcentrum was set */
+    if (size == qh hull_dim || qh POSTmerging)
+      facet2->keepcentrum= False; /* if many merges need to recompute centrum */
+  }
+  if (!facet2->keepcentrum) {
+    qh_memfree (facet2->center, qh normal_size);
+    facet2->center= NULL;
+    FOREACHridge_(facet2->ridges)
+      ridge->tested= False;
+  }
+} /* updatetested */
+
+/*---------------------------------
+  
+  qh_vertexridges( vertex )
+    return temporary set of ridges adjacent to a vertex
+    vertex->neighbors defined
+
+  ntoes:
+    uses qh.visit_id
+    does not include implicit ridges for simplicial facets
+
+  design:
+    for each neighbor of vertex
+      add ridges that include the vertex to ridges  
+*/
+setT *qh_vertexridges (vertexT *vertex) {
+  facetT *neighbor, **neighborp;
+  setT *ridges= qh_settemp (qh TEMPsize);
+  int size;
+
+  qh visit_id++;
+  FOREACHneighbor_(vertex)
+    neighbor->visitid= qh visit_id;
+  FOREACHneighbor_(vertex) {
+    if (*neighborp)   /* no new ridges in last neighbor */
+      qh_vertexridges_facet (vertex, neighbor, &ridges);
+  }
+  if (qh PRINTstatistics || qh IStracing) {
+    size= qh_setsize (ridges);
+    zinc_(Zvertexridge);
+    zadd_(Zvertexridgetot, size);
+    zmax_(Zvertexridgemax, size);
+    trace3((qh ferr, "qh_vertexridges: found %d ridges for v%d\n",
+             size, vertex->id));
+  }
+  return ridges;
+} /* vertexridges */
+
+/*---------------------------------
+  
+  qh_vertexridges_facet( vertex, facet, ridges )
+    add adjacent ridges for vertex in facet
+    neighbor->visitid==qh.visit_id if it hasn't been visited
+
+  returns:
+    ridges updated
+    sets facet->visitid to qh.visit_id-1
+
+  design:
+    for each ridge of facet
+      if ridge of visited neighbor (i.e., unprocessed)
+        if vertex in ridge
+          append ridge to vertex
+    mark facet processed
+*/
+void qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges) {
+  ridgeT *ridge, **ridgep;
+  facetT *neighbor;
+
+  FOREACHridge_(facet->ridges) {
+    neighbor= otherfacet_(ridge, facet);
+    if (neighbor->visitid == qh visit_id 
+    && qh_setin (ridge->vertices, vertex))
+      qh_setappend (ridges, ridge);
+  }
+  facet->visitid= qh visit_id-1;
+} /* vertexridges_facet */
+
+/*---------------------------------
+  
+  qh_willdelete( facet, replace )
+    moves facet to visible list
+    sets facet->f.replace to replace (may be NULL)
+
+  returns:
+    bumps qh.num_visible
+*/
+void qh_willdelete (facetT *facet, facetT *replace) {
+
+  qh_removefacet(facet);
+  qh_prependfacet (facet, &qh visible_list);
+  qh num_visible++;
+  facet->visible= True;
+  facet->f.replace= replace;
+} /* willdelete */
+
+#else /* qh_NOmerge */
+void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle) {
+}
+void qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
+                      boolT vneighbors) {
+}
+boolT qh_checkzero (boolT testall) {
+   }
+#endif /* qh_NOmerge */
+

Added: trunk/scipy/spatial/qhull/src/merge.h
===================================================================
--- trunk/scipy/spatial/qhull/src/merge.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/merge.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,174 @@
+/*
  ---------------------------------
+
+   merge.h 
+   header file for merge.c
+
+   see qh-merge.htm and merge.c
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#ifndef qhDEFmerge
+#define qhDEFmerge 1
+
+
+/*============ -constants- ==============*/
+
+/*----------------------------------
+
+  qh_ANGLEredundant
+    indicates redundant merge in mergeT->angle
+*/
+#define qh_ANGLEredundant 6.0
+
+/*----------------------------------
+  
+  qh_ANGLEdegen
+    indicates degenerate facet in mergeT->angle
+*/
+#define qh_ANGLEdegen     5.0
+
+/*----------------------------------
+  
+  qh_ANGLEconcave
+    offset to indicate concave facets in mergeT->angle
+  
+  notes:
+    concave facets are assigned the range of [2,4] in mergeT->angle
+    roundoff error may make the angle less than 2
+*/
+#define qh_ANGLEconcave  1.5
+
+/*----------------------------------
+  
+  MRG... (mergeType)
+    indicates the type of a merge (mergeT->type)
+*/
+typedef enum {	/* in sort order for facet_mergeset */
+  MRGnone= 0,
+  MRGcoplanar,		/* centrum coplanar */
+  MRGanglecoplanar,	/* angle coplanar */
+  			/* could detect half concave ridges */
+  MRGconcave,		/* concave ridge */
+  MRGflip,		/* flipped facet. facet1 == facet2 */
+  MRGridge,		/* duplicate ridge (qh_MERGEridge) */
+                        /* degen and redundant go onto degen_mergeset */
+  MRGdegen,		/* degenerate facet (not enough neighbors) facet1 == facet2 */
+  MRGredundant,		/* redundant facet (vertex subset) */
+  			/* merge_degenredundant assumes degen < redundant */
+  MRGmirror,	        /* mirror facet from qh_triangulate */
+  ENDmrg
+} mergeType;
+
+/*----------------------------------
+  
+  qh_MERGEapex
+    flag for qh_mergefacet() to indicate an apex merge  
+*/
+#define qh_MERGEapex     True
+
+/*============ -structures- ====================*/
+
+/*----------------------------------
+     
+  mergeT
+    structure used to merge facets
+*/
+
+typedef struct mergeT mergeT;
+struct mergeT {		/* initialize in qh_appendmergeset */
+  realT   angle;        /* angle between normals of facet1 and facet2 */
+  facetT *facet1; 	/* will merge facet1 into facet2 */
+  facetT *facet2;
+  mergeType type;
+};
+
+
+/*=========== -macros- =========================*/
+
+/*----------------------------------
+     
+  FOREACHmerge_( merges ) {...}
+    assign 'merge' to each merge in merges
+       
+  notes:
+    uses 'mergeT *merge, **mergep;'
+    if qh_mergefacet(),
+      restart since qh.facet_mergeset may change
+    see FOREACHsetelement_
+*/
+#define FOREACHmerge_( merges ) FOREACHsetelement_(mergeT, merges, merge)
+
+/*============ prototypes in alphabetical order after pre/postmerge =======*/
+
+void    qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle);
+void    qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
+             boolT vneighbors);
+void    qh_all_merges (boolT othermerge, boolT vneighbors);
+void    qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle);
+setT   *qh_basevertices( facetT *samecycle);
+void    qh_checkconnect (void /* qh new_facets */);
+boolT   qh_checkzero (boolT testall);
+int     qh_compareangle(const void *p1, const void *p2);
+int     qh_comparemerge(const void *p1, const void *p2);
+int     qh_comparevisit (const void *p1, const void *p2);
+void    qh_copynonconvex (ridgeT *atridge);
+void    qh_degen_redundant_facet (facetT *facet);
+void   	qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet);
+vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges);
+void    qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
+           facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
+facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
+void 	qh_flippedmerges(facetT *facetlist, boolT *wasmerge);
+void 	qh_forcedmerges( boolT *wasmerge);
+void	qh_getmergeset(facetT *facetlist);
+void 	qh_getmergeset_initial (facetT *facetlist);
+void    qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
+ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge, 
+              vertexT *vertex, vertexT *oldvertex, int *hashslot);
+void 	qh_makeridges(facetT *facet);
+void    qh_mark_dupridges(facetT *facetlist);
+void    qh_maydropneighbor (facetT *facet);
+int     qh_merge_degenredundant (void);
+void    qh_merge_nonconvex( facetT *facet1, facetT *facet2, mergeType mergetype);
+void    qh_mergecycle (facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_all (facetT *facetlist, boolT *wasmerge);
+void    qh_mergecycle_facets( facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_vneighbors( facetT *samecycle, facetT *newfacet);
+void 	qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex);
+void    qh_mergefacet2d (facetT *facet1, facetT *facet2);
+void 	qh_mergeneighbors(facetT *facet1, facetT *facet2);
+void 	qh_mergeridges(facetT *facet1, facetT *facet2);
+void    qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex);
+void    qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2);
+void    qh_mergevertex_neighbors(facetT *facet1, facetT *facet2);
+void	qh_mergevertices(setT *vertices1, setT **vertices);
+setT   *qh_neighbor_intersections (vertexT *vertex);
+void    qh_newvertices (setT *vertices);
+boolT   qh_reducevertices (void);
+vertexT *qh_redundant_vertex (vertexT *vertex);
+boolT   qh_remove_extravertices (facetT *facet);
+vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet);
+void	qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
+void    qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges,
+			facetT *oldfacet, facetT *neighborA);
+boolT 	qh_test_appendmerge (facetT *facet, facetT *neighbor);
+boolT   qh_test_vneighbors (void /* qh newfacet_list */);
+void    qh_tracemerge (facetT *facet1, facetT *facet2);
+void    qh_tracemerging (void);
+void    qh_updatetested( facetT *facet1, facetT *facet2);
+setT   *qh_vertexridges (vertexT *vertex);
+void    qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges);
+void    qh_willdelete (facetT *facet, facetT *replace);
+
+#endif /* qhDEFmerge */

Added: trunk/scipy/spatial/qhull/src/poly.c
===================================================================
--- trunk/scipy/spatial/qhull/src/poly.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/poly.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,1182 @@
+/*
  ---------------------------------
+
+   poly.c 
+   implements polygons and simplices
+
+   see qh-poly.htm, poly.h and qhull.h
+
+   infrequent code is in poly2.c 
+   (all but top 50 and their callers 12/3/95)
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#include "qhull_a.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*---------------------------------
+  
+  qh_appendfacet( facet )
+    appends facet to end of qh.facet_list,
+
+  returns:
+    updates qh.newfacet_list, facet_next, facet_list
+    increments qh.numfacets
+  
+  notes:
+    assumes qh.facet_list/facet_tail is defined (createsimplex)
+
+  see:
+    qh_removefacet()
+
+*/
+void qh_appendfacet(facetT *facet) {
+  facetT *tail= qh facet_tail;
+
+  if (tail == qh newfacet_list)
+    qh newfacet_list= facet;
+  if (tail == qh facet_next)
+    qh facet_next= facet;
+  facet->previous= tail->previous;
+  facet->next= tail;
+  if (tail->previous)
+    tail->previous->next= facet;
+  else
+    qh facet_list= facet;
+  tail->previous= facet;
+  qh num_facets++;
+  trace4((qh ferr, "qh_appendfacet: append f%d to facet_list\n", facet->id));
+} /* appendfacet */
+
+
+/*---------------------------------
+  
+  qh_appendvertex( vertex )
+    appends vertex to end of qh.vertex_list,
+
+  returns:
+    sets vertex->newlist
+    updates qh.vertex_list, newvertex_list
+    increments qh.num_vertices
+
+  notes:
+    assumes qh.vertex_list/vertex_tail is defined (createsimplex)
+
+*/
+void qh_appendvertex (vertexT *vertex) {
+  vertexT *tail= qh vertex_tail;
+
+  if (tail == qh newvertex_list)
+    qh newvertex_list= vertex;
+  vertex->newlist= True;
+  vertex->previous= tail->previous;
+  vertex->next= tail;
+  if (tail->previous)
+    tail->previous->next= vertex;
+  else
+    qh vertex_list= vertex;
+  tail->previous= vertex;
+  qh num_vertices++;
+  trace4((qh ferr, "qh_appendvertex: append v%d to vertex_list\n", vertex->id));
+} /* appendvertex */
+
+
+/*---------------------------------
+  
+  qh_attachnewfacets( )
+    attach horizon facets to new facets in qh.newfacet_list
+    newfacets have neighbor and ridge links to horizon but not vice versa
+    only needed for qh.ONLYgood
+
+  returns:
+    set qh.NEWfacets
+    horizon facets linked to new facets 
+      ridges changed from visible facets to new facets
+      simplicial ridges deleted
+    qh.visible_list, no ridges valid
+    facet->f.replace is a newfacet (if any)
+
+  design:
+    delete interior ridges and neighbor sets by
+      for each visible, non-simplicial facet
+        for each ridge
+          if last visit or if neighbor is simplicial
+            if horizon neighbor
+              delete ridge for horizon's ridge set
+            delete ridge
+        erase neighbor set
+    attach horizon facets and new facets by
+      for all new facets
+        if corresponding horizon facet is simplicial
+          locate corresponding visible facet {may be more than one}
+          link visible facet to new facet
+          replace visible facet with new facet in horizon
+        else it's non-simplicial
+          for all visible neighbors of the horizon facet
+            link visible neighbor to new facet
+            delete visible neighbor from horizon facet
+          append new facet to horizon's neighbors
+          the first ridge of the new facet is the horizon ridge
+          link the new facet into the horizon ridge
+*/
+void qh_attachnewfacets (void ) {
+  facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
+  ridgeT *ridge, **ridgep;
+
+  qh NEWfacets= True;
+  trace3((qh ferr, "qh_attachnewfacets: delete interior ridges\n"));
+  qh visit_id++;
+  FORALLvisible_facets {
+    visible->visitid= qh visit_id;
+    if (visible->ridges) {
+      FOREACHridge_(visible->ridges) {
+	neighbor= otherfacet_(ridge, visible);
+	if (neighbor->visitid == qh visit_id
+	    || (!neighbor->visible && neighbor->simplicial)) {
+	  if (!neighbor->visible)  /* delete ridge for simplicial horizon */
+	    qh_setdel (neighbor->ridges, ridge);
+	  qh_setfree (&(ridge->vertices)); /* delete on 2nd visit */
+	  qh_memfree (ridge, sizeof(ridgeT));
+	}
+      }
+      SETfirst_(visible->ridges)= NULL;
+    }
+    SETfirst_(visible->neighbors)= NULL;
+  }
+  trace1((qh ferr, "qh_attachnewfacets: attach horizon facets to new facets\n"));
+  FORALLnew_facets {
+    horizon= SETfirstt_(newfacet->neighbors, facetT);
+    if (horizon->simplicial) {
+      visible= NULL;
+      FOREACHneighbor_(horizon) {   /* may have more than one horizon ridge */
+	if (neighbor->visible) {
+	  if (visible) {
+	    if (qh_setequal_skip (newfacet->vertices, 0, horizon->vertices,
+				  SETindex_(horizon->neighbors, neighbor))) {
+	      visible= neighbor;
+	      break;
+	    }
+	  }else
+	    visible= neighbor;
+	}
+      }
+      if (visible) {
+	visible->f.replace= newfacet;
+	qh_setreplace (horizon->neighbors, visible, newfacet);
+      }else {
+	fprintf (qh ferr, "qhull internal error (qh_attachnewfacets): couldn't find visible facet for horizon f%d of newfacet f%d\n",
+		 horizon->id, newfacet->id);
+	qh_errexit2 (qh_ERRqhull, horizon, newfacet);
+      }
+    }else { /* non-simplicial, with a ridge for newfacet */
+      FOREACHneighbor_(horizon) {    /* may hold for many new facets */
+	if (neighbor->visible) {
+	  neighbor->f.replace= newfacet;
+	  qh_setdelnth (horizon->neighbors,
+			SETindex_(horizon->neighbors, neighbor));
+	  neighborp--; /* repeat */
+	}
+      }
+      qh_setappend (&horizon->neighbors, newfacet);
+      ridge= SETfirstt_(newfacet->ridges, ridgeT);
+      if (ridge->top == horizon)
+	ridge->bottom= newfacet;
+      else
+	ridge->top= newfacet;
+      }
+  } /* newfacets */
+  if (qh PRINTstatistics) {
+    FORALLvisible_facets {
+      if (!visible->f.replace) 
+	zinc_(Zinsidevisible);
+    }
+  }
+} /* attachnewfacets */
+
+/*---------------------------------
+  
+  qh_checkflipped( facet, dist, allerror )
+    checks facet orientation to interior point
+
+    if allerror set,
+      tests against qh.DISTround
+    else
+      tests against 0 since tested against DISTround before
+
+  returns:
+    False if it flipped orientation (sets facet->flipped)
+    distance if non-NULL
+*/
+boolT qh_checkflipped (facetT *facet, realT *distp, boolT allerror) {
+  realT dist;
+
+  if (facet->flipped && !distp)
+    return False;
+  zzinc_(Zdistcheck);
+  qh_distplane(qh interior_point, facet, &dist);
+  if (distp)
+    *distp= dist;
+  if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) {
+    facet->flipped= True;
+    zzinc_(Zflippedfacets);
+    trace0((qh ferr, "qh_checkflipped: facet f%d is flipped, distance= %6.12g during p%d\n",
+              facet->id, dist, qh furthest_id));
+    qh_precision ("flipped facet");
+    return False;
+  }
+  return True;
+} /* checkflipped */
+
+/*---------------------------------
+  
+  qh_delfacet( facet )
+    removes facet from facet_list and frees up its memory
+
+  notes:
+    assumes vertices and ridges already freed
+*/
+void qh_delfacet(facetT *facet) {
+  void **freelistp; /* used !qh_NOmem */
+
+  trace4((qh ferr, "qh_delfacet: delete f%d\n", facet->id));
+  if (facet == qh tracefacet)
+    qh tracefacet= NULL;
+  if (facet == qh GOODclosest)
+    qh GOODclosest= NULL;
+  qh_removefacet(facet);
+  if (!facet->tricoplanar || facet->keepcentrum) {
+    qh_memfree_(facet->normal, qh normal_size, freelistp);
+    if (qh CENTERtype == qh_ASvoronoi) {   /* uses macro calls */
+      qh_memfree_(facet->center, qh center_size, freelistp);
+    }else /* AScentrum */ {
+      qh_memfree_(facet->center, qh normal_size, freelistp);
+    }
+  }
+  qh_setfree(&(facet->neighbors));
+  if (facet->ridges)
+    qh_setfree(&(facet->ridges));
+  qh_setfree(&(facet->vertices));
+  if (facet->outsideset)
+    qh_setfree(&(facet->outsideset));
+  if (facet->coplanarset)
+    qh_setfree(&(facet->coplanarset));
+  qh_memfree_(facet, sizeof(facetT), freelistp);
+} /* delfacet */
+
+
+/*---------------------------------
+  
+  qh_deletevisible()
+    delete visible facets and vertices
+
+  returns:
+    deletes each facet and removes from facetlist
+    at exit, qh.visible_list empty (== qh.newfacet_list)
+
+  notes:
+    ridges already deleted
+    horizon facets do not reference facets on qh.visible_list
+    new facets in qh.newfacet_list
+    uses   qh.visit_id;
+*/
+void qh_deletevisible (void /*qh visible_list*/) {
+  facetT *visible, *nextfacet;
+  vertexT *vertex, **vertexp;
+  int numvisible= 0, numdel= qh_setsize(qh del_vertices);
+
+  trace1((qh ferr, "qh_deletevisible: delete %d visible facets and %d vertices\n",
+         qh num_visible, numdel));
+  for (visible= qh visible_list; visible && visible->visible; 
+                visible= nextfacet) { /* deleting current */
+    nextfacet= visible->next;        
+    numvisible++;
+    qh_delfacet(visible);
+  }
+  if (numvisible != qh num_visible) {
+    fprintf (qh ferr, "qhull internal error (qh_deletevisible): qh num_visible %d is not number of visible facets %d\n",
+             qh num_visible, numvisible);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  qh num_visible= 0;
+  zadd_(Zvisfacettot, numvisible);
+  zmax_(Zvisfacetmax, numvisible);
+  zzadd_(Zdelvertextot, numdel);
+  zmax_(Zdelvertexmax, numdel);
+  FOREACHvertex_(qh del_vertices) 
+    qh_delvertex (vertex);
+  qh_settruncate (qh del_vertices, 0);
+} /* deletevisible */
+
+/*---------------------------------
+  
+  qh_facetintersect( facetA, facetB, skipa, skipB, prepend )
+    return vertices for intersection of two simplicial facets
+    may include 1 prepended entry (if more, need to settemppush)
+    
+  returns:
+    returns set of qh.hull_dim-1 + prepend vertices
+    returns skipped index for each test and checks for exactly one
+
+  notes:
+    does not need settemp since set in quick memory
+  
+  see also:
+    qh_vertexintersect and qh_vertexintersect_new
+    use qh_setnew_delnthsorted to get nth ridge (no skip information)
+
+  design:
+    locate skipped vertex by scanning facet A's neighbors
+    locate skipped vertex by scanning facet B's neighbors
+    intersect the vertex sets
+*/
+setT *qh_facetintersect (facetT *facetA, facetT *facetB,
+			 int *skipA,int *skipB, int prepend) {
+  setT *intersect;
+  int dim= qh hull_dim, i, j;
+  facetT **neighborsA, **neighborsB;
+
+  neighborsA= SETaddr_(facetA->neighbors, facetT);
+  neighborsB= SETaddr_(facetB->neighbors, facetT);
+  i= j= 0;
+  if (facetB == *neighborsA++)
+    *skipA= 0;
+  else if (facetB == *neighborsA++)
+    *skipA= 1;
+  else if (facetB == *neighborsA++)
+    *skipA= 2;
+  else {
+    for (i= 3; i < dim; i++) {
+      if (facetB == *neighborsA++) {
+        *skipA= i;
+        break;
+      }
+    }
+  }
+  if (facetA == *neighborsB++)
+    *skipB= 0;
+  else if (facetA == *neighborsB++)
+    *skipB= 1;
+  else if (facetA == *neighborsB++)
+    *skipB= 2;
+  else {
+    for (j= 3; j < dim; j++) {
+      if (facetA == *neighborsB++) {
+        *skipB= j;
+        break;
+      }
+    }
+  }
+  if (i >= dim || j >= dim) {
+    fprintf (qh ferr, "qhull internal error (qh_facetintersect): f%d or f%d not in others neighbors\n",
+            facetA->id, facetB->id);
+    qh_errexit2 (qh_ERRqhull, facetA, facetB);
+  }
+  intersect= qh_setnew_delnthsorted (facetA->vertices, qh hull_dim, *skipA, prepend);
+  trace4((qh ferr, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
+	  facetA->id, *skipA, facetB->id, *skipB));
+  return(intersect);
+} /* facetintersect */
+
+/*---------------------------------
+  
+  qh_gethash( hashsize, set, size, firstindex, skipelem )
+    return hashvalue for a set with firstindex and skipelem
+
+  notes:
+    assumes at least firstindex+1 elements
+    assumes skipelem is NULL, in set, or part of hash
+    
+    hashes memory addresses which may change over different runs of the same data
+    using sum for hash does badly in high d
+*/
+unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem) {
+  void **elemp= SETelemaddr_(set, firstindex, void);
+  ptr_intT hash = 0, elem;
+  int i;
+  unsigned result;
+
+  switch (size-firstindex) {
+  case 1:
+    hash= (ptr_intT)(*elemp) - (ptr_intT) skipelem;
+    break;
+  case 2:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem;
+    break;
+  case 3:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      - (ptr_intT) skipelem;
+    break;
+  case 4:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] - (ptr_intT) skipelem;
+    break;
+  case 5:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem;
+    break;
+  case 6:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
+      - (ptr_intT) skipelem;
+    break;
+  default:
+    hash= 0;
+    i= 3;
+    do {     /* this is about 10% in 10-d */
+      if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
+        hash ^= (elem << i) + (elem >> (32-i));
+	i += 3;
+	if (i >= 32)
+	  i -= 32;
+      }
+    }while(*elemp);
+    break;
+  }
+  result= (unsigned)hash;
+  result %= (unsigned)hashsize;
+  /* result= 0; for debugging purposes */
+  return result;
+} /* gethash */
+
+/*---------------------------------
+  
+  qh_makenewfacet( vertices, toporient, horizon )
+    creates a toporient? facet from vertices
+
+  returns:
+    returns newfacet
+      adds newfacet to qh.facet_list
+      newfacet->vertices= vertices
+      if horizon
+        newfacet->neighbor= horizon, but not vice versa
+    newvertex_list updated with vertices
+*/
+facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) {
+  facetT *newfacet;
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (!vertex->newlist) {
+      qh_removevertex (vertex);
+      qh_appendvertex (vertex);
+    }
+  }
+  newfacet= qh_newfacet();
+  newfacet->vertices= vertices;
+  newfacet->toporient= toporient;
+  if (horizon)
+    qh_setappend(&(newfacet->neighbors), horizon);
+  qh_appendfacet(newfacet);
+  return(newfacet);
+} /* makenewfacet */
+
+
+/*---------------------------------
+  
+  qh_makenewplanes()
+    make new hyperplanes for facets on qh.newfacet_list
+
+  returns:
+    all facets have hyperplanes or are marked for   merging
+    doesn't create hyperplane if horizon is coplanar (will merge)
+    updates qh.min_vertex if qh.JOGGLEmax
+
+  notes:
+    facet->f.samecycle is defined for facet->mergehorizon facets
+*/
+void qh_makenewplanes (void /* newfacet_list */) {
+  facetT *newfacet;
+
+  FORALLnew_facets {
+    if (!newfacet->mergehorizon)
+      qh_setfacetplane (newfacet);  
+  }
+  if (qh JOGGLEmax < REALmax/2)  
+    minimize_(qh min_vertex, -wwval_(Wnewvertexmax));
+} /* makenewplanes */
+
+/*---------------------------------
+  
+  qh_makenew_nonsimplicial( visible, apex, numnew )
+    make new facets for ridges of a visible facet
+    
+  returns:
+    first newfacet, bumps numnew as needed
+    attaches new facets if !qh.ONLYgood
+    marks ridge neighbors for simplicial visible
+    if (qh.ONLYgood)
+      ridges on newfacet, horizon, and visible
+    else
+      ridge and neighbors between newfacet and   horizon
+      visible facet's ridges are deleted    
+
+  notes:
+    qh.visit_id if visible has already been processed
+    sets neighbor->seen for building f.samecycle
+      assumes all 'seen' flags initially false
+    
+  design:
+    for each ridge of visible facet
+      get neighbor of visible facet
+      if neighbor was already processed
+        delete the ridge (will delete all visible facets later)
+      if neighbor is a horizon facet
+        create a new facet
+        if neighbor coplanar
+          adds newfacet to f.samecycle for later merging
+        else 
+          updates neighbor's neighbor set
+          (checks for non-simplicial facet with multiple ridges to visible facet)
+        updates neighbor's ridge set
+        (checks for simplicial neighbor to non-simplicial visible facet)
+	(deletes ridge if neighbor is simplicial)
+          
+*/
+#ifndef qh_NOmerge
+facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew) {
+  void **freelistp; /* used !qh_NOmem */
+  ridgeT *ridge, **ridgep;
+  facetT *neighbor, *newfacet= NULL, *samecycle;
+  setT *vertices;
+  boolT toporient;
+  int ridgeid;
+
+  FOREACHridge_(visible->ridges) {
+    ridgeid= ridge->id;
+    neighbor= otherfacet_(ridge, visible);
+    if (neighbor->visible) {
+      if (!qh ONLYgood) {
+        if (neighbor->visitid == qh visit_id) {
+          qh_setfree (&(ridge->vertices));  /* delete on 2nd visit */
+	  qh_memfree_(ridge, sizeof(ridgeT), freelistp);
+	}
+      }
+    }else {  /* neighbor is an horizon facet */
+      toporient= (ridge->top == visible);
+      vertices= qh_setnew (qh hull_dim); /* makes sure this is quick */
+      qh_setappend (&vertices, apex);
+      qh_setappend_set (&vertices, ridge->vertices);
+      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
+      (*numnew)++;
+      if (neighbor->coplanar) {
+	newfacet->mergehorizon= True;
+        if (!neighbor->seen) {
+          newfacet->f.samecycle= newfacet;
+          neighbor->f.newcycle= newfacet;
+        }else {
+          samecycle= neighbor->f.newcycle;
+          newfacet->f.samecycle= samecycle->f.samecycle;
+          samecycle->f.samecycle= newfacet;
+	}
+      }
+      if (qh ONLYgood) {
+        if (!neighbor->simplicial)
+ 	  qh_setappend(&(newfacet->ridges), ridge);
+      }else {  /* qh_attachnewfacets */
+        if (neighbor->seen) {
+	  if (neighbor->simplicial) {
+	    fprintf (qh ferr, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n", 
+	           neighbor->id, visible->id);
+	    qh_errexit2 (qh_ERRqhull, neighbor, visible);
+	  }
+	  qh_setappend (&(neighbor->neighbors), newfacet);
+	}else
+          qh_setreplace (neighbor->neighbors, visible, newfacet);
+        if (neighbor->simplicial) {
+          qh_setdel (neighbor->ridges, ridge);
+          qh_setfree (&(ridge->vertices)); 
+	  qh_memfree (ridge, sizeof(ridgeT));
+	}else {
+ 	  qh_setappend(&(newfacet->ridges), ridge);
+ 	  if (toporient)
+ 	    ridge->top= newfacet;
+ 	  else
+ 	    ridge->bottom= newfacet;
+ 	}
+      trace4((qh ferr, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
+	    newfacet->id, apex->id, ridgeid, neighbor->id));
+      }
+    }
+    neighbor->seen= True;        
+  } /* for each ridge */
+  if (!qh ONLYgood)
+    SETfirst_(visible->ridges)= NULL;
+  return newfacet;
+} /* makenew_nonsimplicial */
+#else /* qh_NOmerge */
+facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew) {
+  return NULL;
+}
+#endif /* qh_NOmerge */
+
+/*---------------------------------
+  
+  qh_makenew_simplicial( visible, apex, numnew )
+    make new facets for simplicial visible facet and apex
+
+  returns:
+    attaches new facets if (!qh.ONLYgood)
+      neighbors between newfacet and horizon
+
+  notes:
+    nop if neighbor->seen or neighbor->visible (see qh_makenew_nonsimplicial)
+
+  design:
+    locate neighboring horizon facet for visible facet
+    determine vertices and orientation
+    create new facet
+    if coplanar,
+      add new facet to f.samecycle
+    update horizon facet's neighbor list        
+*/
+facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew) {
+  facetT *neighbor, **neighborp, *newfacet= NULL;
+  setT *vertices;
+  boolT flip, toporient;
+  int horizonskip, visibleskip;
+
+  FOREACHneighbor_(visible) {
+    if (!neighbor->seen && !neighbor->visible) {
+      vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1);
+      SETfirst_(vertices)= apex;
+      flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
+      if (neighbor->toporient)         
+	toporient= horizonskip & 0x1;
+      else
+	toporient= (horizonskip & 0x1) ^ 0x1;
+      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
+      (*numnew)++;
+      if (neighbor->coplanar && (qh PREmerge || qh MERGEexact)) {
+#ifndef qh_NOmerge
+	newfacet->f.samecycle= newfacet;
+	newfacet->mergehorizon= True;
+#endif
+      }
+      if (!qh ONLYgood)
+        SETelem_(neighbor->neighbors, horizonskip)= newfacet;
+      trace4((qh ferr, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
+	    newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
+	      neighbor->toporient, visible->id, visibleskip, flip));
+    }
+  }
+  return newfacet;
+} /* makenew_simplicial */
+
+/*---------------------------------
+  
+  qh_matchneighbor( newfacet, newskip, hashsize, hashcount )
+    either match subridge of newfacet with neighbor or add to hash_table
+
+  returns:
+    duplicate ridges are unmatched and marked by qh_DUPLICATEridge
+
+  notes:
+    ridge is newfacet->vertices w/o newskip vertex
+    do not allocate memory (need to free hash_table cleanly)
+    uses linear hash chains
+  
+  see also:
+    qh_matchduplicates
+
+  design:
+    for each possible matching facet in qh.hash_table
+      if vertices match
+        set ismatch, if facets have opposite orientation
+        if ismatch and matching facet doesn't have a match
+          match the facets by updating their neighbor sets
+        else
+          indicate a duplicate ridge
+          set facet hyperplane for later testing
+          add facet to hashtable
+          unless the other facet was already a duplicate ridge
+            mark both facets with a duplicate ridge
+            add other facet (if defined) to hash table
+*/
+void qh_matchneighbor (facetT *newfacet, int newskip, int hashsize, int *hashcount) {
+  boolT newfound= False;   /* True, if new facet is already in hash chain */
+  boolT same, ismatch;
+  int hash, scan;
+  facetT *facet, *matchfacet;
+  int skip, matchskip;
+
+  hash= (int)qh_gethash (hashsize, newfacet->vertices, qh hull_dim, 1, 
+                     SETelem_(newfacet->vertices, newskip));
+  trace4((qh ferr, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
+	  newfacet->id, newskip, hash, *hashcount));
+  zinc_(Zhashlookup);
+  for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT)); 
+       scan= (++scan >= hashsize ? 0 : scan)) {
+    if (facet == newfacet) {
+      newfound= True;
+      continue;
+    }
+    zinc_(Zhashtests);
+    if (qh_matchvertices (1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+      if (SETelem_(newfacet->vertices, newskip) == 
+          SETelem_(facet->vertices, skip)) {
+        qh_precision ("two facets with the same vertices");
+        fprintf (qh ferr, "qhull precision error: Vertex sets are the same for f%d and f%d.  Can not force output.\n",
+          facet->id, newfacet->id);
+        qh_errexit2 (qh_ERRprec, facet, newfacet);
+      }
+      ismatch= (same == (newfacet->toporient ^ facet->toporient));
+      matchfacet= SETelemt_(facet->neighbors, skip, facetT);
+      if (ismatch && !matchfacet) {
+        SETelem_(facet->neighbors, skip)= newfacet;
+        SETelem_(newfacet->neighbors, newskip)= facet;
+        (*hashcount)--;
+        trace4((qh ferr, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
+           facet->id, skip, newfacet->id, newskip));
+        return;
+      }
+      if (!qh PREmerge && !qh MERGEexact) {
+        qh_precision ("a ridge with more than two neighbors");
+	fprintf (qh ferr, "qhull precision error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors.  Can not continue.\n",
+		 facet->id, newfacet->id, getid_(matchfacet));
+	qh_errexit2 (qh_ERRprec, facet, newfacet);
+      }
+      SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
+      newfacet->dupridge= True;
+      if (!newfacet->normal)
+	qh_setfacetplane (newfacet);
+      qh_addhash (newfacet, qh hash_table, hashsize, hash);
+      (*hashcount)++;
+      if (!facet->normal)
+	qh_setfacetplane (facet);
+      if (matchfacet != qh_DUPLICATEridge) {
+	SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
+	facet->dupridge= True;
+	if (!facet->normal)
+	  qh_setfacetplane (facet);
+	if (matchfacet) {
+	  matchskip= qh_setindex (matchfacet->neighbors, facet);
+	  SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge;
+	  matchfacet->dupridge= True;
+	  if (!matchfacet->normal)
+	    qh_setfacetplane (matchfacet);
+	  qh_addhash (matchfacet, qh hash_table, hashsize, hash);
+	  *hashcount += 2;
+	}
+      }
+      trace4((qh ferr, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
+	   newfacet->id, newskip, facet->id, skip, 
+	   (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)), 
+	   ismatch, hash));
+      return; /* end of duplicate ridge */
+    }
+  }
+  if (!newfound) 
+    SETelem_(qh hash_table, scan)= newfacet;  /* same as qh_addhash */
+  (*hashcount)++;
+  trace4((qh ferr, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
+           newfacet->id, newskip, hash));
+} /* matchneighbor */
+
+
+/*---------------------------------
+  
+  qh_matchnewfacets()
+    match newfacets in qh.newfacet_list to their newfacet neighbors
+
+  returns:
+    qh.newfacet_list with full neighbor sets
+      get vertices with nth neighbor by deleting nth vertex
+    if qh.PREmerge/MERGEexact or qh.FORCEoutput 
+      sets facet->flippped if flipped normal (also prevents point partitioning)
+    if duplicate ridges and qh.PREmerge/MERGEexact
+      sets facet->dupridge
+      missing neighbor links identifies extra ridges to be merging (qh_MERGEridge)
+
+  notes:
+    newfacets already have neighbor[0] (horizon facet)
+    assumes qh.hash_table is NULL
+    vertex->neighbors has not been updated yet
+    do not allocate memory after qh.hash_table (need to free it cleanly)
+
+  design:
+    delete neighbor sets for all new facets
+    initialize a hash table
+    for all new facets
+      match facet with neighbors
+    if unmatched facets (due to duplicate ridges)
+      for each new facet with a duplicate ridge
+        match it with a facet
+    check for flipped facets
+*/
+void qh_matchnewfacets (void /* qh newfacet_list */) {
+  int numnew=0, hashcount=0, newskip;
+  facetT *newfacet, *neighbor;
+  int dim= qh hull_dim, hashsize, neighbor_i, neighbor_n;
+  setT *neighbors;
+#ifndef qh_NOtrace
+  int facet_i, facet_n, numfree= 0;
+  facetT *facet;
+#endif
+  
+  trace1((qh ferr, "qh_matchnewfacets: match neighbors for new facets.\n"));
+  FORALLnew_facets {
+    numnew++;
+    {  /* inline qh_setzero (newfacet->neighbors, 1, qh hull_dim); */
+      neighbors= newfacet->neighbors;
+      neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
+      memset ((char *)SETelemaddr_(neighbors, 1, void), 0, dim * SETelemsize);
+    }    
+  }
+  qh_newhashtable (numnew*(qh hull_dim-1)); /* twice what is normally needed,
+                                     but every ridge could be DUPLICATEridge */
+  hashsize= qh_setsize (qh hash_table);
+  FORALLnew_facets {
+    for (newskip=1; newskipneighbors, k, facetT);
+	  if (!neighbor || neighbor == qh_DUPLICATEridge)
+	    count++;
+	}
+	if (facet == newfacet)
+	  break;
+      }
+      if (count != hashcount) {
+	fprintf (qh ferr, "qh_matchnewfacets: after adding facet %d, hashcount %d != count %d\n",
+		 newfacet->id, hashcount, count);
+	qh_errexit (qh_ERRqhull, newfacet, NULL);
+      }
+    }
+#endif  /* end of trap code */
+  }
+  if (hashcount) {
+    FORALLnew_facets {
+      if (newfacet->dupridge) {
+        FOREACHneighbor_i_(newfacet) {
+          if (neighbor == qh_DUPLICATEridge) {
+            qh_matchduplicates (newfacet, neighbor_i, hashsize, &hashcount);
+         	    /* this may report MERGEfacet */
+	  }
+        }
+      }
+    }
+  }
+  if (hashcount) {
+    fprintf (qh ferr, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
+        hashcount);
+    qh_printhashtable (qh ferr);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+#ifndef qh_NOtrace
+  if (qh IStracing >= 2) {
+    FOREACHfacet_i_(qh hash_table) {
+      if (!facet)
+        numfree++;
+    }
+    fprintf (qh ferr, "qh_matchnewfacets: %d new facets, %d unused hash entries .  hashsize %d\n",
+	     numnew, numfree, qh_setsize (qh hash_table));
+  }
+#endif /* !qh_NOtrace */
+  qh_setfree (&qh hash_table);
+  if (qh PREmerge || qh MERGEexact) {
+    if (qh IStracing >= 4)
+      qh_printfacetlist (qh newfacet_list, NULL, qh_ALL);
+    FORALLnew_facets {
+      if (newfacet->normal)
+	qh_checkflipped (newfacet, NULL, qh_ALL);
+    }
+  }else if (qh FORCEoutput)
+    qh_checkflipped_all (qh newfacet_list);  /* prints warnings for flipped */
+} /* matchnewfacets */
+
+    
+/*---------------------------------
+  
+  qh_matchvertices( firstindex, verticesA, skipA, verticesB, skipB, same )
+    tests whether vertices match with a single skip
+    starts match at firstindex since all new facets have a common vertex
+
+  returns:
+    true if matched vertices
+    skip index for each set
+    sets same iff vertices have the same orientation
+
+  notes:
+    assumes skipA is in A and both sets are the same size
+
+  design:
+    set up pointers
+    scan both sets checking for a match
+    test orientation
+*/
+boolT qh_matchvertices (int firstindex, setT *verticesA, int skipA, 
+       setT *verticesB, int *skipB, boolT *same) {
+  vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
+
+  elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
+  elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
+  skipAp= SETelemaddr_(verticesA, skipA, vertexT);
+  do if (elemAp != skipAp) {
+    while (*elemAp != *elemBp++) {
+      if (skipBp)
+        return False;
+      skipBp= elemBp;  /* one extra like FOREACH */
+    }
+  }while(*(++elemAp));
+  if (!skipBp)
+    skipBp= ++elemBp;
+  *skipB= SETindex_(verticesB, skipB);
+  *same= !(((ptr_intT)skipA & 0x1) ^ ((ptr_intT)*skipB & 0x1));
+  trace4((qh ferr, "qh_matchvertices: matched by skip %d (v%d) and skip %d (v%d) same? %d\n",
+	  skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
+  return (True);
+} /* matchvertices */
+
+/*---------------------------------
+  
+  qh_newfacet()
+    return a new facet 
+
+  returns:
+    all fields initialized or cleared   (NULL)
+    preallocates neighbors set
+*/
+facetT *qh_newfacet(void) {
+  facetT *facet;
+  void **freelistp; /* used !qh_NOmem */
+  
+  qh_memalloc_(sizeof(facetT), freelistp, facet, facetT);
+  memset ((char *)facet, 0, sizeof(facetT));
+  if (qh facet_id == qh tracefacet_id)
+    qh tracefacet= facet;
+  facet->id= qh facet_id++;
+  facet->neighbors= qh_setnew(qh hull_dim);
+#if !qh_COMPUTEfurthest
+  facet->furthestdist= 0.0;
+#endif
+#if qh_MAXoutside
+  if (qh FORCEoutput && qh APPROXhull)
+    facet->maxoutside= qh MINoutside;
+  else
+    facet->maxoutside= qh DISTround;
+#endif
+  facet->simplicial= True;
+  facet->good= True;
+  facet->newfacet= True;
+  trace4((qh ferr, "qh_newfacet: created facet f%d\n", facet->id));
+  return (facet);
+} /* newfacet */
+
+
+/*---------------------------------
+  
+  qh_newridge()
+    return a new ridge
+*/
+ridgeT *qh_newridge(void) {
+  ridgeT *ridge;
+  void **freelistp;   /* used !qh_NOmem */
+
+  qh_memalloc_(sizeof(ridgeT), freelistp, ridge, ridgeT);
+  memset ((char *)ridge, 0, sizeof(ridgeT));
+  zinc_(Ztotridges);
+  if (qh ridge_id == 0xFFFFFF) {
+    fprintf(qh ferr, "\
+qhull warning: more than %d ridges.  ID field overflows and two ridges\n\
+may have the same identifier.  Otherwise output ok.\n", 0xFFFFFF);
+  }
+  ridge->id= qh ridge_id++;     
+  trace4((qh ferr, "qh_newridge: created ridge r%d\n", ridge->id));
+  return (ridge);
+} /* newridge */
+
+
+/*---------------------------------
+  
+  qh_pointid(  )
+    return id for a point, 
+    returns -3 if null, -2 if interior, or -1 if not known
+
+  alternative code:
+    unsigned long id;
+    id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
+
+  notes:
+    if point not in point array
+      the code does a comparison of unrelated pointers.
+*/
+int qh_pointid (pointT *point) {
+  long offset, id;
+
+  if (!point)
+    id= -3;
+  else if (point == qh interior_point)
+    id= -2;
+  else if (point >= qh first_point
+  && point < qh first_point + qh num_points * qh hull_dim) {
+    offset= point - qh first_point;
+    id= offset / qh hull_dim;
+  }else if ((id= qh_setindex (qh other_points, point)) != -1)
+    id += qh num_points;
+  else
+    id= -1;
+  return (int) id;
+} /* pointid */
+  
+/*---------------------------------
+  
+  qh_removefacet( facet )
+    unlinks facet from qh.facet_list,
+
+  returns:
+    updates qh.facet_list .newfacet_list .facet_next visible_list
+    decrements qh.num_facets
+
+  see:
+    qh_appendfacet
+*/
+void qh_removefacet(facetT *facet) {
+  facetT *next= facet->next, *previous= facet->previous;
+  
+  if (facet == qh newfacet_list)
+    qh newfacet_list= next;
+  if (facet == qh facet_next)
+    qh facet_next= next;
+  if (facet == qh visible_list)
+    qh visible_list= next; 
+  if (previous) {
+    previous->next= next;
+    next->previous= previous;
+  }else {  /* 1st facet in qh facet_list */
+    qh facet_list= next;
+    qh facet_list->previous= NULL;
+  }
+  qh num_facets--;
+  trace4((qh ferr, "qh_removefacet: remove f%d from facet_list\n", facet->id));
+} /* removefacet */
+
+
+/*---------------------------------
+  
+  qh_removevertex( vertex )
+    unlinks vertex from qh.vertex_list,
+
+  returns:
+    updates qh.vertex_list .newvertex_list 
+    decrements qh.num_vertices
+*/
+void qh_removevertex(vertexT *vertex) {
+  vertexT *next= vertex->next, *previous= vertex->previous;
+  
+  if (vertex == qh newvertex_list)
+    qh newvertex_list= next;
+  if (previous) {
+    previous->next= next;
+    next->previous= previous;
+  }else {  /* 1st vertex in qh vertex_list */
+    qh vertex_list= vertex->next;
+    qh vertex_list->previous= NULL;
+  }
+  qh num_vertices--;
+  trace4((qh ferr, "qh_removevertex: remove v%d from vertex_list\n", vertex->id));
+} /* removevertex */
+
+
+/*---------------------------------
+  
+  qh_updatevertices()
+    update vertex neighbors and delete interior vertices
+
+  returns:
+    if qh.VERTEXneighbors, updates neighbors for each vertex
+      if qh.newvertex_list, 
+         removes visible neighbors  from vertex neighbors
+      if qh.newfacet_list
+         adds new facets to vertex neighbors
+    if qh.visible_list
+       interior vertices added to qh.del_vertices for later partitioning
+
+  design:
+    if qh.VERTEXneighbors
+      deletes references to visible facets from vertex neighbors
+      appends new facets to the neighbor list for each vertex
+      checks all vertices of visible facets
+        removes visible facets from neighbor lists
+        marks unused vertices for deletion
+*/
+void qh_updatevertices (void /*qh newvertex_list, newfacet_list, visible_list*/) {
+  facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
+  vertexT *vertex, **vertexp;
+
+  trace3((qh ferr, "qh_updatevertices: delete interior vertices and update vertex->neighbors\n"));
+  if (qh VERTEXneighbors) {
+    FORALLvertex_(qh newvertex_list) {
+      FOREACHneighbor_(vertex) {
+	if (neighbor->visible) 
+	  SETref_(neighbor)= NULL;
+      }
+      qh_setcompact (vertex->neighbors);
+    }
+    FORALLnew_facets {
+      FOREACHvertex_(newfacet->vertices)
+        qh_setappend (&vertex->neighbors, newfacet);
+    }
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newlist && !vertex->deleted) {
+  	  FOREACHneighbor_(vertex) { /* this can happen under merging */
+	    if (!neighbor->visible)
+	      break;
+	  }
+	  if (neighbor)
+	    qh_setdel (vertex->neighbors, visible);
+	  else {
+	    vertex->deleted= True;
+	    qh_setappend (&qh del_vertices, vertex);
+	    trace2((qh ferr, "qh_updatevertices: delete vertex p%d (v%d) in f%d\n",
+		  qh_pointid(vertex->point), vertex->id, visible->id));
+  	  }
+        }
+      }
+    }
+  }else {  /* !VERTEXneighbors */
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newlist && !vertex->deleted) {
+          vertex->deleted= True;
+	  qh_setappend (&qh del_vertices, vertex);
+	  trace2((qh ferr, "qh_updatevertices: delete vertex p%d (v%d) in f%d\n",
+		  qh_pointid(vertex->point), vertex->id, visible->id));
+  	}
+      }
+    }
+  }
+} /* updatevertices */
+
+
+

Added: trunk/scipy/spatial/qhull/src/poly.h
===================================================================
--- trunk/scipy/spatial/qhull/src/poly.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/poly.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,291 @@
+/*
  ---------------------------------
+
+   poly.h 
+   header file for poly.c and poly2.c
+
+   see qh-poly.htm, qhull.h and poly.c
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#ifndef qhDEFpoly
+#define qhDEFpoly 1
+
+/*===============   constants ========================== */
+
+/*----------------------------------
+  
+  ALGORITHMfault   
+    use as argument to checkconvex() to report errors during buildhull
+*/
+#define qh_ALGORITHMfault 0
+
+/*----------------------------------
+  
+  DATAfault        
+    use as argument to checkconvex() to report errors during initialhull
+*/
+#define qh_DATAfault 1
+
+/*----------------------------------
+  
+  DUPLICATEridge
+    special value for facet->neighbor to indicate a duplicate ridge
+  
+  notes:
+    set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_DUPLICATEridge ( facetT * ) 1L
+
+/*----------------------------------
+  
+  MERGEridge       flag in facet
+    special value for facet->neighbor to indicate a merged ridge
+  
+  notes:
+    set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_MERGEridge ( facetT * ) 2L
+
+
+/*============ -structures- ====================*/
+
+/*=========== -macros- =========================*/
+
+/*----------------------------------
+  
+  FORALLfacet_( facetlist ) { ... }
+    assign 'facet' to each facet in facetlist
+    
+  notes:
+    uses 'facetT *facet;'
+    assumes last facet is a sentinel
+    
+  see:
+    FORALLfacets
+*/
+#define FORALLfacet_( facetlist ) if ( facetlist ) for( facet=( facetlist );facet && facet->next;facet=facet->next )
+
+/*----------------------------------
+  
+  FORALLnew_facets { ... } 
+    assign 'newfacet' to each facet in qh.newfacet_list
+    
+  notes:
+    uses 'facetT *newfacet;'
+    at exit, newfacet==NULL
+*/
+#define FORALLnew_facets for( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )
+
+/*----------------------------------
+  
+  FORALLvertex_( vertexlist ) { ... }
+    assign 'vertex' to each vertex in vertexlist
+    
+  notes:
+    uses 'vertexT *vertex;'
+    at exit, vertex==NULL
+*/
+#define FORALLvertex_( vertexlist ) for ( vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
+
+/*----------------------------------
+  
+  FORALLvisible_facets { ... }
+    assign 'visible' to each visible facet in qh.visible_list
+    
+  notes:
+    uses 'vacetT *visible;'
+    at exit, visible==NULL
+*/
+#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)
+
+/*----------------------------------
+  
+  FORALLsame_( newfacet ) { ... } 
+    assign 'same' to each facet in newfacet->f.samecycle
+    
+  notes:
+    uses 'facetT *same;'
+    stops when it returns to newfacet
+*/
+#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
+
+/*----------------------------------
+  
+  FORALLsame_cycle_( newfacet ) { ... } 
+    assign 'same' to each facet in newfacet->f.samecycle
+    
+  notes:
+    uses 'facetT *same;'
+    at exit, same == NULL
+*/
+#define FORALLsame_cycle_(newfacet) \
+     for (same= newfacet->f.samecycle; \
+         same; same= (same == newfacet ?  NULL : same->f.samecycle))
+
+/*----------------------------------
+  
+  FOREACHneighborA_( facet ) { ... }
+    assign 'neighborA' to each neighbor in facet->neighbors
+  
+  FOREACHneighborA_( vertex ) { ... }
+    assign 'neighborA' to each neighbor in vertex->neighbors
+  
+  declare:
+    facetT *neighborA, **neighborAp;
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHneighborA_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighborA)
+
+/*----------------------------------
+  
+  FOREACHvisible_( facets ) { ... } 
+    assign 'visible' to each facet in facets
+    
+  notes:
+    uses 'facetT *facet, *facetp;'
+    see FOREACHsetelement_
+*/
+#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
+
+/*----------------------------------
+  
+  FOREACHnewfacet_( facets ) { ... } 
+    assign 'newfacet' to each facet in facets
+    
+  notes:
+    uses 'facetT *newfacet, *newfacetp;'
+    see FOREACHsetelement_
+*/
+#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
+
+/*----------------------------------
+  
+  FOREACHvertexA_( vertices ) { ... } 
+    assign 'vertexA' to each vertex in vertices
+    
+  notes:
+    uses 'vertexT *vertexA, *vertexAp;'
+    see FOREACHsetelement_
+*/
+#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
+
+/*----------------------------------
+  
+  FOREACHvertexreverse12_( vertices ) { ... } 
+    assign 'vertex' to each vertex in vertices
+    reverse order of first two vertices
+    
+  notes:
+    uses 'vertexT *vertex, *vertexp;'
+    see FOREACHsetelement_
+*/
+#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
+
+
+/*=============== prototypes poly.c in alphabetical order ================*/
+
+void    qh_appendfacet(facetT *facet);
+void    qh_appendvertex(vertexT *vertex);
+void 	qh_attachnewfacets (void);
+boolT   qh_checkflipped (facetT *facet, realT *dist, boolT allerror);
+void	qh_delfacet(facetT *facet);
+void 	qh_deletevisible(void /*qh visible_list, qh horizon_list*/);
+setT   *qh_facetintersect (facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
+unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem);
+facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
+void    qh_makenewplanes ( void /* newfacet_list */);
+facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew);
+facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew);
+void    qh_matchneighbor (facetT *newfacet, int newskip, int hashsize,
+			  int *hashcount);
+void	qh_matchnewfacets (void);
+boolT   qh_matchvertices (int firstindex, setT *verticesA, int skipA, 
+			  setT *verticesB, int *skipB, boolT *same);
+facetT *qh_newfacet(void);
+ridgeT *qh_newridge(void);
+int     qh_pointid (pointT *point);
+void 	qh_removefacet(facetT *facet);
+void 	qh_removevertex(vertexT *vertex);
+void    qh_updatevertices (void);
+
+
+/*========== -prototypes poly2.c in alphabetical order ===========*/
+
+void    qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash);
+void 	qh_check_bestdist (void);
+void    qh_check_maxout (void);
+void    qh_check_output (void);
+void    qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
+void   	qh_check_points(void);
+void 	qh_checkconvex(facetT *facetlist, int fault);
+void    qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
+void 	qh_checkflipped_all (facetT *facetlist);
+void 	qh_checkpolygon(facetT *facetlist);
+void    qh_checkvertex (vertexT *vertex);
+void 	qh_clearcenters (qh_CENTER type);
+void 	qh_createsimplex(setT *vertices);
+void 	qh_delridge(ridgeT *ridge);
+void    qh_delvertex (vertexT *vertex);
+setT   *qh_facet3vertex (facetT *facet);
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside);
+facetT *qh_findbestlower (facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart);
+facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
+			  int *numpart);
+int 	qh_findgood (facetT *facetlist, int goodhorizon);
+void 	qh_findgood_all (facetT *facetlist);
+void    qh_furthestnext (void /* qh facet_list */);
+void    qh_furthestout (facetT *facet);
+void    qh_infiniteloop (facetT *facet);
+void 	qh_initbuild(void);
+void 	qh_initialhull(setT *vertices);
+setT   *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
+vertexT *qh_isvertex (pointT *point, setT *vertices);
+vertexT *qh_makenewfacets (pointT *point /*horizon_list, visible_list*/);
+void    qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount);
+void    qh_nearcoplanar ( void /* qh.facet_list */);
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
+int 	qh_newhashtable(int newsize);
+vertexT *qh_newvertex(pointT *point);
+ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp);
+void    qh_outcoplanar (void /* facet_list */);
+pointT *qh_point (int id);
+void 	qh_point_add (setT *set, pointT *point, void *elem);
+setT   *qh_pointfacet (void /*qh facet_list*/);
+setT   *qh_pointvertex (void /*qh facet_list*/);
+void 	qh_prependfacet(facetT *facet, facetT **facetlist);
+void	qh_printhashtable(FILE *fp);
+void    qh_printlists (void);
+void    qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/);
+void    qh_setvoronoi_all (void);
+void	qh_triangulate (void /*qh facet_list*/);
+void    qh_triangulate_facet (facetT *facetA, vertexT **first_vertex);
+void    qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
+void	qh_triangulate_mirror (facetT *facetA, facetT *facetB);
+void    qh_triangulate_null (facetT *facetA);
+void    qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
+setT   *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
+void    qh_vertexneighbors (void /*qh facet_list*/);
+boolT 	qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
+
+
+#endif /* qhDEFpoly */

Added: trunk/scipy/spatial/qhull/src/poly2.c
===================================================================
--- trunk/scipy/spatial/qhull/src/poly2.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/poly2.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,3137 @@
+/*
  ---------------------------------
+
+   poly2.c 
+   implements polygons and simplices
+
+   see qh-poly.htm, poly.h and qhull.h
+
+   frequently used code is in poly.c
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#include "qhull_a.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*---------------------------------
+  
+  qh_addhash( newelem, hashtable, hashsize, hash )
+    add newelem to linear hash table at hash if not already there
+*/
+void qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash) {
+  int scan;
+  void *elem;
+
+  for (scan= (int)hash; (elem= SETelem_(hashtable, scan)); 
+       scan= (++scan >= hashsize ? 0 : scan)) {
+    if (elem == newelem)
+      break;
+  }
+  /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
+  if (!elem)
+    SETelem_(hashtable, scan)= newelem;
+} /* addhash */
+
+/*---------------------------------
+  
+  qh_check_bestdist()
+    check that all points are within max_outside of the nearest facet
+    if qh.ONLYgood,
+      ignores !good facets
+
+  see: 
+    qh_check_maxout(), qh_outerinner()
+
+  notes:
+    only called from qh_check_points()
+      seldom used since qh.MERGING is almost always set
+    if notverified>0 at end of routine
+      some points were well inside the hull.  If the hull contains
+      a lens-shaped component, these points were not verified.  Use
+      options 'Qi Tv' to verify all points.  (Exhaustive check also verifies)
+
+  design:
+    determine facet for each point (if any)
+    for each point
+      start with the assigned facet or with the first facet
+      find the best facet for the point and check all coplanar facets
+      error if point is outside of facet
+*/
+void qh_check_bestdist (void) {
+  boolT waserror= False, unassigned;
+  facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
+  facetT *facetlist; 
+  realT dist, maxoutside, maxdist= -REALmax;
+  pointT *point;
+  int numpart= 0, facet_i, facet_n, notgood= 0, notverified= 0;
+  setT *facets;
+
+  trace1((qh ferr, "qh_check_bestdist: check points below nearest facet.  Facet_list f%d\n",
+      qh facet_list->id));
+  maxoutside= qh_maxouter();
+  maxoutside += qh DISTround;
+  /* one more qh.DISTround for check computation */
+  trace1((qh ferr, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
+  facets= qh_pointfacet (/*qh facet_list*/);
+  if (!qh_QUICKhelp && qh PRINTprecision)
+    fprintf (qh ferr, "\n\
+qhull output completed.  Verifying that %d points are\n\
+below %2.2g of the nearest %sfacet.\n",
+	     qh_setsize(facets), maxoutside, (qh ONLYgood ?  "good " : ""));
+  FOREACHfacet_i_(facets) {  /* for each point with facet assignment */
+    if (facet)
+      unassigned= False;
+    else {
+      unassigned= True;
+      facet= qh facet_list;
+    }
+    point= qh_point(facet_i);
+    if (point == qh GOODpointp)
+      continue;
+    qh_distplane(point, facet, &dist);
+    numpart++;
+    bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, facet, qh_NOupper, &dist, &numpart);
+    /* occurs after statistics reported */
+    maximize_(maxdist, dist);
+    if (dist > maxoutside) {
+      if (qh ONLYgood && !bestfacet->good 
+	  && !((bestfacet= qh_findgooddist (point, bestfacet, &dist, &facetlist))
+	       && dist > maxoutside))
+	notgood++;
+      else {
+	waserror= True;
+	fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n", 
+		facet_i, bestfacet->id, dist, maxoutside);
+	if (errfacet1 != bestfacet) {
+	  errfacet2= errfacet1;
+	  errfacet1= bestfacet;
+	}
+      }
+    }else if (unassigned && dist < -qh MAXcoplanar)
+      notverified++;
+  }
+  qh_settempfree (&facets);
+  if (notverified && !qh DELAUNAY && !qh_QUICKhelp && qh PRINTprecision) 
+    fprintf(qh ferr, "\n%d points were well inside the hull.  If the hull contains\n\
+a lens-shaped component, these points were not verified.  Use\n\
+options 'Qci Tv' to verify all points.\n", notverified); 
+  if (maxdist > qh outside_err) {
+    fprintf( qh ferr, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull.  The maximum value (qh.outside_err) is %6.2g\n",
+              maxdist, qh outside_err);
+    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+  }else if (waserror && qh outside_err > REALmax/2)
+    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+  else if (waserror)
+    ;                       /* the error was logged to qh.ferr but does not effect the output */
+  trace0((qh ferr, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
+} /* check_bestdist */
+
+/*---------------------------------
+  
+  qh_check_maxout()
+    updates qh.max_outside by checking all points against bestfacet
+    if qh.ONLYgood, ignores !good facets
+
+  returns:
+    updates facet->maxoutside via qh_findbesthorizon()
+    sets qh.maxoutdone
+    if printing qh.min_vertex (qh_outerinner), 
+      it is updated to the current vertices
+    removes inside/coplanar points from coplanarset as needed
+
+  notes:
+    defines coplanar as min_vertex instead of MAXcoplanar 
+    may not need to check near-inside points because of qh.MAXcoplanar 
+      and qh.KEEPnearinside (before it was -DISTround)
+
+  see also:
+    qh_check_bestdist()
+
+  design:
+    if qh.min_vertex is needed
+      for all neighbors of all vertices
+        test distance from vertex to neighbor
+    determine facet for each point (if any)
+    for each point with an assigned facet
+      find the best facet for the point and check all coplanar facets
+        (updates outer planes)
+    remove near-inside points from coplanar sets
+*/
+#ifndef qh_NOmerge
+void qh_check_maxout (void) {
+  facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist;
+  realT dist, maxoutside, minvertex, old_maxoutside;
+  pointT *point;
+  int numpart= 0, facet_i, facet_n, notgood= 0;
+  setT *facets, *vertices;
+  vertexT *vertex;
+
+  trace1((qh ferr, "qh_check_maxout: check and update maxoutside for each facet.\n"));
+  maxoutside= minvertex= 0;
+  if (qh VERTEXneighbors 
+  && (qh PRINTsummary || qh KEEPinside || qh KEEPcoplanar 
+	|| qh TRACElevel || qh PRINTstatistics
+	|| qh PRINTout[0] == qh_PRINTsummary || qh PRINTout[0] == qh_PRINTnone)) { 
+    trace1((qh ferr, "qh_check_maxout: determine actual maxoutside and minvertex\n"));
+    vertices= qh_pointvertex (/*qh facet_list*/);
+    FORALLvertices {
+      FOREACHneighbor_(vertex) {
+        zinc_(Zdistvertex);  /* distance also computed by main loop below */
+	qh_distplane (vertex->point, neighbor, &dist);
+	minimize_(minvertex, dist);
+	if (-dist > qh TRACEdist || dist > qh TRACEdist 
+	|| neighbor == qh tracefacet || vertex == qh tracevertex)
+	  fprintf (qh ferr, "qh_check_maxout: p%d (v%d) is %.2g from f%d\n",
+		    qh_pointid (vertex->point), vertex->id, dist, neighbor->id);
+      }
+    }
+    if (qh MERGING) {
+      wmin_(Wminvertex, qh min_vertex);
+    }
+    qh min_vertex= minvertex;
+    qh_settempfree (&vertices);  
+  }
+  facets= qh_pointfacet (/*qh facet_list*/);
+  do {
+    old_maxoutside= fmax_(qh max_outside, maxoutside);
+    FOREACHfacet_i_(facets) {     /* for each point with facet assignment */
+      if (facet) { 
+	point= qh_point(facet_i);
+	if (point == qh GOODpointp)
+	  continue;
+	zinc_(Ztotcheck);
+	qh_distplane(point, facet, &dist);
+	numpart++;
+	bestfacet= qh_findbesthorizon (qh_IScheckmax, point, facet, !qh_NOupper, &dist, &numpart);
+	if (bestfacet && dist > maxoutside) {
+	  if (qh ONLYgood && !bestfacet->good 
+	  && !((bestfacet= qh_findgooddist (point, bestfacet, &dist, &facetlist))
+	       && dist > maxoutside))
+	    notgood++;
+	  else
+	    maxoutside= dist;
+	}
+	if (dist > qh TRACEdist || (bestfacet && bestfacet == qh tracefacet))
+	  fprintf (qh ferr, "qh_check_maxout: p%d is %.2g above f%d\n",
+		     qh_pointid (point), dist, bestfacet->id);
+      }
+    }
+  }while 
+    (maxoutside > 2*old_maxoutside);
+    /* if qh.maxoutside increases substantially, qh_SEARCHdist is not valid 
+          e.g., RBOX 5000 s Z1 G1e-13 t1001200614 | qhull */
+  zzadd_(Zcheckpart, numpart);
+  qh_settempfree (&facets);
+  wval_(Wmaxout)= maxoutside - qh max_outside;
+  wmax_(Wmaxoutside, qh max_outside);
+  qh max_outside= maxoutside;
+  qh_nearcoplanar (/*qh.facet_list*/);
+  qh maxoutdone= True;
+  trace1((qh ferr, "qh_check_maxout: maxoutside %2.2g, min_vertex %2.2g, outside of not good %d\n",
+       maxoutside, qh min_vertex, notgood));
+} /* check_maxout */
+#else /* qh_NOmerge */
+void qh_check_maxout (void) {
+}
+#endif
+
+/*---------------------------------
+  
+  qh_check_output()
+    performs the checks at the end of qhull algorithm
+    Maybe called after voronoi output.  Will recompute otherwise centrums are Voronoi centers instead
+*/
+void qh_check_output (void) {
+  int i;
+
+  if (qh STOPcone)
+    return;
+  if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
+    qh_checkpolygon (qh facet_list);
+    qh_checkflipped_all (qh facet_list);
+    qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
+  }else if (!qh MERGING && qh_newstats (qhstat precision, &i)) {
+    qh_checkflipped_all (qh facet_list);
+    qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
+  }
+} /* check_output */
+
+
+
+/*---------------------------------
+  
+  qh_check_point( point, facet, maxoutside, maxdist, errfacet1, errfacet2 )
+    check that point is less than maxoutside from facet
+*/
+void qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2) {
+  realT dist;
+
+  /* occurs after statistics reported */
+  qh_distplane(point, facet, &dist);
+  if (dist > *maxoutside) {
+    if (*errfacet1 != facet) {
+      *errfacet2= *errfacet1;
+      *errfacet1= facet;
+    }
+    fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n", 
+	      qh_pointid(point), facet->id, dist, *maxoutside);
+  }
+  maximize_(*maxdist, dist);
+} /* qh_check_point */
+
+
+/*---------------------------------
+  
+  qh_check_points()
+    checks that all points are inside all facets
+
+  notes:
+    if many points and qh_check_maxout not called (i.e., !qh.MERGING), 
+       calls qh_findbesthorizon (seldom done).
+    ignores flipped facets
+    maxoutside includes 2 qh.DISTrounds
+      one qh.DISTround for the computed distances in qh_check_points
+    qh_printafacet and qh_printsummary needs only one qh.DISTround
+    the computation for qh.VERIFYdirect does not account for qh.other_points
+
+  design:
+    if many points
+      use qh_check_bestdist()
+    else
+      for all facets
+        for all points
+          check that point is inside facet
+*/
+void qh_check_points (void) {
+  facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
+  realT total, maxoutside, maxdist= -REALmax;
+  pointT *point, **pointp, *pointtemp;
+  boolT testouter;
+
+  maxoutside= qh_maxouter();
+  maxoutside += qh DISTround;
+  /* one more qh.DISTround for check computation */
+  trace1((qh ferr, "qh_check_points: check all points below %2.2g of all facet planes\n",
+	  maxoutside));
+  if (qh num_good)   /* miss counts other_points and !good facets */
+     total= (float) qh num_good * qh num_points;
+  else
+     total= (float) qh num_facets * qh num_points;
+  if (total >= qh_VERIFYdirect && !qh maxoutdone) {
+    if (!qh_QUICKhelp && qh SKIPcheckmax && qh MERGING)
+      fprintf (qh ferr, "\n\
+qhull input warning: merging without checking outer planes ('Q5' or 'Po').\n\
+Verify may report that a point is outside of a facet.\n");
+    qh_check_bestdist();
+  }else {
+    if (qh_MAXoutside && qh maxoutdone)
+      testouter= True;
+    else
+      testouter= False;
+    if (!qh_QUICKhelp) {
+      if (qh MERGEexact)
+	fprintf (qh ferr, "\n\
+qhull input warning: exact merge ('Qx').  Verify may report that a point\n\
+is outside of a facet.  See qh-optq.htm#Qx\n");
+      else if (qh SKIPcheckmax || qh NOnearinside)
+	fprintf (qh ferr, "\n\
+qhull input warning: no outer plane check ('Q5') or no processing of\n\
+near-inside points ('Q8').  Verify may report that a point is outside\n\
+of a facet.\n");
+    }
+    if (qh PRINTprecision) {
+      if (testouter)
+	fprintf (qh ferr, "\n\
+Output completed.  Verifying that all points are below outer planes of\n\
+all %sfacets.  Will make %2.0f distance computations.\n", 
+	      (qh ONLYgood ?  "good " : ""), total);
+      else
+	fprintf (qh ferr, "\n\
+Output completed.  Verifying that all points are below %2.2g of\n\
+all %sfacets.  Will make %2.0f distance computations.\n", 
+	      maxoutside, (qh ONLYgood ?  "good " : ""), total);
+    }
+    FORALLfacets {
+      if (!facet->good && qh ONLYgood)
+        continue;
+      if (facet->flipped)
+        continue;
+      if (!facet->normal) {
+	fprintf( qh ferr, "qhull warning (qh_check_points): missing normal for facet f%d\n", facet->id);
+        continue;
+      }
+      if (testouter) {
+#if qh_MAXoutside
+	maxoutside= facet->maxoutside + 2* qh DISTround;
+	/* one DISTround to actual point and another to computed point */
+#endif
+      }
+      FORALLpoints {
+	if (point != qh GOODpointp)
+	  qh_check_point (point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
+      }
+      FOREACHpoint_(qh other_points) {
+	if (point != qh GOODpointp)
+	  qh_check_point (point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
+      }
+    }
+    if (maxdist > qh outside_err) {
+      fprintf( qh ferr, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull.  The maximum value (qh.outside_err) is %6.2g\n",
+                maxdist, qh outside_err );
+      qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
+    }else if (errfacet1 && qh outside_err > REALmax/2)
+        qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
+    else if (errfacet1)
+        ;  /* the error was logged to qh.ferr but does not effect the output */
+    trace0((qh ferr, "qh_check_points: max distance outside %2.2g\n", maxdist));
+  }
+} /* check_points */
+
+
+/*---------------------------------
+  
+  qh_checkconvex( facetlist, fault )
+    check that each ridge in facetlist is convex
+    fault = qh_DATAfault if reporting errors
+          = qh_ALGORITHMfault otherwise
+
+  returns:
+    counts Zconcaveridges and Zcoplanarridges
+    errors if concaveridge or if merging an coplanar ridge
+
+  note:
+    if not merging, 
+      tests vertices for neighboring simplicial facets
+    else if ZEROcentrum, 
+      tests vertices for neighboring simplicial   facets
+    else 
+      tests centrums of neighboring facets
+
+  design:
+    for all facets
+      report flipped facets
+      if ZEROcentrum and simplicial neighbors
+        test vertices for neighboring simplicial facets
+      else
+        test centrum against all neighbors 
+*/
+void qh_checkconvex(facetT *facetlist, int fault) {
+  facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
+  vertexT *vertex;
+  realT dist;
+  pointT *centrum;
+  boolT waserror= False, centrum_warning= False, tempcentrum= False, allsimplicial;
+  int neighbor_i;
+
+  trace1((qh ferr, "qh_checkconvex: check all ridges are convex\n"));
+  if (!qh RERUN) {
+    zzval_(Zconcaveridges)= 0;
+    zzval_(Zcoplanarridges)= 0;
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->flipped) {
+      qh_precision ("flipped facet");
+      fprintf (qh ferr, "qhull precision error: f%d is flipped (interior point is outside)\n",
+	       facet->id);
+      errfacet1= facet;
+      waserror= True;
+      continue;
+    }
+    if (qh MERGING && (!qh ZEROcentrum || !facet->simplicial || facet->tricoplanar))
+      allsimplicial= False;
+    else {
+      allsimplicial= True;
+      neighbor_i= 0;
+      FOREACHneighbor_(facet) {
+        vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
+	if (!neighbor->simplicial || neighbor->tricoplanar) {
+	  allsimplicial= False;
+	  continue;
+	}
+        qh_distplane (vertex->point, neighbor, &dist);
+        if (dist > -qh DISTround) {
+	  if (fault == qh_DATAfault) {
+            qh_precision ("coplanar or concave ridge");
+	    fprintf (qh ferr, "qhull precision error: initial simplex is not convex. Distance=%.2g\n", dist);
+	    qh_errexit(qh_ERRsingular, NULL, NULL);
+	  }
+          if (dist > qh DISTround) {
+            zzinc_(Zconcaveridges);
+            qh_precision ("concave ridge");
+            fprintf (qh ferr, "qhull precision error: f%d is concave to f%d, since p%d (v%d) is %6.4g above\n",
+              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
+            errfacet1= facet;
+            errfacet2= neighbor;
+            waserror= True;
+          }else if (qh ZEROcentrum) {
+            if (dist > 0) {     /* qh_checkzero checks that dist < - qh DISTround */
+              zzinc_(Zcoplanarridges); 
+              qh_precision ("coplanar ridge");
+              fprintf (qh ferr, "qhull precision error: f%d is clearly not convex to f%d, since p%d (v%d) is %6.4g above\n",
+                facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
+              errfacet1= facet;
+              errfacet2= neighbor;
+              waserror= True;
+	    }
+	  }else {              
+            zzinc_(Zcoplanarridges);
+            qh_precision ("coplanar ridge");
+            trace0((qh ferr, "qhull precision error: f%d may be coplanar to f%d, since p%d (v%d) is within %6.4g during p%d\n",
+              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist, qh furthest_id));
+          }
+        }
+      }
+    }
+    if (!allsimplicial) {
+      if (qh CENTERtype == qh_AScentrum) {
+        if (!facet->center)
+          facet->center= qh_getcentrum (facet);
+        centrum= facet->center;
+      }else {
+	if (!centrum_warning && (!facet->simplicial || facet->tricoplanar)) {
+	   centrum_warning= True;
+	   fprintf (qh ferr, "qhull note: recomputing centrums for convexity test.  This may lead to false, precision errors.\n");
+	}
+        centrum= qh_getcentrum(facet);
+        tempcentrum= True;
+      }
+      FOREACHneighbor_(facet) {
+	if (qh ZEROcentrum && facet->simplicial && neighbor->simplicial)
+	  continue;
+	if (facet->tricoplanar || neighbor->tricoplanar)
+	  continue;
+        zzinc_(Zdistconvex);
+        qh_distplane (centrum, neighbor, &dist);
+        if (dist > qh DISTround) {
+          zzinc_(Zconcaveridges);
+          qh_precision ("concave ridge");
+          fprintf (qh ferr, "qhull precision error: f%d is concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
+            facet->id, neighbor->id, facet->id, dist, neighbor->id);
+          errfacet1= facet;
+          errfacet2= neighbor;
+          waserror= True;
+	}else if (dist >= 0.0) {   /* if arithmetic always rounds the same,
+				     can test against centrum radius instead */
+          zzinc_(Zcoplanarridges);
+          qh_precision ("coplanar ridge");
+          fprintf (qh ferr, "qhull precision error: f%d is coplanar or concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
+            facet->id, neighbor->id, facet->id, dist, neighbor->id);
+	  errfacet1= facet;
+	  errfacet2= neighbor;
+	  waserror= True;
+        }
+      }
+      if (tempcentrum)
+        qh_memfree(centrum, qh normal_size);
+    }
+  }
+  if (waserror && !qh FORCEoutput)
+    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+} /* checkconvex */
+
+
+/*---------------------------------
+  
+  qh_checkfacet( facet, newmerge, waserror )
+    checks for consistency errors in facet
+    newmerge set if from merge.c
+
+  returns:
+    sets waserror if any error occurs
+
+  checks:
+    vertex ids are inverse sorted
+    unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
+    if non-simplicial, at least as many ridges as neighbors
+    neighbors are not duplicated
+    ridges are not duplicated
+    in 3-d, ridges=verticies
+    (qh.hull_dim-1) ridge vertices
+    neighbors are reciprocated
+    ridge neighbors are facet neighbors and a ridge for every neighbor
+    simplicial neighbors match facetintersect
+    vertex intersection matches vertices of common ridges 
+    vertex neighbors and facet vertices agree
+    all ridges have distinct vertex sets
+
+  notes:  
+    uses neighbor->seen
+
+  design:
+    check sets
+    check vertices
+    check sizes of neighbors and vertices
+    check for qh_MERGEridge and qh_DUPLICATEridge flags
+    check neighbor set
+    check ridge set
+    check ridges, neighbors, and vertices
+*/
+void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
+  facetT *neighbor, **neighborp, *errother=NULL;
+  ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
+  vertexT *vertex, **vertexp;
+  unsigned previousid= INT_MAX;
+  int numneighbors, numvertices, numridges=0, numRvertices=0;
+  boolT waserror= False;
+  int skipA, skipB, ridge_i, ridge_n, i;
+  setT *intersection;
+
+  if (facet->visible) {
+    fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d is on the visible_list\n",
+      facet->id);
+    qh_errexit (qh_ERRqhull, facet, NULL);
+  }
+  if (!facet->normal) {
+    fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d does not have  a normal\n",
+      facet->id);
+    waserror= True;
+  }
+  qh_setcheck (facet->vertices, "vertices for f", facet->id);
+  qh_setcheck (facet->ridges, "ridges for f", facet->id);
+  qh_setcheck (facet->outsideset, "outsideset for f", facet->id);
+  qh_setcheck (facet->coplanarset, "coplanarset for f", facet->id);
+  qh_setcheck (facet->neighbors, "neighbors for f", facet->id);
+  FOREACHvertex_(facet->vertices) {
+    if (vertex->deleted) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
+      qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
+      waserror= True;
+    }
+    if (vertex->id >= previousid) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
+      waserror= True;
+      break;
+    }
+    previousid= vertex->id;
+  }
+  numneighbors= qh_setsize(facet->neighbors);
+  numvertices= qh_setsize(facet->vertices);
+  numridges= qh_setsize(facet->ridges);
+  if (facet->simplicial) {
+    if (numvertices+numneighbors != 2*qh hull_dim 
+    && !facet->degenerate && !facet->redundant) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n", 
+                facet->id, numvertices, numneighbors);
+      qh_setprint (qh ferr, "", facet->neighbors);
+      waserror= True;
+    }
+  }else { /* non-simplicial */
+    if (!newmerge 
+    &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
+    && !facet->degenerate && !facet->redundant) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
+         facet->id, numvertices, numneighbors);
+       waserror= True;
+    }
+    /* in 3-d, can get a vertex twice in an edge list, e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv TP624 TW1e-13 T4 */
+    if (numridges < numneighbors
+    ||(qh hull_dim == 3 && numvertices > numridges && !qh NEWfacets)
+    ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
+      if (!facet->degenerate && !facet->redundant) {
+	fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or (3-d) > #vertices %d or (2-d) not all 2\n",
+	    facet->id, numridges, numneighbors, numvertices);
+	waserror= True;
+      }
+    }
+  }
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d still has a MERGE or DUP neighbor\n", facet->id);
+      qh_errexit (qh_ERRqhull, facet, NULL);
+    }
+    neighbor->seen= True;
+  }
+  FOREACHneighbor_(facet) {
+    if (!qh_setin(neighbor->neighbors, facet)) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
+	      facet->id, neighbor->id, neighbor->id, facet->id);
+      errother= neighbor;
+      waserror= True;
+    }
+    if (!neighbor->seen) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
+	      facet->id, neighbor->id);
+      errother= neighbor;
+      waserror= True;
+    }    
+    neighbor->seen= False;
+  }
+  FOREACHridge_(facet->ridges) {
+    qh_setcheck (ridge->vertices, "vertices for r", ridge->id);
+    ridge->seen= False;
+  }
+  FOREACHridge_(facet->ridges) {
+    if (ridge->seen) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
+	      facet->id, ridge->id);
+      errridge= ridge;
+      waserror= True;
+    }    
+    ridge->seen= True;
+    numRvertices= qh_setsize(ridge->vertices);
+    if (numRvertices != qh hull_dim - 1) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n", 
+                ridge->top->id, ridge->bottom->id, numRvertices);
+      errridge= ridge;
+      waserror= True;
+    }
+    neighbor= otherfacet_(ridge, facet);
+    neighbor->seen= True;
+    if (!qh_setin(facet->neighbors, neighbor)) {
+      fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
+           facet->id, neighbor->id, ridge->id);
+      errridge= ridge;
+      waserror= True;
+    }
+  }
+  if (!facet->simplicial) {
+    FOREACHneighbor_(facet) {
+      if (!neighbor->seen) {
+        fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
+	      facet->id, neighbor->id);
+	errother= neighbor;
+        waserror= True;
+      }
+      intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
+      qh_settemppush (intersection);
+      FOREACHvertex_(facet->vertices) {
+	vertex->seen= False;
+	vertex->seen2= False;
+      }
+      FOREACHvertex_(intersection)
+	vertex->seen= True;
+      FOREACHridge_(facet->ridges) {
+	if (neighbor != otherfacet_(ridge, facet))
+	    continue;
+	FOREACHvertex_(ridge->vertices) {
+	  if (!vertex->seen) {
+	    fprintf (qh ferr, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
+  	          vertex->id, ridge->id, facet->id, neighbor->id);
+	    qh_errexit (qh_ERRqhull, facet, ridge);
+	  }
+	  vertex->seen2= True;
+	}
+      }
+      if (!newmerge) {
+	FOREACHvertex_(intersection) {
+	  if (!vertex->seen2) {
+	    if (qh IStracing >=3 || !qh MERGING) {
+	      fprintf (qh ferr, "qhull precision error (qh_checkfacet): vertex v%d in f%d intersect f%d but\n\
+ not in a ridge.  This is ok under merging.  Last point was p%d\n",
+		     vertex->id, facet->id, neighbor->id, qh furthest_id);
+	      if (!qh FORCEoutput && !qh MERGING) {
+		qh_errprint ("ERRONEOUS", facet, neighbor, NULL, vertex);
+		if (!qh MERGING)
+		  qh_errexit (qh_ERRqhull, NULL, NULL);
+	      }
+	    }
+	  }
+	}
+      }      
+      qh_settempfree (&intersection);
+    }
+  }else { /* simplicial */
+    FOREACHneighbor_(facet) {
+      if (neighbor->simplicial) {    
+	skipA= SETindex_(facet->neighbors, neighbor);
+	skipB= qh_setindex (neighbor->neighbors, facet);
+	if (!qh_setequal_skip (facet->vertices, skipA, neighbor->vertices, skipB)) {
+	  fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
+		   facet->id, skipA, neighbor->id, skipB);
+	  errother= neighbor;
+	  waserror= True;
+	}
+      }
+    }
+  }
+  if (qh hull_dim < 5 && (qh IStracing > 2 || qh CHECKfrequently)) {
+    FOREACHridge_i_(facet->ridges) {           /* expensive */
+      for (i= ridge_i+1; i < ridge_n; i++) {
+	ridge2= SETelemt_(facet->ridges, i, ridgeT);
+	if (qh_setequal (ridge->vertices, ridge2->vertices)) {
+	  fprintf (qh ferr, "qh_checkfacet: ridges r%d and r%d have the same vertices\n",
+		  ridge->id, ridge2->id);
+	  errridge= ridge;
+	  waserror= True;
+	}
+      }
+    }
+  }
+  if (waserror) {
+    qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
+    *waserrorp= True;
+  }
+} /* checkfacet */
+
+
+/*---------------------------------
+  
+  qh_checkflipped_all( facetlist )
+    checks orientation of facets in list against interior point
+*/
+void qh_checkflipped_all (facetT *facetlist) {
+  facetT *facet;
+  boolT waserror= False;
+  realT dist;
+
+  if (facetlist == qh facet_list)
+    zzval_(Zflippedfacets)= 0;
+  FORALLfacet_(facetlist) {
+    if (facet->normal && !qh_checkflipped (facet, &dist, !qh_ALL)) {
+      fprintf(qh ferr, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
+	      facet->id, dist);
+      if (!qh FORCEoutput) {
+	qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
+	waserror= True;
+      }
+    }
+  }
+  if (waserror) {
+    fprintf (qh ferr, "\n\
+A flipped facet occurs when its distance to the interior point is\n\
+greater than %2.2g, the maximum roundoff error.\n", -qh DISTround);
+    qh_errexit(qh_ERRprec, NULL, NULL);
+  }
+} /* checkflipped_all */
+
+/*---------------------------------
+  
+  qh_checkpolygon( facetlist )
+    checks the correctness of the structure
+
+  notes:
+    call with either qh.facet_list or qh.newfacet_list
+    checks num_facets and num_vertices if qh.facet_list
+
+  design:
+    for each facet
+      checks facet and outside set
+    initializes vertexlist
+    for each facet
+      checks vertex set
+    if checking all facets (qh.facetlist)
+      check facet count
+      if qh.VERTEXneighbors
+        check vertex neighbors and count
+      check vertex count
+*/
+void qh_checkpolygon(facetT *facetlist) {
+  facetT *facet;
+  vertexT *vertex, **vertexp, *vertexlist;
+  int numfacets= 0, numvertices= 0, numridges= 0;
+  int totvneighbors= 0, totvertices= 0;
+  boolT waserror= False, nextseen= False, visibleseen= False;
+  
+  trace1((qh ferr, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
+  if (facetlist != qh facet_list || qh ONLYgood)
+    nextseen= True;
+  FORALLfacet_(facetlist) {
+    if (facet == qh visible_list)
+      visibleseen= True;
+    if (!facet->visible) {
+      if (!nextseen) {
+	if (facet == qh facet_next)
+	  nextseen= True;
+	else if (qh_setsize (facet->outsideset)) {
+	  if (!qh NARROWhull
+#if !qh_COMPUTEfurthest
+	       || facet->furthestdist >= qh MINoutside
+#endif
+			) {
+	    fprintf (qh ferr, "qhull internal error (qh_checkpolygon): f%d has outside points before qh facet_next\n",
+		     facet->id);
+	    qh_errexit (qh_ERRqhull, facet, NULL);
+	  }
+	}
+      }
+      numfacets++;
+      qh_checkfacet(facet, False, &waserror);
+    }
+  }
+  if (qh visible_list && !visibleseen && facetlist == qh facet_list) {
+    fprintf (qh ferr, "qhull internal error (qh_checkpolygon): visible list f%d no longer on facet list\n", qh visible_list->id);
+    qh_printlists();
+    qh_errexit (qh_ERRqhull, qh visible_list, NULL);
+  }
+  if (facetlist == qh facet_list)
+    vertexlist= qh vertex_list;
+  else if (facetlist == qh newfacet_list)
+    vertexlist= qh newvertex_list;
+  else
+    vertexlist= NULL;
+  FORALLvertex_(vertexlist) {
+    vertex->seen= False;
+    vertex->visitid= 0;
+  }  
+  FORALLfacet_(facetlist) {
+    if (facet->visible)
+      continue;
+    if (facet->simplicial)
+      numridges += qh hull_dim;
+    else
+      numridges += qh_setsize (facet->ridges);
+    FOREACHvertex_(facet->vertices) {
+      vertex->visitid++;
+      if (!vertex->seen) {
+	vertex->seen= True;
+	numvertices++;
+	if (qh_pointid (vertex->point) == -1) {
+	  fprintf (qh ferr, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
+		   vertex->point, vertex->id, qh first_point);
+	  waserror= True;
+	}
+      }
+    }
+  }
+  qh vertex_visit += numfacets;
+  if (facetlist == qh facet_list) {
+    if (numfacets != qh num_facets - qh num_visible) {
+      fprintf(qh ferr, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d - %d visible facets\n",
+	      numfacets, qh num_facets, qh num_visible);
+      waserror= True;
+    }
+    qh vertex_visit++;
+    if (qh VERTEXneighbors) {
+      FORALLvertices {
+	qh_setcheck (vertex->neighbors, "neighbors for v", vertex->id);
+	if (vertex->deleted)
+	  continue;
+	totvneighbors += qh_setsize (vertex->neighbors);
+      }
+      FORALLfacet_(facetlist)
+	totvertices += qh_setsize (facet->vertices);
+      if (totvneighbors != totvertices) {
+	fprintf(qh ferr, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent.  Totvneighbors %d, totvertices %d\n",
+		totvneighbors, totvertices);
+	waserror= True;
+      }
+    }
+    if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
+      fprintf(qh ferr, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
+	      numvertices, qh num_vertices - qh_setsize(qh del_vertices));
+      waserror= True;
+    }
+    if (qh hull_dim == 2 && numvertices != numfacets) {
+      fprintf (qh ferr, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
+        numvertices, numfacets);
+      waserror= True;
+    }
+    if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
+      fprintf (qh ferr, "qhull warning: #vertices %d + #facets %d - #edges %d != 2\n\
+	A vertex appears twice in a edge list.  May occur during merging.",
+        numvertices, numfacets, numridges/2);
+      /* occurs if lots of merging and a vertex ends up twice in an edge list.  e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv */
+    }
+  }
+  if (waserror) 
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+} /* checkpolygon */
+
+
+/*---------------------------------
+  
+  qh_checkvertex( vertex )
+    check vertex for consistency
+    checks vertex->neighbors
+
+  notes:
+    neighbors checked efficiently in checkpolygon
+*/
+void qh_checkvertex (vertexT *vertex) {
+  boolT waserror= False;
+  facetT *neighbor, **neighborp, *errfacet=NULL;
+
+  if (qh_pointid (vertex->point) == -1) {
+    fprintf (qh ferr, "qhull internal error (qh_checkvertex): unknown point id %p\n", vertex->point);
+    waserror= True;
+  }
+  if (vertex->id >= qh vertex_id) {
+    fprintf (qh ferr, "qhull internal error (qh_checkvertex): unknown vertex id %d\n", vertex->id);
+    waserror= True;
+  }
+  if (!waserror && !vertex->deleted) {
+    if (qh_setsize (vertex->neighbors)) {
+      FOREACHneighbor_(vertex) {
+        if (!qh_setin (neighbor->vertices, vertex)) {
+          fprintf (qh ferr, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
+	  errfacet= neighbor;
+	  waserror= True;
+	}
+      }
+    }
+  }
+  if (waserror) {
+    qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
+    qh_errexit (qh_ERRqhull, errfacet, NULL);
+  }
+} /* checkvertex */
+  
+/*---------------------------------
+  
+  qh_clearcenters( type )
+    clear old data from facet->center
+
+  notes:
+    sets new centertype
+    nop if CENTERtype is the same
+*/
+void qh_clearcenters (qh_CENTER type) {
+  facetT *facet;
+  
+  if (qh CENTERtype != type) {
+    FORALLfacets {
+      if (qh CENTERtype == qh_ASvoronoi){
+        if (facet->center) {
+          qh_memfree (facet->center, qh center_size);
+          facet->center= NULL;
+        }
+      }else /* qh CENTERtype == qh_AScentrum */ {
+        if (facet->center) {
+          qh_memfree (facet->center, qh normal_size);
+	  facet->center= NULL;
+        }
+      }
+    }
+    qh CENTERtype= type;
+  }
+  trace2((qh ferr, "qh_clearcenters: switched to center type %d\n", type));
+} /* clearcenters */
+
+/*---------------------------------
+  
+  qh_createsimplex( vertices )
+    creates a simplex from a set of vertices
+
+  returns:
+    initializes qh.facet_list to the simplex
+    initializes qh.newfacet_list, .facet_tail
+    initializes qh.vertex_list, .newvertex_list, .vertex_tail
+
+  design:
+    initializes lists
+    for each vertex
+      create a new facet
+    for each new facet
+      create its neighbor set
+*/
+void qh_createsimplex(setT *vertices) {
+  facetT *facet= NULL, *newfacet;
+  boolT toporient= True;
+  int vertex_i, vertex_n, nth;
+  setT *newfacets= qh_settemp (qh hull_dim+1);
+  vertexT *vertex;
+  
+  qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
+  qh num_facets= qh num_vertices= qh num_visible= 0;
+  qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
+  FOREACHvertex_i_(vertices) {
+    newfacet= qh_newfacet();
+    newfacet->vertices= qh_setnew_delnthsorted (vertices, vertex_n,
+						vertex_i, 0);
+    newfacet->toporient= toporient;
+    qh_appendfacet(newfacet);
+    newfacet->newfacet= True;
+    qh_appendvertex (vertex);
+    qh_setappend (&newfacets, newfacet);
+    toporient ^= True;
+  }
+  FORALLnew_facets {
+    nth= 0;
+    FORALLfacet_(qh newfacet_list) {
+      if (facet != newfacet) 
+        SETelem_(newfacet->neighbors, nth++)= facet;
+    }
+    qh_settruncate (newfacet->neighbors, qh hull_dim);
+  }
+  qh_settempfree (&newfacets);
+  trace1((qh ferr, "qh_createsimplex: created simplex\n"));
+} /* createsimplex */
+
+/*---------------------------------
+  
+  qh_delridge( ridge )
+    deletes ridge from data structures it belongs to
+    frees up its memory
+
+  notes:
+    in merge.c, caller sets vertex->delridge for each vertex
+    ridges also freed in qh_freeqhull
+*/
+void qh_delridge(ridgeT *ridge) {
+  void **freelistp; /* used !qh_NOmem */
+  
+  qh_setdel(ridge->top->ridges, ridge);
+  qh_setdel(ridge->bottom->ridges, ridge);
+  qh_setfree(&(ridge->vertices));
+  qh_memfree_(ridge, sizeof(ridgeT), freelistp);
+} /* delridge */
+
+
+/*---------------------------------
+  
+  qh_delvertex( vertex )
+    deletes a vertex and frees its memory
+
+  notes:
+    assumes vertex->adjacencies have been updated if needed
+    unlinks from vertex_list
+*/
+void qh_delvertex (vertexT *vertex) {
+
+  if (vertex == qh tracevertex)
+    qh tracevertex= NULL;
+  qh_removevertex (vertex);
+  qh_setfree (&vertex->neighbors);
+  qh_memfree(vertex, sizeof(vertexT));
+} /* delvertex */
+
+
+/*---------------------------------
+  
+  qh_facet3vertex(  )
+    return temporary set of 3-d vertices in qh_ORIENTclock order
+
+  design:
+    if simplicial facet
+      build set from facet->vertices with facet->toporient
+    else
+      for each ridge in order
+        build set from ridge's vertices
+*/
+setT *qh_facet3vertex (facetT *facet) {
+  ridgeT *ridge, *firstridge;
+  vertexT *vertex;
+  int cntvertices, cntprojected=0;
+  setT *vertices;
+
+  cntvertices= qh_setsize(facet->vertices);
+  vertices= qh_settemp (cntvertices);
+  if (facet->simplicial) {
+    if (cntvertices != 3) {
+      fprintf (qh ferr, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n", 
+                  cntvertices, facet->id);
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+    qh_setappend (&vertices, SETfirst_(facet->vertices));
+    if (facet->toporient ^ qh_ORIENTclock)
+      qh_setappend (&vertices, SETsecond_(facet->vertices));
+    else
+      qh_setaddnth (&vertices, 0, SETsecond_(facet->vertices));
+    qh_setappend (&vertices, SETelem_(facet->vertices, 2));
+  }else {
+    ridge= firstridge= SETfirstt_(facet->ridges, ridgeT);   /* no infinite */
+    while ((ridge= qh_nextridge3d (ridge, facet, &vertex))) {
+      qh_setappend (&vertices, vertex);
+      if (++cntprojected > cntvertices || ridge == firstridge)
+        break;
+    }
+    if (!ridge || cntprojected != cntvertices) {
+      fprintf (qh ferr, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up.  got at least %d\n", 
+                  facet->id, cntprojected);
+      qh_errexit(qh_ERRqhull, facet, ridge);
+    }
+  }
+  return vertices;
+} /* facet3vertex */
+
+/*---------------------------------
+  
+  qh_findbestfacet( point, bestoutside, bestdist, isoutside )
+    find facet that is furthest below a point 
+
+    for Delaunay triangulations, 
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates. 
+
+  returns:
+    if bestoutside is set (e.g., qh_ALL)
+      returns best facet that is not upperdelaunay
+      if Delaunay and inside, point is outside circumsphere of bestfacet
+    else
+      returns first facet below point
+      if point is inside, returns nearest, !upperdelaunay facet
+    distance to facet
+    isoutside set if outside of facet
+    
+  notes:
+    For tricoplanar facets, this finds one of the tricoplanar facets closest 
+    to the point.  For Delaunay triangulations, the point may be inside a 
+    different tricoplanar facet. See locate a facet with qh_findbestfacet()
+    
+    If inside, qh_findbestfacet performs an exhaustive search
+       this may be too conservative.  Sometimes it is clearly required.
+
+    qh_findbestfacet is not used by qhull.
+    uses qh.visit_id and qh.coplanarset
+    
+  see:
+    qh_findbest
+*/
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside) {
+  facetT *bestfacet= NULL;
+  int numpart, totpart= 0;
+  
+  bestfacet= qh_findbest (point, qh facet_list, 
+			    bestoutside, !qh_ISnewfacets, bestoutside /* qh_NOupper */,
+			    bestdist, isoutside, &totpart);
+  if (*bestdist < -qh DISTround) {
+    bestfacet= qh_findfacet_all (point, bestdist, isoutside, &numpart);
+    totpart += numpart;
+    if ((isoutside && bestoutside)
+    || (!isoutside && bestfacet->upperdelaunay)) {
+      bestfacet= qh_findbest (point, bestfacet, 
+			    bestoutside, False, bestoutside,
+			    bestdist, isoutside, &totpart);
+      totpart += numpart;
+    }
+  }
+  trace3((qh ferr, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
+	  bestfacet->id, *bestdist, *isoutside, totpart));
+  return bestfacet;
+} /* findbestfacet */ 
+
+/*---------------------------------
+  
+  qh_findbestlower( facet, point, bestdist, numpart )
+    returns best non-upper, non-flipped neighbor of facet for point
+    if needed, searches vertex neighbors 
+
+  returns:
+    returns bestdist and updates numpart
+
+  notes:
+    if Delaunay and inside, point is outside of circumsphere of bestfacet
+    called by qh_findbest() for points above an upperdelaunay facet
+
+*/
+facetT *qh_findbestlower (facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart) {
+  facetT *neighbor, **neighborp, *bestfacet= NULL;
+  realT bestdist= -REALmax/2 /* avoid underflow */;
+  realT dist;
+  vertexT *vertex;
+
+  zinc_(Zbestlower);
+  FOREACHneighbor_(upperfacet) {
+    if (neighbor->upperdelaunay || neighbor->flipped)
+      continue;
+    (*numpart)++;
+    qh_distplane (point, neighbor, &dist);
+    if (dist > bestdist) {
+      bestfacet= neighbor;
+      bestdist= dist;
+    }
+  }
+  if (!bestfacet) {
+    zinc_(Zbestlowerv);
+    /* rarely called, numpart does not count nearvertex computations */
+    vertex= qh_nearvertex (upperfacet, point, &dist);
+    qh_vertexneighbors();
+    FOREACHneighbor_(vertex) {
+      if (neighbor->upperdelaunay || neighbor->flipped)
+	continue;
+      (*numpart)++;
+      qh_distplane (point, neighbor, &dist);
+      if (dist > bestdist) {
+	bestfacet= neighbor;
+	bestdist= dist;
+      }
+    }
+  }
+  if (!bestfacet) {
+    fprintf(qh ferr, "\n\
+qh_findbestlower: all neighbors of facet %d are flipped or upper Delaunay.\n\
+Please report this error to qhull_bug at qhull.org with the input and all of the output.\n",
+       upperfacet->id);
+    qh_errexit (qh_ERRqhull, upperfacet, NULL);
+  }
+  *bestdistp= bestdist;
+  trace3((qh ferr, "qh_findbestlower: f%d dist %2.2g for f%d p%d\n",
+	  bestfacet->id, bestdist, upperfacet->id, qh_pointid(point)));
+  return bestfacet;
+} /* findbestlower */
+
+/*---------------------------------
+  
+  qh_findfacet_all( point, bestdist, isoutside, numpart )
+    exhaustive search for facet below a point 
+
+    for Delaunay triangulations, 
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates. 
+
+  returns:
+    returns first facet below point
+    if point is inside, 
+      returns nearest facet
+    distance to facet
+    isoutside if point is outside of the hull
+    number of distance tests
+*/
+facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
+			  int *numpart) {
+  facetT *bestfacet= NULL, *facet;
+  realT dist;
+  int totpart= 0;
+  
+  *bestdist= REALmin;
+  *isoutside= False;
+  FORALLfacets {
+    if (facet->flipped || !facet->normal)
+      continue;
+    totpart++;
+    qh_distplane (point, facet, &dist);
+    if (dist > *bestdist) {
+      *bestdist= dist;
+      bestfacet= facet;
+      if (dist > qh MINoutside) {
+        *isoutside= True;
+        break;
+      }
+    }
+  }
+  *numpart= totpart;
+  trace3((qh ferr, "qh_findfacet_all: f%d dist %2.2g isoutside %d totpart %d\n",
+	  getid_(bestfacet), *bestdist, *isoutside, totpart));
+  return bestfacet;
+} /* findfacet_all */ 
+ 
+/*---------------------------------
+  
+  qh_findgood( facetlist, goodhorizon )
+    identify good facets for qh.PRINTgood
+    if qh.GOODvertex>0
+      facet includes point as vertex
+      if !match, returns goodhorizon
+      inactive if qh.MERGING
+    if qh.GOODpoint
+      facet is visible or coplanar (>0) or not visible (<0) 
+    if qh.GOODthreshold
+      facet->normal matches threshold
+    if !goodhorizon and !match, 
+      selects facet with closest angle
+      sets GOODclosest
+      
+  returns:
+    number of new, good facets found
+    determines facet->good
+    may update qh.GOODclosest
+    
+  notes:
+    qh_findgood_all further reduces the good region
+
+  design:
+    count good facets
+    mark good facets for qh.GOODpoint  
+    mark good facets for qh.GOODthreshold
+    if necessary
+      update qh.GOODclosest  
+*/
+int qh_findgood (facetT *facetlist, int goodhorizon) {
+  facetT *facet, *bestfacet= NULL;
+  realT angle, bestangle= REALmax, dist;
+  int  numgood=0;
+
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      numgood++;
+  }
+  if (qh GOODvertex>0 && !qh MERGING) {
+    FORALLfacet_(facetlist) {
+      if (!qh_isvertex (qh GOODvertexp, facet->vertices)) {
+        facet->good= False;
+        numgood--;
+      }
+    }
+  }
+  if (qh GOODpoint && numgood) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && facet->normal) {
+        zinc_(Zdistgood);
+        qh_distplane (qh GOODpointp, facet, &dist);
+        if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
+          facet->good= False;
+          numgood--;
+        }
+      }
+    }
+  }
+  if (qh GOODthreshold && (numgood || goodhorizon || qh GOODclosest)) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && facet->normal) {
+        if (!qh_inthresholds (facet->normal, &angle)) {
+          facet->good= False;
+          numgood--;
+          if (angle < bestangle) {
+            bestangle= angle;
+            bestfacet= facet;
+          }
+        }
+      }
+    }
+    if (!numgood && (!goodhorizon || qh GOODclosest)) {
+      if (qh GOODclosest) {
+	if (qh GOODclosest->visible)
+	  qh GOODclosest= NULL;
+	else {
+	  qh_inthresholds (qh GOODclosest->normal, &angle);
+	  if (angle < bestangle)
+	    bestfacet= qh GOODclosest;
+	}
+      }
+      if (bestfacet && bestfacet != qh GOODclosest) {
+	if (qh GOODclosest)
+	  qh GOODclosest->good= False;
+	qh GOODclosest= bestfacet;
+	bestfacet->good= True;
+	numgood++;
+	trace2((qh ferr, "qh_findgood: f%d is closest (%2.2g) to thresholds\n", 
+           bestfacet->id, bestangle));
+	return numgood;
+      }
+    }else if (qh GOODclosest) { /* numgood > 0 */
+      qh GOODclosest->good= False;
+      qh GOODclosest= NULL;
+    }
+  }
+  zadd_(Zgoodfacet, numgood);
+  trace2((qh ferr, "qh_findgood: found %d good facets with %d good horizon\n",
+               numgood, goodhorizon));
+  if (!numgood && qh GOODvertex>0 && !qh MERGING) 
+    return goodhorizon;
+  return numgood;
+} /* findgood */
+
+/*---------------------------------
+  
+  qh_findgood_all( facetlist )
+    apply other constraints for good facets (used by qh.PRINTgood)
+    if qh.GOODvertex 
+      facet includes (>0) or doesn't include (<0) point as vertex
+      if last good facet and ONLYgood, prints warning and continues
+    if qh.SPLITthresholds
+      facet->normal matches threshold, or if none, the closest one
+    calls qh_findgood
+    nop if good not used
+
+  returns:
+    clears facet->good if not good
+    sets qh.num_good
+
+  notes:
+    this is like qh_findgood but more restrictive
+
+  design:
+    uses qh_findgood to mark good facets
+    marks facets for qh.GOODvertex
+    marks facets for qh.SPLITthreholds  
+*/
+void qh_findgood_all (facetT *facetlist) {
+  facetT *facet, *bestfacet=NULL;
+  realT angle, bestangle= REALmax;
+  int  numgood=0, startgood;
+
+  if (!qh GOODvertex && !qh GOODthreshold && !qh GOODpoint 
+  && !qh SPLITthresholds)
+    return;
+  if (!qh ONLYgood)
+    qh_findgood (qh facet_list, 0);
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      numgood++;
+  }
+  if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && ((qh GOODvertex > 0) ^ !!qh_isvertex (qh GOODvertexp, facet->vertices))) {
+        if (!--numgood) {
+	  if (qh ONLYgood) {
+            fprintf (qh ferr, "qhull warning: good vertex p%d does not match last good facet f%d.  Ignored.\n",
+               qh_pointid(qh GOODvertexp), facet->id);
+	    return;
+	  }else if (qh GOODvertex > 0)
+            fprintf (qh ferr, "qhull warning: point p%d is not a vertex ('QV%d').\n",
+		qh GOODvertex-1, qh GOODvertex-1);
+	  else
+            fprintf (qh ferr, "qhull warning: point p%d is a vertex for every facet ('QV-%d').\n",
+	        -qh GOODvertex - 1, -qh GOODvertex - 1);
+        }
+        facet->good= False;
+      }
+    }
+  }
+  startgood= numgood;
+  if (qh SPLITthresholds) {
+    FORALLfacet_(facetlist) {
+      if (facet->good) {
+        if (!qh_inthresholds (facet->normal, &angle)) {
+          facet->good= False;
+          numgood--;
+          if (angle < bestangle) {
+            bestangle= angle;
+            bestfacet= facet;
+          }
+        }
+      }
+    }
+    if (!numgood && bestfacet) {
+      bestfacet->good= True;
+      numgood++;
+      trace0((qh ferr, "qh_findgood_all: f%d is closest (%2.2g) to thresholds\n", 
+           bestfacet->id, bestangle));
+      return;
+    }
+  }
+  qh num_good= numgood;
+  trace0((qh ferr, "qh_findgood_all: %d good facets remain out of %d facets\n",
+        numgood, startgood));
+} /* findgood_all */
+
+/*---------------------------------
+  
+  qh_furthestnext()
+    set qh.facet_next to facet with furthest of all furthest points
+    searches all facets on qh.facet_list
+
+  notes:
+    this may help avoid precision problems
+*/
+void qh_furthestnext (void /* qh facet_list */) {
+  facetT *facet, *bestfacet= NULL;
+  realT dist, bestdist= -REALmax;
+
+  FORALLfacets {
+    if (facet->outsideset) {
+#if qh_COMPUTEfurthest
+      pointT *furthest;
+      furthest= (pointT*)qh_setlast (facet->outsideset);
+      zinc_(Zcomputefurthest);
+      qh_distplane (furthest, facet, &dist);
+#else
+      dist= facet->furthestdist;
+#endif
+      if (dist > bestdist) {
+	bestfacet= facet;
+	bestdist= dist;
+      }
+    }
+  }
+  if (bestfacet) {
+    qh_removefacet (bestfacet);
+    qh_prependfacet (bestfacet, &qh facet_next);
+    trace1((qh ferr, "qh_furthestnext: made f%d next facet (dist %.2g)\n",
+	    bestfacet->id, bestdist));
+  }
+} /* furthestnext */
+
+/*---------------------------------
+  
+  qh_furthestout( facet )
+    make furthest outside point the last point of outsideset
+
+  returns:
+    updates facet->outsideset
+    clears facet->notfurthest
+    sets facet->furthestdist
+
+  design:
+    determine best point of outsideset
+    make it the last point of outsideset
+*/
+void qh_furthestout (facetT *facet) {
+  pointT *point, **pointp, *bestpoint= NULL;
+  realT dist, bestdist= -REALmax;
+
+  FOREACHpoint_(facet->outsideset) {
+    qh_distplane (point, facet, &dist);
+    zinc_(Zcomputefurthest);
+    if (dist > bestdist) {
+      bestpoint= point;
+      bestdist= dist;
+    }
+  }
+  if (bestpoint) {
+    qh_setdel (facet->outsideset, point);
+    qh_setappend (&facet->outsideset, point);
+#if !qh_COMPUTEfurthest
+    facet->furthestdist= bestdist;
+#endif
+  }
+  facet->notfurthest= False;
+  trace3((qh ferr, "qh_furthestout: p%d is furthest outside point of f%d\n",
+	  qh_pointid (point), facet->id));
+} /* furthestout */
+
+
+/*---------------------------------
+  
+  qh_infiniteloop( facet )
+    report infinite loop error due to facet
+*/
+void qh_infiniteloop (facetT *facet) {
+
+  fprintf (qh ferr, "qhull internal error (qh_infiniteloop): potential infinite loop detected\n");
+  qh_errexit (qh_ERRqhull, facet, NULL);
+} /* qh_infiniteloop */
+
+/*---------------------------------
+  
+  qh_initbuild()
+    initialize hull and outside sets with point array
+    qh.FIRSTpoint/qh.NUMpoints is point array
+    if qh.GOODpoint
+      adds qh.GOODpoint to initial hull
+
+  returns:
+    qh_facetlist with initial hull
+    points partioned into outside sets, coplanar sets, or inside
+    initializes qh.GOODpointp, qh.GOODvertexp,
+
+  design:
+    initialize global variables used during qh_buildhull
+    determine precision constants and points with max/min coordinate values
+      if qh.SCALElast, scale last coordinate (for 'd')
+    build initial simplex
+    partition input points into facets of initial simplex
+    set up lists
+    if qh.ONLYgood
+      check consistency  
+      add qh.GOODvertex if defined
+*/
+void qh_initbuild( void) {
+  setT *maxpoints, *vertices;
+  facetT *facet;
+  int i, numpart;
+  realT dist;
+  boolT isoutside;
+
+  qh furthest_id= -1;
+  qh lastreport= 0;
+  qh facet_id= qh vertex_id= qh ridge_id= 0;
+  qh visit_id= qh vertex_visit= 0;
+  qh maxoutdone= False;
+
+  if (qh GOODpoint > 0) 
+    qh GOODpointp= qh_point (qh GOODpoint-1);
+  else if (qh GOODpoint < 0) 
+    qh GOODpointp= qh_point (-qh GOODpoint-1);
+  if (qh GOODvertex > 0)
+    qh GOODvertexp= qh_point (qh GOODvertex-1);
+  else if (qh GOODvertex < 0) 
+    qh GOODvertexp= qh_point (-qh GOODvertex-1);
+  if ((qh GOODpoint  
+       && (qh GOODpointp < qh first_point  /* also catches !GOODpointp */
+	   || qh GOODpointp > qh_point (qh num_points-1)))
+    || (qh GOODvertex
+	&& (qh GOODvertexp < qh first_point  /* also catches !GOODvertexp */
+	    || qh GOODvertexp > qh_point (qh num_points-1)))) {
+    fprintf (qh ferr, "qhull input error: either QGn or QVn point is > p%d\n",
+	     qh num_points-1);
+    qh_errexit (qh_ERRinput, NULL, NULL);
+  }
+  maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
+  if (qh SCALElast)
+    qh_scalelast (qh first_point, qh num_points, qh hull_dim,
+               qh MINlastcoord, qh MAXlastcoord, qh MAXwidth);
+  qh_detroundoff();
+  if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2
+                  && qh lower_threshold[qh hull_dim-1] < -REALmax/2) {
+    for (i= qh_PRINTEND; i--; ) {
+      if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0 
+ 	  && !qh GOODthreshold && !qh SPLITthresholds)
+	break;  /* in this case, don't set upper_threshold */
+    }
+    if (i < 0) {
+      if (qh UPPERdelaunay) { /* matches qh.upperdelaunay in qh_setfacetplane */
+	qh lower_threshold[qh hull_dim-1]= qh ANGLEround * qh_ZEROdelaunay;
+	qh GOODthreshold= True;
+      }else { 
+	qh upper_threshold[qh hull_dim-1]= -qh ANGLEround * qh_ZEROdelaunay;
+        if (!qh GOODthreshold) 
+	  qh SPLITthresholds= True; /* build upper-convex hull even if Qg */
+          /* qh_initqhull_globals errors if Qg without Pdk/etc. */
+      }
+    }
+  }
+  vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points); 
+  qh_initialhull (vertices);  /* initial qh facet_list */
+  qh_partitionall (vertices, qh first_point, qh num_points);
+  if (qh PRINToptions1st || qh TRACElevel || qh IStracing) {
+    if (qh TRACElevel || qh IStracing)
+      fprintf (qh ferr, "\nTrace level %d for %s | %s\n", 
+         qh IStracing ? qh IStracing : qh TRACElevel, qh rbox_command, qh qhull_command);
+    fprintf (qh ferr, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
+  }
+  qh_resetlists (False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+  qh facet_next= qh facet_list;
+  qh_furthestnext (/* qh facet_list */);
+  if (qh PREmerge) {
+    qh cos_max= qh premerge_cos;
+    qh centrum_radius= qh premerge_centrum;
+  }
+  if (qh ONLYgood) {
+    if (qh GOODvertex > 0 && qh MERGING) {
+      fprintf (qh ferr, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    if (!(qh GOODthreshold || qh GOODpoint
+         || (!qh MERGEexact && !qh PREmerge && qh GOODvertexp))) {
+      fprintf (qh ferr, "qhull input error: 'Qg' (ONLYgood) needs a good threshold ('Pd0D0'), a\n\
+good point (QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
+      qh_errexit (qh_ERRinput, NULL, NULL);
+    }
+    if (qh GOODvertex > 0  && !qh MERGING  /* matches qh_partitionall */
+	&& !qh_isvertex (qh GOODvertexp, vertices)) {
+      facet= qh_findbestnew (qh GOODvertexp, qh facet_list, 
+			  &dist, !qh_ALL, &isoutside, &numpart);
+      zadd_(Zdistgood, numpart);
+      if (!isoutside) {
+        fprintf (qh ferr, "qhull input error: point for QV%d is inside initial simplex.  It can not be made a vertex.\n",
+	       qh_pointid(qh GOODvertexp));
+        qh_errexit (qh_ERRinput, NULL, NULL);
+      }
+      if (!qh_addpoint (qh GOODvertexp, facet, False)) {
+	qh_settempfree(&vertices);
+	qh_settempfree(&maxpoints);
+	return;
+      }
+    }
+    qh_findgood (qh facet_list, 0);
+  }
+  qh_settempfree(&vertices);
+  qh_settempfree(&maxpoints);
+  trace1((qh ferr, "qh_initbuild: initial hull created and points partitioned\n"));
+} /* initbuild */
+
+/*---------------------------------
+  
+  qh_initialhull( vertices )
+    constructs the initial hull as a DIM3 simplex of vertices
+
+  design:
+    creates a simplex (initializes lists)
+    determines orientation of simplex
+    sets hyperplanes for facets
+    doubles checks orientation (in case of axis-parallel facets with Gaussian elimination)
+    checks for flipped facets and qh.NARROWhull
+    checks the result   
+*/
+void qh_initialhull(setT *vertices) {
+  facetT *facet, *firstfacet, *neighbor, **neighborp;
+  realT dist, angle, minangle= REALmax;
+#ifndef qh_NOtrace
+  int k;
+#endif
+
+  qh_createsimplex(vertices);  /* qh facet_list */
+  qh_resetlists (False, qh_RESETvisible);
+  qh facet_next= qh facet_list;      /* advance facet when processed */
+  qh interior_point= qh_getcenter(vertices);
+  firstfacet= qh facet_list;
+  qh_setfacetplane(firstfacet);
+  zinc_(Znumvisibility); /* needs to be in printsummary */
+  qh_distplane(qh interior_point, firstfacet, &dist);
+  if (dist > 0) {  
+    FORALLfacets
+      facet->toporient ^= True;
+  }
+  FORALLfacets
+    qh_setfacetplane(facet);
+  FORALLfacets {
+    if (!qh_checkflipped (facet, NULL, qh_ALL)) {/* due to axis-parallel facet */
+      trace1((qh ferr, "qh_initialhull: initial orientation incorrect.  Correct all facets\n"));
+      facet->flipped= False;
+      FORALLfacets {
+	facet->toporient ^= True;
+	qh_orientoutside (facet);
+      }
+      break;
+    }
+  }
+  FORALLfacets {
+    if (!qh_checkflipped (facet, NULL, !qh_ALL)) {  /* can happen with 'R0.1' */
+      qh_precision ("initial facet is coplanar with interior point");
+      fprintf (qh ferr, "qhull precision error: initial facet %d is coplanar with the interior point\n",
+                   facet->id);
+      qh_errexit (qh_ERRsingular, facet, NULL);
+    }
+    FOREACHneighbor_(facet) {
+      angle= qh_getangle (facet->normal, neighbor->normal);
+      minimize_( minangle, angle);
+    }
+  }
+  if (minangle < qh_MAXnarrow && !qh NOnarrow) { 
+    realT diff= 1.0 + minangle;
+
+    qh NARROWhull= True;
+    qh_option ("_narrow-hull", NULL, &diff);
+    if (minangle < qh_WARNnarrow && !qh RERUN && qh PRINTprecision)
+      fprintf (qh ferr, "qhull precision warning: \n\
+The initial hull is narrow (cosine of min. angle is %.16f).\n\
+A coplanar point may lead to a wide facet.  Options 'QbB' (scale to unit box)\n\
+or 'Qbb' (scale last coordinate) may remove this warning.  Use 'Pp' to skip\n\
+this warning.  See 'Limitations' in qh-impre.htm.\n",
+          -minangle);   /* convert from angle between normals to angle between facets */
+  }
+  zzval_(Zprocessed)= qh hull_dim+1;
+  qh_checkpolygon (qh facet_list);
+  qh_checkconvex(qh facet_list,   qh_DATAfault);
+#ifndef qh_NOtrace
+  if (qh IStracing >= 1) {
+    fprintf(qh ferr, "qh_initialhull: simplex constructed, interior point:");
+    for (k=0; k < qh hull_dim; k++) 
+      fprintf (qh ferr, " %6.4g", qh interior_point[k]);
+    fprintf (qh ferr, "\n");
+  }
+#endif
+} /* initialhull */
+
+/*---------------------------------
+  
+  qh_initialvertices( dim, maxpoints, points, numpoints )
+    determines a non-singular set of initial vertices
+    maxpoints may include duplicate points
+
+  returns:
+    temporary set of dim+1 vertices in descending order by vertex id
+    if qh.RANDOMoutside && !qh.ALLpoints
+      picks random points
+    if dim >= qh_INITIALmax, 
+      uses min/max x and max points with non-zero determinants
+
+  notes:
+    unless qh.ALLpoints, 
+      uses maxpoints as long as determinate is non-zero
+*/
+setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
+  pointT *point, **pointp;
+  setT *vertices, *simplex, *tested;
+  realT randr;
+  int index, point_i, point_n, k;
+  boolT nearzero= False;
+  
+  vertices= qh_settemp (dim + 1);
+  simplex= qh_settemp (dim+1);
+  if (qh ALLpoints) 
+    qh_maxsimplex (dim, NULL, points, numpoints, &simplex);
+  else if (qh RANDOMoutside) {
+    while (qh_setsize (simplex) != dim+1) {
+      randr= qh_RANDOMint;
+      randr= randr/(qh_RANDOMmax+1);
+      index= (int)floor(qh num_points * randr);
+      while (qh_setin (simplex, qh_point (index))) {
+	index++; /* in case qh_RANDOMint always returns the same value */
+        index= index < qh num_points ? index : 0;
+      }
+      qh_setappend (&simplex, qh_point (index));
+    }
+  }else if (qh hull_dim >= qh_INITIALmax) {
+    tested= qh_settemp (dim+1);
+    qh_setappend (&simplex, SETfirst_(maxpoints));   /* max and min X coord */
+    qh_setappend (&simplex, SETsecond_(maxpoints));
+    qh_maxsimplex (fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
+    k= qh_setsize (simplex);
+    FOREACHpoint_i_(maxpoints) { 
+      if (point_i & 0x1) {     /* first pick up max. coord. points */
+      	if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
+	  qh_detsimplex(point, simplex, k, &nearzero);
+          if (nearzero)
+            qh_setappend (&tested, point);
+          else {
+            qh_setappend (&simplex, point);
+            if (++k == dim)  /* use search for last point */
+	      break;
+	  }
+	}
+      }
+    }
+    while (k != dim && (point= (pointT*)qh_setdellast (maxpoints))) {
+      if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
+        qh_detsimplex (point, simplex, k, &nearzero);
+        if (nearzero)
+          qh_setappend (&tested, point);
+        else {
+          qh_setappend (&simplex, point);
+          k++;
+	}
+      }
+    }
+    index= 0;
+    while (k != dim && (point= qh_point (index++))) {
+      if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
+        qh_detsimplex (point, simplex, k, &nearzero);
+        if (!nearzero){
+          qh_setappend (&simplex, point);
+          k++;
+	}
+      }
+    }
+    qh_settempfree (&tested);
+    qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
+  }else
+    qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
+  FOREACHpoint_(simplex) 
+    qh_setaddnth (&vertices, 0, qh_newvertex(point)); /* descending order */
+  qh_settempfree (&simplex);
+  return vertices;
+} /* initialvertices */
+
+
+/*---------------------------------
+  
+  qh_isvertex(  )
+    returns vertex if point is in vertex set, else returns NULL
+
+  notes:
+    for qh.GOODvertex
+*/
+vertexT *qh_isvertex (pointT *point, setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (vertex->point == point)
+      return vertex;
+  }
+  return NULL;
+} /* isvertex */
+
+/*---------------------------------
+  
+  qh_makenewfacets( point )
+    make new facets from point and qh.visible_list
+
+  returns:
+    qh.newfacet_list= list of new facets with hyperplanes and ->newfacet
+    qh.newvertex_list= list of vertices in new facets with ->newlist set
+    
+    if (qh.ONLYgood)
+      newfacets reference horizon facets, but not vice versa
+      ridges reference non-simplicial horizon ridges, but not vice versa
+      does not change existing facets
+    else
+      sets qh.NEWfacets
+      new facets attached to horizon facets and ridges
+      for visible facets, 
+        visible->r.replace is corresponding new facet
+
+  see also: 
+    qh_makenewplanes() -- make hyperplanes for facets
+    qh_attachnewfacets() -- attachnewfacets if not done here (qh ONLYgood)
+    qh_matchnewfacets() -- match up neighbors
+    qh_updatevertices() -- update vertex neighbors and delvertices
+    qh_deletevisible() -- delete visible facets
+    qh_checkpolygon() --check the result
+    qh_triangulate() -- triangulate a non-simplicial facet
+
+  design:
+    for each visible facet
+      make new facets to its horizon facets
+      update its f.replace 
+      clear its neighbor set
+*/
+vertexT *qh_makenewfacets (pointT *point /*visible_list*/) {
+  facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
+  vertexT *apex;
+  int numnew=0;
+
+  qh newfacet_list= qh facet_tail;
+  qh newvertex_list= qh vertex_tail;
+  apex= qh_newvertex(point);
+  qh_appendvertex (apex);  
+  qh visit_id++;
+  if (!qh ONLYgood)
+    qh NEWfacets= True;
+  FORALLvisible_facets {
+    FOREACHneighbor_(visible) 
+      neighbor->seen= False;
+    if (visible->ridges) {
+      visible->visitid= qh visit_id;
+      newfacet2= qh_makenew_nonsimplicial (visible, apex, &numnew);
+    }
+    if (visible->simplicial)
+      newfacet= qh_makenew_simplicial (visible, apex, &numnew);
+    if (!qh ONLYgood) {
+      if (newfacet2)  /* newfacet is null if all ridges defined */
+        newfacet= newfacet2;
+      if (newfacet)
+      	visible->f.replace= newfacet;
+      else
+        zinc_(Zinsidevisible);
+      SETfirst_(visible->neighbors)= NULL;
+    }
+  }
+  trace1((qh ferr, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
+	  numnew, qh_pointid(point)));
+  if (qh IStracing >= 4)
+    qh_printfacetlist (qh newfacet_list, NULL, qh_ALL);
+  return apex;
+} /* makenewfacets */
+
+/*---------------------------------
+  
+  qh_matchduplicates( atfacet, atskip, hashsize, hashcount )
+    match duplicate ridges in qh.hash_table for atfacet/atskip
+    duplicates marked with ->dupridge and qh_DUPLICATEridge
+
+  returns:
+    picks match with worst merge (min distance apart)
+    updates hashcount
+  
+  see also:
+    qh_matchneighbor
+
+  notes:
+
+  design:
+    compute hash value for atfacet and atskip
+    repeat twice -- once to make best matches, once to match the rest
+      for each possible facet in qh.hash_table
+        if it is a matching facet and pass 2
+          make match 
+	  unless tricoplanar, mark match for merging (qh_MERGEridge)
+          [e.g., tricoplanar RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Qt]
+        if it is a matching facet and pass 1
+          test if this is a better match
+      if pass 1,
+        make best match (it will not be merged)
+*/
+#ifndef qh_NOmerge
+void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+  boolT same, ismatch;
+  int hash, scan;
+  facetT *facet, *newfacet, *maxmatch= NULL, *maxmatch2= NULL, *nextfacet;
+  int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch;
+  realT maxdist= -REALmax, mindist, dist2, low, high;
+
+  hash= (int)qh_gethash (hashsize, atfacet->vertices, qh hull_dim, 1, 
+                     SETelem_(atfacet->vertices, atskip));
+  trace2((qh ferr, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n",
+	  atfacet->id, atskip, hash, *hashcount));
+  for (makematch= 0; makematch < 2; makematch++) {
+    qh visit_id++;
+    for (newfacet= atfacet, newskip= atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
+      zinc_(Zhashlookup);
+      nextfacet= NULL;
+      newfacet->visitid= qh visit_id;
+      for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT)); 
+	   scan= (++scan >= hashsize ? 0 : scan)) {
+	if (!facet->dupridge || facet->visitid == qh visit_id)
+	  continue;
+	zinc_(Zhashtests);
+	if (qh_matchvertices (1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+	  ismatch= (same == (newfacet->toporient ^ facet->toporient));
+	  if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
+	    if (!makematch) {
+	      fprintf (qh ferr, "qhull internal error (qh_matchduplicates): missing dupridge at f%d skip %d for new f%d skip %d hash %d\n",
+		     facet->id, skip, newfacet->id, newskip, hash);
+	      qh_errexit2 (qh_ERRqhull, facet, newfacet);
+	    }
+	  }else if (ismatch && makematch) {
+	    if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
+	      SETelem_(facet->neighbors, skip)= newfacet;
+	      if (newfacet->tricoplanar)
+  		SETelem_(newfacet->neighbors, newskip)= facet;
+	      else
+		SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
+	      *hashcount -= 2; /* removed two unmatched facets */
+	      trace4((qh ferr, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d merge\n",
+		    facet->id, skip, newfacet->id, newskip));
+	    }
+	  }else if (ismatch) {
+	    mindist= qh_getdistance (facet, newfacet, &low, &high);
+	    dist2= qh_getdistance (newfacet, facet, &low, &high);
+	    minimize_(mindist, dist2);
+	    if (mindist > maxdist) {
+	      maxdist= mindist;
+	      maxmatch= facet;
+	      maxskip= skip;
+	      maxmatch2= newfacet;
+	      maxskip2= newskip;
+	    }
+	    trace3((qh ferr, "qh_matchduplicates: duplicate f%d skip %d new f%d skip %d at dist %2.2g, max is now f%d f%d\n",
+		    facet->id, skip, newfacet->id, newskip, mindist, 
+		    maxmatch->id, maxmatch2->id));
+	  }else { /* !ismatch */
+	    nextfacet= facet;
+	    nextskip= skip;
+	  }
+	}
+	if (makematch && !facet 
+        && SETelemt_(facet->neighbors, skip, facetT) == qh_DUPLICATEridge) {
+	  fprintf (qh ferr, "qhull internal error (qh_matchduplicates): no MERGEridge match for duplicate f%d skip %d at hash %d\n",
+		     newfacet->id, newskip, hash);
+	  qh_errexit (qh_ERRqhull, newfacet, NULL);
+	}
+      }
+    } /* end of for each new facet at hash */
+    if (!makematch) {
+      if (!maxmatch) {
+	fprintf (qh ferr, "qhull internal error (qh_matchduplicates): no maximum match at duplicate f%d skip %d at hash %d\n",
+		     atfacet->id, atskip, hash);
+	qh_errexit (qh_ERRqhull, atfacet, NULL);
+      }
+      SETelem_(maxmatch->neighbors, maxskip)= maxmatch2;
+      SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
+      *hashcount -= 2; /* removed two unmatched facets */
+      zzinc_(Zmultiridge);
+      trace0((qh ferr, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d keep\n",
+	      maxmatch->id, maxskip, maxmatch2->id, maxskip2));
+      qh_precision ("ridge with multiple neighbors");
+      if (qh IStracing >= 4)
+	qh_errprint ("DUPLICATED/MATCH", maxmatch, maxmatch2, NULL, NULL);
+    }
+  }
+} /* matchduplicates */
+
+/*---------------------------------
+  
+  qh_nearcoplanar()
+    for all facets, remove near-inside points from facet->coplanarset
+    coplanar points defined by innerplane from qh_outerinner()
+
+  returns:
+    if qh KEEPcoplanar && !qh KEEPinside
+      facet->coplanarset only contains coplanar points
+    if qh.JOGGLEmax
+      drops inner plane by another qh.JOGGLEmax diagonal since a
+        vertex could shift out while a coplanar point shifts in
+  
+  notes:
+    used for qh.PREmerge and qh.JOGGLEmax
+    must agree with computation of qh.NEARcoplanar in qh_detroundoff()
+  design:
+    if not keeping coplanar or inside points
+      free all coplanar sets
+    else if not keeping both coplanar and inside points
+      remove !coplanar or !inside points from coplanar sets
+*/
+void qh_nearcoplanar ( void /* qh.facet_list */) {
+  facetT *facet;
+  pointT *point, **pointp;
+  int numpart;
+  realT dist, innerplane;
+
+  if (!qh KEEPcoplanar && !qh KEEPinside) {
+    FORALLfacets {
+      if (facet->coplanarset) 
+        qh_setfree( &facet->coplanarset);
+    }
+  }else if (!qh KEEPcoplanar || !qh KEEPinside) {
+    qh_outerinner (NULL, NULL, &innerplane);
+    if (qh JOGGLEmax < REALmax/2)
+      innerplane -= qh JOGGLEmax * sqrt (qh hull_dim);
+    numpart= 0;
+    FORALLfacets { 
+      if (facet->coplanarset) {
+        FOREACHpoint_(facet->coplanarset) {
+          numpart++;
+	  qh_distplane (point, facet, &dist); 
+  	  if (dist < innerplane) {
+	    if (!qh KEEPinside)
+              SETref_(point)= NULL;
+          }else if (!qh KEEPcoplanar)
+            SETref_(point)= NULL;
+        }
+	qh_setcompact (facet->coplanarset);
+      }
+    }
+    zzadd_(Zcheckpart, numpart);
+  }
+} /* nearcoplanar */
+
+/*---------------------------------
+  
+  qh_nearvertex( facet, point, bestdist )
+    return nearest vertex in facet to point
+
+  returns:
+    vertex and its distance
+    
+  notes:
+    if qh.DELAUNAY
+      distance is measured in the input set
+    searches neighboring tricoplanar facets (requires vertexneighbors)
+      Slow implementation.  Recomputes vertex set for each point.
+    The vertex set could be stored in the qh.keepcentrum facet.
+*/
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp) {
+  realT bestdist= REALmax, dist;
+  vertexT *bestvertex= NULL, *vertex, **vertexp, *apex;
+  coordT *center;
+  facetT *neighbor, **neighborp;
+  setT *vertices;
+  int dim= qh hull_dim;
+
+  if (qh DELAUNAY)
+    dim--;
+  if (facet->tricoplanar) {
+    if (!qh VERTEXneighbors || !facet->center) {
+      fprintf(qh ferr, "qhull internal error (qh_nearvertex): qh.VERTEXneighbors and facet->center required for tricoplanar facets\n");
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+    vertices= qh_settemp (qh TEMPsize);
+    apex= SETfirst_(facet->vertices);
+    center= facet->center;
+    FOREACHneighbor_(apex) {
+      if (neighbor->center == center) {
+	FOREACHvertex_(neighbor->vertices) 
+	  qh_setappend(&vertices, vertex);
+      }
+    }
+  }else 
+    vertices= facet->vertices;
+  FOREACHvertex_(vertices) {
+    dist= qh_pointdist (vertex->point, point, -dim);
+    if (dist < bestdist) {
+      bestdist= dist;
+      bestvertex= vertex;
+    }
+  }
+  if (facet->tricoplanar)
+    qh_settempfree (&vertices);
+  *bestdistp= sqrt (bestdist);
+  trace3((qh ferr, "qh_nearvertex: v%d dist %2.2g for f%d p%d\n", 
+        bestvertex->id, *bestdistp, facet->id, qh_pointid(point)));
+  return bestvertex;
+} /* nearvertex */
+
+/*---------------------------------
+  
+  qh_newhashtable( newsize )
+    returns size of qh.hash_table of at least newsize slots
+
+  notes:
+    assumes qh.hash_table is NULL
+    qh_HASHfactor determines the number of extra slots
+    size is not divisible by 2, 3, or 5
+*/
+int qh_newhashtable(int newsize) {
+  int size;
+
+  size= ((newsize+1)*qh_HASHfactor) | 0x1;  /* odd number */
+  while (True) { 
+    if ((size%3) && (size%5))
+      break;
+    size += 2;
+    /* loop terminates because there is an infinite number of primes */
+  }
+  qh hash_table= qh_setnew (size);
+  qh_setzero (qh hash_table, 0, size);
+  return size;
+} /* newhashtable */
+
+/*---------------------------------
+  
+  qh_newvertex( point )
+    returns a new vertex for point
+*/
+vertexT *qh_newvertex(pointT *point) {
+  vertexT *vertex;
+
+  zinc_(Ztotvertices);
+  vertex= (vertexT *)qh_memalloc(sizeof(vertexT));
+  memset ((char *) vertex, 0, sizeof (vertexT));
+  if (qh vertex_id == 0xFFFFFF) {
+    fprintf(qh ferr, "qhull input error: more than %d vertices.  ID field overflows and two vertices\n\
+may have the same identifier.  Vertices not sorted correctly.\n", 0xFFFFFF);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh vertex_id == qh tracevertex_id)
+    qh tracevertex= vertex;
+  vertex->id= qh vertex_id++;
+  vertex->point= point;
+  trace4((qh ferr, "qh_newvertex: vertex p%d (v%d) created\n", qh_pointid(vertex->point), 
+	  vertex->id));
+  return (vertex);
+} /* newvertex */
+
+/*---------------------------------
+  
+  qh_nextridge3d( atridge, facet, vertex )
+    return next ridge and vertex for a 3d facet
+
+  notes:
+    in qh_ORIENTclock order
+    this is a O(n^2) implementation to trace all ridges
+    be sure to stop on any 2nd visit
+  
+  design:
+    for each ridge
+      exit if it is the ridge after atridge
+*/
+ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) {
+  vertexT *atvertex, *vertex, *othervertex;
+  ridgeT *ridge, **ridgep;
+
+  if ((atridge->top == facet) ^ qh_ORIENTclock)
+    atvertex= SETsecondt_(atridge->vertices, vertexT);
+  else
+    atvertex= SETfirstt_(atridge->vertices, vertexT);
+  FOREACHridge_(facet->ridges) {
+    if (ridge == atridge)
+      continue;
+    if ((ridge->top == facet) ^ qh_ORIENTclock) {
+      othervertex= SETsecondt_(ridge->vertices, vertexT);
+      vertex= SETfirstt_(ridge->vertices, vertexT);
+    }else {
+      vertex= SETsecondt_(ridge->vertices, vertexT);
+      othervertex= SETfirstt_(ridge->vertices, vertexT);
+    }
+    if (vertex == atvertex) {
+      if (vertexp)
+        *vertexp= othervertex;
+      return ridge;
+    }
+  }
+  return NULL;
+} /* nextridge3d */
+#else /* qh_NOmerge */
+void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+}
+ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) {
+
+  return NULL;
+}
+#endif /* qh_NOmerge */
+  
+/*---------------------------------
+  
+  qh_outcoplanar()
+    move points from all facets' outsidesets to their coplanarsets
+
+  notes:
+    for post-processing under qh.NARROWhull
+
+  design:
+    for each facet
+      for each outside point for facet
+        partition point into coplanar set
+*/
+void qh_outcoplanar (void /* facet_list */) {
+  pointT *point, **pointp;
+  facetT *facet;
+  realT dist;
+
+  trace1((qh ferr, "qh_outcoplanar: move outsideset to coplanarset for qh NARROWhull\n"));
+  FORALLfacets {
+    FOREACHpoint_(facet->outsideset) {
+      qh num_outside--;
+      if (qh KEEPcoplanar || qh KEEPnearinside) {
+	qh_distplane (point, facet, &dist);
+        zinc_(Zpartition);
+	qh_partitioncoplanar (point, facet, &dist);
+      }
+    }
+    qh_setfree (&facet->outsideset);
+  }
+} /* outcoplanar */
+
+/*---------------------------------
+  
+  qh_point( id )
+    return point for a point id, or NULL if unknown
+
+  alternative code:
+    return ((pointT *)((unsigned   long)qh.first_point
+           + (unsigned long)((id)*qh.normal_size)));
+*/
+pointT *qh_point (int id) {
+
+  if (id < 0)
+    return NULL;
+  if (id < qh num_points)
+    return qh first_point + id * qh hull_dim;
+  id -= qh num_points;
+  if (id < qh_setsize (qh other_points))
+    return SETelemt_(qh other_points, id, pointT);
+  return NULL;
+} /* point */
+  
+/*---------------------------------
+  
+  qh_point_add( set, point, elem )
+    stores elem at set[point.id]
+  
+  returns:
+    access function for qh_pointfacet and qh_pointvertex
+
+  notes:
+    checks point.id
+*/
+void qh_point_add (setT *set, pointT *point, void *elem) {
+  int id, size;
+
+  SETreturnsize_(set, size);
+  if ((id= qh_pointid(point)) < 0)
+    fprintf (qh ferr, "qhull internal warning (point_add): unknown point %p id %d\n", 
+      point, id);
+  else if (id >= size) {
+    fprintf (qh ferr, "qhull internal errror (point_add): point p%d is out of bounds (%d)\n",
+	     id, size);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }else
+    SETelem_(set, id)= elem;
+} /* point_add */
+
+
+/*---------------------------------
+  
+  qh_pointfacet()
+    return temporary set of facet for each point
+    the set is indexed by point id
+
+  notes:
+    vertices assigned to one of the facets
+    coplanarset assigned to the facet
+    outside set assigned to the facet
+    NULL if no facet for point (inside)
+      includes qh.GOODpointp
+
+  access:
+    FOREACHfacet_i_(facets) { ... }
+    SETelem_(facets, i)
+  
+  design:
+    for each facet
+      add each vertex
+      add each coplanar point
+      add each outside point
+*/
+setT *qh_pointfacet (void /*qh facet_list*/) {
+  int numpoints= qh num_points + qh_setsize (qh other_points);
+  setT *facets;
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+  pointT *point, **pointp;
+  
+  facets= qh_settemp (numpoints);
+  qh_setzero (facets, 0, numpoints);
+  qh vertex_visit++;
+  FORALLfacets {
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        vertex->visitid= qh vertex_visit;
+        qh_point_add (facets, vertex->point, facet);
+      }
+    }
+    FOREACHpoint_(facet->coplanarset) 
+      qh_point_add (facets, point, facet);
+    FOREACHpoint_(facet->outsideset) 
+      qh_point_add (facets, point, facet);
+  }
+  return facets;
+} /* pointfacet */
+
+/*---------------------------------
+  
+  qh_pointvertex(  )
+    return temporary set of vertices indexed by point id
+    entry is NULL if no vertex for a point
+      this will include qh.GOODpointp
+
+  access:
+    FOREACHvertex_i_(vertices) { ... }
+    SETelem_(vertices, i)
+*/
+setT *qh_pointvertex (void /*qh facet_list*/) {
+  int numpoints= qh num_points + qh_setsize (qh other_points);
+  setT *vertices;
+  vertexT *vertex;
+  
+  vertices= qh_settemp (numpoints);
+  qh_setzero (vertices, 0, numpoints);
+  FORALLvertices 
+    qh_point_add (vertices, vertex->point, vertex);
+  return vertices;
+} /* pointvertex */
+
+
+/*---------------------------------
+  
+  qh_prependfacet( facet, facetlist )
+    prepend facet to the start of a facetlist
+
+  returns:
+    increments qh.numfacets
+    updates facetlist, qh.facet_list, facet_next
+  
+  notes:
+    be careful of prepending since it can lose a pointer.
+      e.g., can lose _next by deleting and then prepending before _next
+*/
+void qh_prependfacet(facetT *facet, facetT **facetlist) {
+  facetT *prevfacet, *list;
+  
+
+  trace4((qh ferr, "qh_prependfacet: prepend f%d before f%d\n",
+	  facet->id, getid_(*facetlist)));
+  if (!*facetlist)
+    (*facetlist)= qh facet_tail;
+  list= *facetlist;
+  prevfacet= list->previous;
+  facet->previous= prevfacet;
+  if (prevfacet)
+    prevfacet->next= facet;
+  list->previous= facet;
+  facet->next= *facetlist;
+  if (qh facet_list == list)  /* this may change *facetlist */
+    qh facet_list= facet;
+  if (qh facet_next == list)
+    qh facet_next= facet;
+  *facetlist= facet;
+  qh num_facets++;
+} /* prependfacet */
+
+
+/*---------------------------------
+  
+  qh_printhashtable( fp )
+    print hash table to fp
+
+  notes:
+    not in I/O to avoid bringing io.c in
+  
+  design:
+    for each hash entry
+      if defined
+        if unmatched or will merge (NULL, qh_MERGEridge, qh_DUPLICATEridge)
+          print entry and neighbors
+*/
+void qh_printhashtable(FILE *fp) {
+  facetT *facet, *neighbor;
+  int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
+  vertexT *vertex, **vertexp;
+
+  FOREACHfacet_i_(qh hash_table) {
+    if (facet) {
+      FOREACHneighbor_i_(facet) {
+        if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) 
+          break;
+      }
+      if (neighbor_i == neighbor_n)
+        continue;
+      fprintf (fp, "hash %d f%d ", facet_i, facet->id);
+      FOREACHvertex_(facet->vertices)
+        fprintf (fp, "v%d ", vertex->id);
+      fprintf (fp, "\n neighbors:");
+      FOREACHneighbor_i_(facet) {
+	if (neighbor == qh_MERGEridge)
+	  id= -3;
+	else if (neighbor == qh_DUPLICATEridge)
+	  id= -2;
+	else
+	  id= getid_(neighbor);
+        fprintf (fp, " %d", id);
+      }
+      fprintf (fp, "\n");
+    }
+  }
+} /* printhashtable */
+     
+
+/*---------------------------------
+  
+  qh_printlists( fp )
+    print out facet and vertex list for debugging (without 'f/v' tags)
+*/
+void qh_printlists (void) {
+  facetT *facet;
+  vertexT *vertex;
+  int count= 0;
+  
+  fprintf (qh ferr, "qh_printlists: facets:");
+  FORALLfacets {
+    if (++count % 100 == 0)
+      fprintf (qh ferr, "\n     ");
+    fprintf (qh ferr, " %d", facet->id);
+  }
+  fprintf (qh ferr, "\n  new facets %d visible facets %d next facet for qh_addpoint %d\n  vertices (new %d):",
+     getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
+     getid_(qh newvertex_list));
+  count = 0;
+  FORALLvertices {
+    if (++count % 100 == 0)
+      fprintf (qh ferr, "\n     ");
+    fprintf (qh ferr, " %d", vertex->id);
+  }
+  fprintf (qh ferr, "\n");
+} /* printlists */
+  
+/*---------------------------------
+  
+  qh_resetlists( stats, qh_RESETvisible )
+    reset newvertex_list, newfacet_list, visible_list
+    if stats, 
+      maintains statistics
+
+  returns:
+    visible_list is empty if qh_deletevisible was called
+*/
+void qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/) {
+  vertexT *vertex;
+  facetT *newfacet, *visible;
+  int totnew=0, totver=0;
+  
+  if (stats) {
+    FORALLvertex_(qh newvertex_list)
+      totver++;
+    FORALLnew_facets 
+      totnew++;
+    zadd_(Zvisvertextot, totver);
+    zmax_(Zvisvertexmax, totver);
+    zadd_(Znewfacettot, totnew);
+    zmax_(Znewfacetmax, totnew);
+  }
+  FORALLvertex_(qh newvertex_list)
+    vertex->newlist= False;
+  qh newvertex_list= NULL;
+  FORALLnew_facets
+    newfacet->newfacet= False;
+  qh newfacet_list= NULL;
+  if (resetVisible) {
+    FORALLvisible_facets {
+      visible->f.replace= NULL;
+      visible->visible= False;
+    }
+    qh num_visible= 0;
+  }
+  qh visible_list= NULL; /* may still have visible facets via qh_triangulate */
+  qh NEWfacets= False;
+} /* resetlists */
+
+/*---------------------------------
+  
+  qh_setvoronoi_all()
+    compute Voronoi centers for all facets
+    includes upperDelaunay facets if qh.UPPERdelaunay ('Qu')
+
+  returns:
+    facet->center is the Voronoi center
+    
+  notes:
+    this is unused/untested code
+      please email bradb at shore.net if this works ok for you
+  
+  use:
+    FORALLvertices {...} to locate the vertex for a point.  
+    FOREACHneighbor_(vertex) {...} to visit the Voronoi centers for a Voronoi cell.
+*/
+void qh_setvoronoi_all (void) {
+  facetT *facet;
+
+  qh_clearcenters (qh_ASvoronoi);
+  qh_vertexneighbors();
+  
+  FORALLfacets {
+    if (!facet->normal || !facet->upperdelaunay || qh UPPERdelaunay) {
+      if (!facet->center)
+        facet->center= qh_facetcenter (facet->vertices);
+    }
+  }
+} /* setvoronoi_all */
+
+#ifndef qh_NOmerge
+
+/*---------------------------------
+  
+  qh_triangulate()
+    triangulate non-simplicial facets on qh.facet_list, 
+    if qh.CENTERtype=qh_ASvoronoi, sets Voronoi centers of non-simplicial facets
+
+  returns:
+    all facets simplicial
+    each tricoplanar facet has ->f.triowner == owner of ->center,normal,etc.
+
+  notes:
+    call after qh_check_output since may switch to Voronoi centers
+    Output may overwrite ->f.triowner with ->f.area
+*/
+void qh_triangulate (void /*qh facet_list*/) {
+  facetT *facet, *nextfacet, *owner;
+  int onlygood= qh ONLYgood;
+  facetT *neighbor, *visible= NULL, *facet1, *facet2, *new_facet_list= NULL;
+  facetT *orig_neighbor= NULL, *otherfacet;
+  vertexT *new_vertex_list= NULL;
+  mergeT *merge; 
+  mergeType mergetype;
+  int neighbor_i, neighbor_n;
+
+  trace1((qh ferr, "qh_triangulate: triangulate non-simplicial facets\n"));
+  if (qh hull_dim == 2)
+    return;
+  if (qh VORONOI) {  /* otherwise lose Voronoi centers [could rebuild vertex set from tricoplanar] */
+    qh_clearcenters (qh_ASvoronoi);
+    qh_vertexneighbors();
+  }
+  qh ONLYgood= False; /* for makenew_nonsimplicial */
+  qh visit_id++;
+  qh NEWfacets= True;
+  qh degen_mergeset= qh_settemp (qh TEMPsize);
+  qh newvertex_list= qh vertex_tail;
+  for (facet= qh facet_list; facet && facet->next; facet= nextfacet) { /* non-simplicial facets moved to end */
+    nextfacet= facet->next;
+    if (facet->visible || facet->simplicial)
+      continue;
+    /* triangulate all non-simplicial facets, otherwise merging does not work, e.g., RBOX c P-0.1 P+0.1 P+0.1 D3 | QHULL d Qt Tv */
+    if (!new_facet_list)
+      new_facet_list= facet;  /* will be moved to end */
+    qh_triangulate_facet (facet, &new_vertex_list);
+  }
+  trace2((qh ferr, "qh_triangulate: delete null facets from f%d -- apex same as second vertex\n", getid_(new_facet_list)));
+  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* null facets moved to end */
+    nextfacet= facet->next;
+    if (facet->visible) 
+      continue;
+    if (facet->ridges) {
+      if (qh_setsize(facet->ridges) > 0) {
+	fprintf( qh ferr, "qhull error (qh_triangulate): ridges still defined for f%d\n", facet->id);
+	qh_errexit (qh_ERRqhull, facet, NULL);
+      }
+      qh_setfree (&facet->ridges);
+    }
+    if (SETfirst_(facet->vertices) == SETsecond_(facet->vertices)) {
+      zinc_(Ztrinull);
+      qh_triangulate_null (facet);
+    }
+  }
+  trace2((qh ferr, "qh_triangulate: delete %d or more mirror facets -- same vertices and neighbors\n", qh_setsize(qh degen_mergeset)));
+  qh visible_list= qh facet_tail;
+  while ((merge= (mergeT*)qh_setdellast (qh degen_mergeset))) {
+    facet1= merge->facet1;
+    facet2= merge->facet2;
+    mergetype= merge->type;
+    qh_memfree (merge, sizeof(mergeT));
+    if (mergetype == MRGmirror) {
+      zinc_(Ztrimirror);
+      qh_triangulate_mirror (facet1, facet2);
+    }
+  }
+  qh_settempfree(&qh degen_mergeset);
+  trace2((qh ferr, "qh_triangulate: update neighbor lists for vertices from v%d\n", getid_(new_vertex_list)));
+  qh newvertex_list= new_vertex_list;  /* all vertices of new facets */
+  qh visible_list= NULL;
+  qh_updatevertices(/*qh newvertex_list, empty newfacet_list and visible_list*/);
+  qh_resetlists (False, !qh_RESETvisible /*qh newvertex_list, empty newfacet_list and visible_list*/);
+
+  trace2((qh ferr, "qh_triangulate: identify degenerate tricoplanar facets from f%d\n", getid_(new_facet_list)));
+  trace2((qh ferr, "qh_triangulate: and replace facet->f.triowner with tricoplanar facets that own center, normal, etc.\n"));
+  FORALLfacet_(new_facet_list) {
+    if (facet->tricoplanar && !facet->visible) {
+      FOREACHneighbor_i_(facet) {
+	if (neighbor_i == 0) {  /* first iteration */
+	  if (neighbor->tricoplanar)
+            orig_neighbor= neighbor->f.triowner;
+	  else
+	    orig_neighbor= neighbor;
+	}else {
+	  if (neighbor->tricoplanar)
+  	    otherfacet= neighbor->f.triowner;
+	  else
+	    otherfacet= neighbor;
+	  if (orig_neighbor == otherfacet) {
+	    zinc_(Ztridegen);
+	    facet->degenerate= True;
+	    break;
+	  }
+	}
+      }
+    }
+  }
+
+  trace2((qh ferr, "qh_triangulate: delete visible facets -- non-simplicial, null, and mirrored facets\n"));
+  owner= NULL;
+  visible= NULL;
+  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* may delete facet */
+    nextfacet= facet->next;
+    if (facet->visible) {
+      if (facet->tricoplanar) { /* a null or mirrored facet */
+	qh_delfacet(facet);
+	qh num_visible--;
+      }else {  /* a non-simplicial facet followed by its tricoplanars */
+	if (visible && !owner) {
+	  /*  RBOX 200 s D5 t1001471447 | QHULL Qt C-0.01 Qx Qc Tv Qt -- f4483 had 6 vertices/neighbors and 8 ridges */
+	  trace2((qh ferr, "qh_triangulate: all tricoplanar facets degenerate for non-simplicial facet f%d\n",
+		       visible->id));
+	  qh_delfacet(visible);
+	  qh num_visible--;
+	}
+	visible= facet;
+	owner= NULL;
+      }
+    }else if (facet->tricoplanar) {
+      if (facet->f.triowner != visible) { 
+	fprintf( qh ferr, "qhull error (qh_triangulate): tricoplanar facet f%d not owned by its visible, non-simplicial facet f%d\n", facet->id, getid_(visible));
+	qh_errexit2 (qh_ERRqhull, facet, visible);
+      }
+      if (owner) 
+	facet->f.triowner= owner;
+      else if (!facet->degenerate) {
+	owner= facet;
+	nextfacet= visible->next; /* rescan tricoplanar facets with owner */
+	facet->keepcentrum= True;  /* one facet owns ->normal, etc. */
+	facet->coplanarset= visible->coplanarset;
+	facet->outsideset= visible->outsideset;
+  	visible->coplanarset= NULL;
+	visible->outsideset= NULL;
+        if (!qh TRInormals) { /* center and normal copied to tricoplanar facets */
+	  visible->center= NULL;
+	  visible->normal= NULL;
+	}
+	qh_delfacet(visible);
+	qh num_visible--;
+      }
+    }
+  }
+  if (visible && !owner) {
+    trace2((qh ferr, "qh_triangulate: all tricoplanar facets degenerate for last non-simplicial facet f%d\n",
+	         visible->id));
+    qh_delfacet(visible);
+    qh num_visible--;
+  }
+  qh NEWfacets= False;
+  qh ONLYgood= onlygood; /* restore value */
+  if (qh CHECKfrequently) 
+    qh_checkpolygon (qh facet_list);
+} /* triangulate */
+
+
+/*---------------------------------
+  
+  qh_triangulate_facet (facetA)
+    triangulate a non-simplicial facet
+      if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center
+  returns:
+    qh.newfacet_list == simplicial facets
+      facet->tricoplanar set and ->keepcentrum false
+      facet->degenerate set if duplicated apex
+      facet->f.trivisible set to facetA
+      facet->center copied from facetA (created if qh_ASvoronoi)
+	qh_eachvoronoi, qh_detvridge, qh_detvridge3 assume centers copied
+      facet->normal,offset,maxoutside copied from facetA
+
+  notes:
+      qh_makenew_nonsimplicial uses neighbor->seen for the same
+
+  see also:
+      qh_addpoint() -- add a point
+      qh_makenewfacets() -- construct a cone of facets for a new vertex
+
+  design:
+      if qh_ASvoronoi, 
+	 compute Voronoi center (facet->center)
+      select first vertex (highest ID to preserve ID ordering of ->vertices)
+      triangulate from vertex to ridges
+      copy facet->center, normal, offset
+      update vertex neighbors
+*/
+void qh_triangulate_facet (facetT *facetA, vertexT **first_vertex) {
+  facetT *newfacet;
+  facetT *neighbor, **neighborp;
+  vertexT *apex;
+  int numnew=0;
+
+  trace3((qh ferr, "qh_triangulate_facet: triangulate facet f%d\n", facetA->id));
+
+  if (qh IStracing >= 4)
+    qh_printfacet (qh ferr, facetA);
+  FOREACHneighbor_(facetA) {
+    neighbor->seen= False;
+    neighbor->coplanar= False;
+  }
+  if (qh CENTERtype == qh_ASvoronoi && !facetA->center  /* matches upperdelaunay in qh_setfacetplane() */
+        && fabs_(facetA->normal[qh hull_dim -1]) >= qh ANGLEround * qh_ZEROdelaunay) {
+    facetA->center= qh_facetcenter (facetA->vertices);
+  }
+  qh_willdelete (facetA, NULL);
+  qh newfacet_list= qh facet_tail;
+  facetA->visitid= qh visit_id;
+  apex= SETfirst_(facetA->vertices);
+  qh_makenew_nonsimplicial (facetA, apex, &numnew);
+  SETfirst_(facetA->neighbors)= NULL;
+  FORALLnew_facets {
+    newfacet->tricoplanar= True;
+    newfacet->f.trivisible= facetA;
+    newfacet->degenerate= False;
+    newfacet->upperdelaunay= facetA->upperdelaunay;
+    newfacet->good= facetA->good;
+    if (qh TRInormals) { 
+      newfacet->keepcentrum= True;
+      newfacet->normal= qh_copypoints (facetA->normal, 1, qh hull_dim);
+      if (qh CENTERtype == qh_AScentrum) 
+	newfacet->center= qh_getcentrum (newfacet);
+      else
+	newfacet->center= qh_copypoints (facetA->center, 1, qh hull_dim);
+    }else {
+      newfacet->keepcentrum= False;
+      newfacet->normal= facetA->normal;
+      newfacet->center= facetA->center;
+    }
+    newfacet->offset= facetA->offset;
+#if qh_MAXoutside
+    newfacet->maxoutside= facetA->maxoutside;
+#endif
+  }
+  qh_matchnewfacets(/*qh newfacet_list*/);
+  zinc_(Ztricoplanar);
+  zadd_(Ztricoplanartot, numnew);
+  zmax_(Ztricoplanarmax, numnew);
+  qh visible_list= NULL;
+  if (!(*first_vertex))
+    (*first_vertex)= qh newvertex_list;
+  qh newvertex_list= NULL;
+  qh_updatevertices(/*qh newfacet_list, empty visible_list and newvertex_list*/);
+  qh_resetlists (False, !qh_RESETvisible /*qh newfacet_list, empty visible_list and newvertex_list*/);
+} /* triangulate_facet */
+
+/*---------------------------------
+  
+  qh_triangulate_link (oldfacetA, facetA, oldfacetB, facetB)
+    relink facetA to facetB via oldfacets
+  returns:
+    adds mirror facets to qh degen_mergeset (4-d and up only)
+  design:
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB) {
+  int errmirror= False;
+
+  trace3((qh ferr, "qh_triangulate_link: relink old facets f%d and f%d between neighbors f%d and f%d\n", 
+         oldfacetA->id, oldfacetB->id, facetA->id, facetB->id));
+  if (qh_setin (facetA->neighbors, facetB)) {
+    if (!qh_setin (facetB->neighbors, facetA)) 
+      errmirror= True;
+    else
+      qh_appendmergeset (facetA, facetB, MRGmirror, NULL);
+  }else if (qh_setin (facetB->neighbors, facetA)) 
+    errmirror= True;
+  if (errmirror) {
+    fprintf( qh ferr, "qhull error (qh_triangulate_link): mirror facets f%d and f%d do not match for old facets f%d and f%d\n",
+       facetA->id, facetB->id, oldfacetA->id, oldfacetB->id);
+    qh_errexit2 (qh_ERRqhull, facetA, facetB);
+  }
+  qh_setreplace (facetB->neighbors, oldfacetB, facetA);
+  qh_setreplace (facetA->neighbors, oldfacetA, facetB);
+} /* triangulate_link */
+
+/*---------------------------------
+  
+  qh_triangulate_mirror (facetA, facetB)
+    delete mirrored facets from qh_triangulate_null() and qh_triangulate_mirror
+      a mirrored facet shares the same vertices of a logical ridge
+  design:
+    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_mirror (facetT *facetA, facetT *facetB) {
+  facetT *neighbor, *neighborB;
+  int neighbor_i, neighbor_n;
+
+  trace3((qh ferr, "qh_triangulate_mirror: delete mirrored facets f%d and f%d\n", 
+         facetA->id, facetB->id));
+  FOREACHneighbor_i_(facetA) {
+    neighborB= SETelemt_(facetB->neighbors, neighbor_i, facetT);
+    if (neighbor == neighborB)
+      continue; /* occurs twice */
+    qh_triangulate_link (facetA, neighbor, facetB, neighborB);
+  }
+  qh_willdelete (facetA, NULL);
+  qh_willdelete (facetB, NULL);
+} /* triangulate_mirror */
+
+/*---------------------------------
+  
+  qh_triangulate_null (facetA)
+    remove null facetA from qh_triangulate_facet()
+      a null facet has vertex #1 (apex) == vertex #2
+  returns:
+    adds facetA to ->visible for deletion after qh_updatevertices
+    qh degen_mergeset contains mirror facets (4-d and up only)
+  design:
+    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_null (facetT *facetA) {
+  facetT *neighbor, *otherfacet;
+
+  trace3((qh ferr, "qh_triangulate_null: delete null facet f%d\n", facetA->id));
+  neighbor= SETfirst_(facetA->neighbors);
+  otherfacet= SETsecond_(facetA->neighbors);
+  qh_triangulate_link (facetA, neighbor, facetA, otherfacet);
+  qh_willdelete (facetA, NULL);
+} /* triangulate_null */
+
+#else /* qh_NOmerge */
+void qh_triangulate (void) {
+}
+#endif /* qh_NOmerge */
+
+   /*---------------------------------
+  
+  qh_vertexintersect( vertexsetA, vertexsetB )
+    intersects two vertex sets (inverse id ordered)
+    vertexsetA is a temporary set at the top of qhmem.tempstack
+
+  returns:
+    replaces vertexsetA with the intersection
+  
+  notes:
+    could overwrite vertexsetA if currently too slow
+*/
+void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
+  setT *intersection;
+
+  intersection= qh_vertexintersect_new (*vertexsetA, vertexsetB);
+  qh_settempfree (vertexsetA);
+  *vertexsetA= intersection;
+  qh_settemppush (intersection);
+} /* vertexintersect */
+
+/*---------------------------------
+  
+  qh_vertexintersect_new(  )
+    intersects two vertex sets (inverse id ordered)
+
+  returns:
+    a new set
+*/
+setT *qh_vertexintersect_new (setT *vertexsetA,setT *vertexsetB) {
+  setT *intersection= qh_setnew (qh hull_dim - 1);
+  vertexT **vertexA= SETaddr_(vertexsetA, vertexT); 
+  vertexT **vertexB= SETaddr_(vertexsetB, vertexT); 
+
+  while (*vertexA && *vertexB) {
+    if (*vertexA  == *vertexB) {
+      qh_setappend(&intersection, *vertexA);
+      vertexA++; vertexB++;
+    }else {
+      if ((*vertexA)->id > (*vertexB)->id)
+        vertexA++;
+      else
+        vertexB++;
+    }
+  }
+  return intersection;
+} /* vertexintersect_new */
+
+/*---------------------------------
+  
+  qh_vertexneighbors()
+    for each vertex in qh.facet_list, 
+      determine its neighboring facets 
+
+  returns:
+    sets qh.VERTEXneighbors
+      nop if qh.VERTEXneighbors already set
+      qh_addpoint() will maintain them
+
+  notes:
+    assumes all vertex->neighbors are NULL
+
+  design:
+    for each facet
+      for each vertex
+        append facet to vertex->neighbors
+*/
+void qh_vertexneighbors (void /*qh facet_list*/) {
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+
+  if (qh VERTEXneighbors)
+    return;
+  trace1((qh ferr, "qh_vertexneighbors: determing neighboring facets for each vertex\n"));
+  qh vertex_visit++;
+  FORALLfacets {
+    if (facet->visible)
+      continue;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        vertex->visitid= qh vertex_visit;
+        vertex->neighbors= qh_setnew (qh hull_dim);
+      }
+      qh_setappend (&vertex->neighbors, facet);
+    }
+  }
+  qh VERTEXneighbors= True;
+} /* vertexneighbors */
+
+/*---------------------------------
+  
+  qh_vertexsubset( vertexsetA, vertexsetB )
+    returns True if vertexsetA is a subset of vertexsetB
+    assumes vertexsets are sorted
+
+  note:    
+    empty set is a subset of any other set
+*/
+boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
+  vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
+  vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
+
+  while (True) {
+    if (!*vertexA)
+      return True;
+    if (!*vertexB)
+      return False;
+    if ((*vertexA)->id > (*vertexB)->id)
+      return False;
+    if (*vertexA  == *vertexB)
+      vertexA++;
+    vertexB++; 
+  }
+  return False; /* avoid warnings */
+} /* vertexsubset */

Added: trunk/scipy/spatial/qhull/src/qconvex.c
===================================================================
--- trunk/scipy/spatial/qhull/src/qconvex.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qconvex.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,334 @@
+/*
  ---------------------------------
+
+   qconvex.c
+      compute convex hulls using qhull
+
+   see unix.c for full interface
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include 
+#include 
+#include 
+#include 
+
+#elif __cplusplus
+extern "C" {
+  int isatty (int);
+}
+
+#elif _MSC_VER
+#include 
+#define isatty _isatty
+
+#else
+int isatty (int);  /* returns 1 if stdin is a tty
+		   if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*---------------------------------
+
+  qh_prompt
+    long prompt for qconvex
+    
+  notes:
+    restricted version of qhull.c
+
+  see:
+    concise prompt below
+*/  
+
+/* duplicated in qconvex.htm */
+char hidden_options[]=" d v H Qbb Qf Qg Qm Qr Qu Qv Qx Qz TR E V Fp Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
+	       
+char qh_prompta[]= "\n\
+qconvex- compute the convex hull\n\
+    http://www.qhull.org  %s\n\
+\n\
+input (stdin):\n\
+    first lines: dimension and number of points (or vice-versa).\n\
+    other lines: point coordinates, best if one point per line\n\
+    comments:    start with a non-numeric character\n\
+\n\
+options:\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+    Qc   - keep coplanar points with nearest facet\n\
+    Qi   - keep interior points with nearest facet\n\
+\n\
+Qhull control options:\n\
+    Qbk:n   - scale coord k so that low bound is n\n\
+      QBk:n - scale coord k so that upper bound is n (QBk is %2.2g)\n\
+    QbB  - scale input to unit cube centered at the origin\n\
+    Qbk:0Bk:0 - remove k-th coordinate from input\n\
+    QJn  - randomly joggle input in range [-n,n]\n\
+    QRn  - random rotation (n=seed, n=0 time, n=-1 time/no rotate)\n\
+%s%s%s%s";  /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+    Qs   - search all points for the initial simplex\n\
+    QGn  - good facet if visible from point n, -n for not visible\n\
+    QVn  - good facet if it includes point n, -n if not\n\
+\n\
+";
+char qh_promptc[]= "\
+Trace options:\n\
+    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+    Tc   - check frequently during execution\n\
+    Ts   - print statistics\n\
+    Tv   - verify result: structure, convexity, and point inclusion\n\
+    Tz   - send all output to stdout\n\
+    TFn  - report summary when n or more facets created\n\
+    TI file - input data from file, no spaces or single quotes\n\
+    TO file - output results to file, may be enclosed in single quotes\n\
+    TPn  - turn on tracing when point n added to hull\n\
+     TMn - turn on tracing at merge n\n\
+     TWn - trace merge facets when width > n\n\
+    TVn  - stop qhull after adding point n, -n for before (see TCn)\n\
+     TCn - stop qhull after building cone for point n (see TVn)\n\
+\n\
+Precision options:\n\
+    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
+     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
+           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
+    Un   - max distance below plane for a new, coplanar point\n\
+    Wn   - min facet width for outside point (before roundoff)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+    f    - facet dump\n\
+    G    - Geomview output (see below)\n\
+    i    - vertices incident to each facet\n\
+    m    - Mathematica output (2-d and 3-d)\n\
+    n    - normals with offsets\n\
+    o    - OFF file format (dim, points and facets; Voronoi regions)\n\
+    p    - point coordinates \n\
+    s    - summary (stderr)\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+    Fa   - area for each facet\n\
+    FA   - compute total area and volume for option 's'\n\
+    Fc   - count plus coplanar points for each facet\n\
+           use 'Qc' (default) for coplanar and 'Qi' for interior\n\
+    FC   - centrum for each facet\n\
+    Fd   - use cdd format for input (homogeneous with offset first)\n\
+    FD   - use cdd format for numeric output (offset first)\n\
+    FF   - facet dump without ridges\n\
+    Fi   - inner plane for each facet\n\
+    FI   - ID for each facet\n\
+    Fm   - merge count for each facet (511 max)\n\
+    Fn   - count plus neighboring facets for each facet\n\
+    FN   - count plus neighboring facets for each point\n\
+    Fo   - outer plane (or max_outside) for each facet\n\
+    FO   - options and precision constants\n\
+    FP   - nearest vertex for each coplanar point\n\
+    FQ   - command used for qconvex\n\
+    Fs   - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
+                      for output: #vertices, #facets,\n\
+                                  #coplanar points, #non-simplicial facets\n\
+                    #real (2), max outer plane, min vertex\n\
+    FS   - sizes:   #int (0) \n\
+                    #real(2) tot area, tot volume\n\
+    Ft   - triangulation with centrums for non-simplicial facets (OFF format)\n\
+    Fv   - count plus vertices for each facet\n\
+    FV   - average of vertices (a feasible point for 'H')\n\
+    Fx   - extreme points (in order for 2-d)\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview output (2-d, 3-d, and 4-d)\n\
+    Ga   - all points as dots\n\
+     Gp  -  coplanar points and vertices as radii\n\
+     Gv  -  vertices as spheres\n\
+    Gi   - inner planes only\n\
+     Gn  -  no planes\n\
+     Go  -  outer planes only\n\
+    Gc   - centrums\n\
+    Gh   - hyperplane intersections\n\
+    Gr   - ridges\n\
+    GDn  - drop dimension n in 3-d and 4-d output\n\
+\n\
+Print options:\n\
+    PAn  - keep n largest facets by area\n\
+    Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
+    PDk:n - drop facet if normal[k] >= n\n\
+    Pg   - print good facets (needs 'QGn' or 'QVn')\n\
+    PFn  - keep facets whose area is at least n\n\
+    PG   - print neighbors of good facets\n\
+    PMn  - keep n facets with most merges\n\
+    Po   - force output.  If error, output neighborhood of facet\n\
+    Pp   - do not report precision problems\n\
+\n\
+    .    - list of all options\n\
+    -    - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt2
+    synopsis for qhull 
+*/  
+char qh_prompt2[]= "\n\
+qconvex- compute the convex hull.  Qhull %s\n\
+    input (stdin): dimension, number of points, point coordinates\n\
+    comments start with a non-numeric character\n\
+\n\
+options (qconvex.htm):\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+    Tv   - verify result: structure, convexity, and point inclusion\n\
+    .    - concise list of all options\n\
+    -    - one-line description of all options\n\
+\n\
+output options (subset):\n\
+    s    - summary of results (default)\n\
+    i    - vertices incident to each facet\n\
+    n    - normals with offsets\n\
+    p    - vertex coordinates (includes coplanar points if 'Qc')\n\
+    Fx   - extreme points (convex hull vertices)\n\
+    FA   - compute total area and volume\n\
+    o    - OFF format (dim, n, points, facets)\n\
+    G    - Geomview output (2-d, 3-d, and 4-d)\n\
+    m    - Mathematica output (2-d and 3-d)\n\
+    QVn  - print facets that include point n, -n if not\n\
+    TO file- output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+    rbox c D2 | qconvex s n                    rbox c D2 | qconvex i\n\
+    rbox c D2 | qconvex o                      rbox 1000 s | qconvex s Tv FA\n\
+    rbox c d D2 | qconvex s Qc Fx              rbox y 1000 W0 | qconvex s n\n\
+    rbox y 1000 W0 | qconvex s QJ              rbox d G1 D12 | qconvex QR0 FA Pp\n\
+    rbox c D7 | qconvex FA TF1000\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt3
+    concise prompt for qhull 
+*/  
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper-case options take an argument.\n\
+\n\
+ incidences     mathematica    normals        OFF_format     points\n\
+ summary        facet_dump\n\
+\n\
+ Farea          FArea_total    Fcoplanars     FCentrums      Fd_cdd_in\n\
+ FD_cdd_out     FFacet_xridge  Finner         FIDs           Fmerges\n\
+ Fneighbors     FNeigh_vertex  Fouter         FOptions       FPoint_near\n\
+ FQhull         Fsummary       FSize          Fvertices      FVertex_ave\n\
+ Fxtremes       FMaple\n\
+\n\
+ Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
+ Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
+\n\
+ PArea_keep     Pdrop d0:0D0   PFacet_area_keep Pgood        PGood_neighbors\n\
+ PMerge_keep    Poutput_forced Pprecision_not\n\
+\n\
+ QbBound 0:0.5  QbB_scale_box  Qcoplanar      QGood_point    Qinterior\n\
+ QJoggle        Qrandom        QRotate        Qsearch_1st    Qtriangulate\n\
+ QVertex_good\n\
+\n\
+ T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
+ TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
+ TWide_trace    TVertex_stop   TCone_stop\n\
+\n\
+ Angle_max      Centrum_size   Random_dist    Ucoplanar_max  Wide_outside\n\
+";
+
+/*---------------------------------
+  
+  main( argc, argv )
+    processes the command line, calls qhull() to do the work, and exits
+  
+  design:
+    initializes data structures
+    reads points
+    finishes initialization
+    computes convex hull and other structures
+    checks the result
+    writes the output
+    frees memory
+*/
+int main(int argc, char *argv[]) {
+  int curlong, totlong; /* used !qh_NOmem */
+  int exitcode, numpoints, dim;
+  coordT *points;
+  boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+  SIOUXSettings.showstatusline= false;
+  SIOUXSettings.tabspaces= 1;
+  SIOUXSettings.rows= 40;
+  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
+  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
+    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+  argc= ccommand(&argv);
+#endif
+
+  if ((argc == 1) && isatty( 0 /*stdin*/)) {      
+    fprintf(stdout, qh_prompt2, qh_version);
+    exit(qh_ERRnone);
+  }
+  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompta, qh_version, qh_DEFAULTbox, 
+		qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+    exit(qh_ERRnone);
+  }
+  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompt3, qh_version);
+    exit(qh_ERRnone);
+  }
+  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
+  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+  if (!exitcode) {
+    qh_checkflags (qh qhull_command, hidden_options);
+    qh_initflags (qh qhull_command);
+    points= qh_readpoints (&numpoints, &dim, &ismalloc);
+    if (dim >= 5) {
+      qh_option ("Qxact_merge", NULL, NULL);
+      qh MERGEexact= True; /* 'Qx' always */
+    }
+    qh_init_B (points, numpoints, dim, ismalloc);
+    qh_qhull();
+    qh_check_output();
+    qh_produce_output();
+    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points();
+    exitcode= qh_ERRnone;
+  }
+  qh NOerrexit= True;  /* no more setjmp */
+#ifdef qh_NOmem
+  qh_freeqhull( True);
+#else
+  qh_freeqhull( False);
+  qh_memfreeshort (&curlong, &totlong);
+  if (curlong || totlong) 
+    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+       totlong, curlong);
+#endif
+  return exitcode;
+} /* main */
+

Added: trunk/scipy/spatial/qhull/src/qdelaun.c
===================================================================
--- trunk/scipy/spatial/qhull/src/qdelaun.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qdelaun.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,324 @@
+/*
  ---------------------------------
+
+   qdelaun.c
+     compute Delaunay triangulations and furthest-point Delaunay
+     triangulations using qhull
+
+   see unix.c for full interface
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include 
+#include 
+#include 
+#include 
+
+#elif __cplusplus
+extern "C" {
+  int isatty (int);
+}
+
+#elif _MSC_VER
+#include 
+#define isatty _isatty
+
+#else
+int isatty (int);  /* returns 1 if stdin is a tty
+		   if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*---------------------------------
+
+  qh_prompt 
+    long prompt for qhull
+    
+  notes:
+    restricted version of qhull.c
+ 
+  see:
+    concise prompt below
+*/  
+
+/* duplicated in qdelau_f.htm and qdelaun.htm */
+char hidden_options[]=" d n v H U Qb QB Qc Qf Qg Qi Qm Qr QR Qv Qx TR E V FC Fi Fo Ft Fp FV Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
+
+char qh_prompta[]= "\n\
+qdelaunay- compute the Delaunay triangulation\n\
+    http://www.qhull.org  %s\n\
+\n\
+input (stdin):\n\
+    first lines: dimension and number of points (or vice-versa).\n\
+    other lines: point coordinates, best if one point per line\n\
+    comments:    start with a non-numeric character\n\
+\n\
+options:\n\
+    Qu   - compute furthest-site Delaunay triangulation\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+\n\
+Qhull control options:\n\
+    QJn  - randomly joggle input in range [-n,n]\n\
+%s%s%s%s";  /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+    Qs   - search all points for the initial simplex\n\
+    Qz   - add point-at-infinity to Delaunay triangulation\n\
+    QGn  - print Delaunay region if visible from point n, -n if not\n\
+    QVn  - print Delaunay regions that include point n, -n if not\n\
+\n\
+";
+char qh_promptc[]= "\
+Trace options:\n\
+    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+    Tc   - check frequently during execution\n\
+    Ts   - print statistics\n\
+    Tv   - verify result: structure, convexity, and in-circle test\n\
+    Tz   - send all output to stdout\n\
+    TFn  - report summary when n or more facets created\n\
+    TI file - input data from file, no spaces or single quotes\n\
+    TO file - output results to file, may be enclosed in single quotes\n\
+    TPn  - turn on tracing when point n added to hull\n\
+     TMn - turn on tracing at merge n\n\
+     TWn - trace merge facets when width > n\n\
+    TVn  - stop qhull after adding point n, -n for before (see TCn)\n\
+     TCn - stop qhull after building cone for point n (see TVn)\n\
+\n\
+Precision options:\n\
+    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
+     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
+           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
+    Wn   - min facet width for outside point (before roundoff)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+    f    - facet dump\n\
+    G    - Geomview output (see below)\n\
+    i    - vertices incident to each Delaunay region\n\
+    m    - Mathematica output (2-d only, lifted to a paraboloid)\n\
+    o    - OFF format (dim, points, and facets as a paraboloid)\n\
+    p    - point coordinates (lifted to a paraboloid)\n\
+    s    - summary (stderr)\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+    Fa   - area for each Delaunay region\n\
+    FA   - compute total area for option 's'\n\
+    Fc   - count plus coincident points for each Delaunay region\n\
+    Fd   - use cdd format for input (homogeneous with offset first)\n\
+    FD   - use cdd format for numeric output (offset first)\n\
+    FF   - facet dump without ridges\n\
+    FI   - ID of each Delaunay region\n\
+    Fm   - merge count for each Delaunay region (511 max)\n\
+    FM   - Maple output (2-d only, lifted to a paraboloid)\n\
+    Fn   - count plus neighboring region for each Delaunay region\n\
+    FN   - count plus neighboring region for each point\n\
+    FO   - options and precision constants\n\
+    FP   - nearest point and distance for each coincident point\n\
+    FQ   - command used for qdelaunay\n\
+    Fs   - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
+                    for output: #vertices, #Delaunay regions,\n\
+                                #coincident points, #non-simplicial regions\n\
+                    #real (2), max outer plane, min vertex\n\
+    FS   - sizes:   #int (0)\n\
+                    #real(2) tot area, 0\n\
+    Fv   - count plus vertices for each Delaunay region\n\
+    Fx   - extreme points of Delaunay triangulation (on convex hull)\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview options (2-d and 3-d)\n\
+    Ga   - all points as dots\n\
+     Gp  -  coplanar points and vertices as radii\n\
+     Gv  -  vertices as spheres\n\
+    Gi   - inner planes only\n\
+     Gn  -  no planes\n\
+     Go  -  outer planes only\n\
+    Gc	   - centrums\n\
+    Gh   - hyperplane intersections\n\
+    Gr   - ridges\n\
+    GDn  - drop dimension n in 3-d and 4-d output\n\
+    Gt   - transparent outer ridges to view 3-d Delaunay\n\
+\n\
+Print options:\n\
+    PAn  - keep n largest Delaunay regions by area\n\
+    Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
+    PDk:n - drop facet if normal[k] >= n\n\
+    Pg   - print good Delaunay regions (needs 'QGn' or 'QVn')\n\
+    PFn  - keep Delaunay regions whose area is at least n\n\
+    PG   - print neighbors of good regions (needs 'QGn' or 'QVn')\n\
+    PMn  - keep n Delaunay regions with most merges\n\
+    Po   - force output.  If error, output neighborhood of facet\n\
+    Pp   - do not report precision problems\n\
+\n\
+    .    - list of all options\n\
+    -    - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt2
+    synopsis for qhull 
+*/  
+char qh_prompt2[]= "\n\
+qdelaunay- compute the Delaunay triangulation.  Qhull %s\n\
+    input (stdin): dimension, number of points, point coordinates\n\
+    comments start with a non-numeric character\n\
+\n\
+options (qdelaun.htm):\n\
+    Qu   - furthest-site Delaunay triangulation\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+    Tv   - verify result: structure, convexity, and in-circle test\n\
+    .    - concise list of all options\n\
+    -    - one-line description of all options\n\
+\n\
+output options (subset):\n\
+    s    - summary of results (default)\n\
+    i    - vertices incident to each Delaunay region\n\
+    Fx   - extreme points (vertices of the convex hull)\n\
+    o    - OFF format (shows the points lifted to a paraboloid)\n\
+    G    - Geomview output (2-d and 3-d points lifted to a paraboloid)\n\
+    m    - Mathematica output (2-d inputs lifted to a paraboloid)\n\
+    QVn  - print Delaunay regions that include point n, -n if not\n\
+    TO file- output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+    rbox c P0 D2 | qdelaunay s o          rbox c P0 D2 | qdelaunay i\n\
+    rbox c P0 D2 | qdelaunay Fv           rbox c P0 D2 | qdelaunay s Qu Fv\n\
+    rbox c G1 d D2 | qdelaunay s i        rbox c G1 d D2 | qdelaunay Qt\n\
+    rbox M3,4 z 100 D2 | qdelaunay s      rbox M3,4 z 100 D2 | qdelaunay s Qt\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt3
+    concise prompt for qhull 
+*/  
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper-case options take an argument.\n\
+\n\
+ incidences     mathematica    OFF_format     points_lifted  summary\n\
+ facet_dump\n\
+\n\
+ Farea          FArea_total    Fcoincident    Fd_cdd_in      FD_cdd_out\n\
+ FF_dump_xridge FIDs           Fmerges        Fneighbors     FNeigh_vertex\n\
+ FOptions       FPoint_near    FQdelaun       Fsummary       FSize\n\
+ Fvertices      Fxtremes       FMaple\n\
+\n\
+ Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
+ Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
+ Gtransparent\n\
+\n\
+ PArea_keep     Pdrop d0:0D0   Pgood          PFacet_area_keep\n\
+ PGood_neighbors PMerge_keep   Poutput_forced Pprecision_not\n\
+\n\
+ QGood_point    QJoggle        Qsearch_1st    Qtriangulate   QupperDelaunay\n\
+ QVertex_good   Qzinfinite\n\
+\n\
+ T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
+ TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
+ TWide_trace    TVertex_stop   TCone_stop\n\
+\n\
+ Angle_max      Centrum_size   Random_dist    Wide_outside\n\
+";
+
+/*---------------------------------
+  
+  main( argc, argv )
+    processes the command line, calls qhull() to do the work, and exits
+  
+  design:
+    initializes data structures
+    reads points
+    finishes initialization
+    computes convex hull and other structures
+    checks the result
+    writes the output
+    frees memory
+*/
+int main(int argc, char *argv[]) {
+  int curlong, totlong; /* used !qh_NOmem */
+  int exitcode, numpoints, dim;
+  coordT *points;
+  boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+  SIOUXSettings.showstatusline= false;
+  SIOUXSettings.tabspaces= 1;
+  SIOUXSettings.rows= 40;
+  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
+  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
+    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+  argc= ccommand(&argv);
+#endif
+
+  if ((argc == 1) && isatty( 0 /*stdin*/)) {      
+    fprintf(stdout, qh_prompt2, qh_version);
+    exit(qh_ERRnone);
+  }
+  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompta, qh_version,
+		qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+    exit(qh_ERRnone);
+  }
+  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompt3, qh_version);
+    exit(qh_ERRnone);
+  }
+  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
+  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+  if (!exitcode) {
+    qh_option ("delaunay  Qbbound-last", NULL, NULL);
+    qh DELAUNAY= True;     /* 'd'   */
+    qh SCALElast= True;    /* 'Qbb' */
+    qh KEEPcoplanar= True; /* 'Qc', to keep coplanars in 'p' */
+    qh_checkflags (qh qhull_command, hidden_options);
+    qh_initflags (qh qhull_command);
+    points= qh_readpoints (&numpoints, &dim, &ismalloc);
+    if (dim >= 5) {
+      qh_option ("Qxact_merge", NULL, NULL);
+      qh MERGEexact= True; /* 'Qx' always */
+    }
+    qh_init_B (points, numpoints, dim, ismalloc);
+    qh_qhull();
+    qh_check_output();
+    qh_produce_output();
+    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points();
+    exitcode= qh_ERRnone;
+  }
+  qh NOerrexit= True;  /* no more setjmp */
+#ifdef qh_NOmem
+  qh_freeqhull( True);
+#else
+  qh_freeqhull( False);
+  qh_memfreeshort (&curlong, &totlong);
+  if (curlong || totlong) 
+    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+       totlong, curlong);
+#endif
+  return exitcode;
+} /* main */
+

Added: trunk/scipy/spatial/qhull/src/qhalf.c
===================================================================
--- trunk/scipy/spatial/qhull/src/qhalf.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qhalf.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,325 @@
+/*
  ---------------------------------
+
+   qhalf.c
+     compute the intersection of halfspaces about a point
+
+   see unix.c for full interface
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include 
+#include 
+#include 
+#include 
+
+#elif __cplusplus
+extern "C" {
+  int isatty (int);
+}
+
+#elif _MSC_VER
+#include 
+#define isatty _isatty
+
+#else
+int isatty (int);  /* returns 1 if stdin is a tty
+		   if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*---------------------------------
+
+  qh_prompt 
+    long prompt for qhull
+    
+  notes:
+    restricted version of qhull.c
+ 
+  see:
+    concise prompt below
+*/  
+
+/* duplicated in qhalf.htm */
+char hidden_options[]=" d n v Qbb QbB Qf Qg Qm Qr QR Qv Qx Qz TR E V Fa FA FC FD FS Ft FV Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
+
+char qh_prompta[]= "\n\
+qhalf- compute the intersection of halfspaces about a point\n\
+    http://www.qhull.org  %s\n\
+\n\
+input (stdin):\n\
+    optional interior point: dimension, 1, coordinates\n\
+    first lines: dimension+1 and number of halfspaces\n\
+    other lines: halfspace coefficients followed by offset\n\
+    comments:    start with a non-numeric character\n\
+\n\
+options:\n\
+    Hn,n - specify coordinates of interior point\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+    Qc   - keep coplanar halfspaces\n\
+    Qi   - keep other redundant halfspaces\n\
+\n\
+Qhull control options:\n\
+    QJn  - randomly joggle input in range [-n,n]\n\
+%s%s%s%s";  /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+    Qbk:0Bk:0 - remove k-th coordinate from input\n\
+    Qs   - search all halfspaces for the initial simplex\n\
+    QGn  - print intersection if visible to halfspace n, -n for not\n\
+    QVn  - print intersections for halfspace n, -n if not\n\
+\n\
+";
+char qh_promptc[]= "\
+Trace options:\n\
+    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+    Tc   - check frequently during execution\n\
+    Ts   - print statistics\n\
+    Tv   - verify result: structure, convexity, and redundancy\n\
+    Tz   - send all output to stdout\n\
+    TFn  - report summary when n or more facets created\n\
+    TI file - input data from file, no spaces or single quotes\n\
+    TO file - output results to file, may be enclosed in single quotes\n\
+    TPn  - turn on tracing when halfspace n added to intersection\n\
+    TMn  - turn on tracing at merge n\n\
+    TWn  - trace merge facets when width > n\n\
+    TVn  - stop qhull after adding halfspace n, -n for before (see TCn)\n\
+    TCn  - stop qhull after building cone for halfspace n (see TVn)\n\
+\n\
+Precision options:\n\
+    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
+     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
+           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
+    Un   - max distance below plane for a new, coplanar halfspace\n\
+    Wn   - min facet width for outside halfspace (before roundoff)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+    f    - facet dump\n\
+    G    - Geomview output (dual convex hull)\n\
+    i    - non-redundant halfspaces incident to each intersection\n\
+    m    - Mathematica output (dual convex hull)\n\
+    o    - OFF format (dual convex hull: dimension, points, and facets)\n\
+    p    - vertex coordinates of dual convex hull (coplanars if 'Qc' or 'Qi')\n\
+    s    - summary (stderr)\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+    Fc   - count plus redundant halfspaces for each intersection\n\
+         -   Qc (default) for coplanar and Qi for other redundant\n\
+    Fd   - use cdd format for input (homogeneous with offset first)\n\
+    FF   - facet dump without ridges\n\
+    FI   - ID of each intersection\n\
+    Fm   - merge count for each intersection (511 max)\n\
+    FM   - Maple output (dual convex hull)\n\
+    Fn   - count plus neighboring intersections for each intersection\n\
+    FN   - count plus intersections for each non-redundant halfspace\n\
+    FO   - options and precision constants\n\
+    Fp   - dim, count, and intersection coordinates\n\
+    FP   - nearest halfspace and distance for each redundant halfspace\n\
+    FQ   - command used for qhalf\n\
+    Fs   - summary: #int (8), dim, #halfspaces, #non-redundant, #intersections\n\
+                      for output: #non-redundant, #intersections, #coplanar\n\
+                                  halfspaces, #non-simplicial intersections\n\
+                    #real (2), max outer plane, min vertex\n\
+    Fv   - count plus non-redundant halfspaces for each intersection\n\
+    Fx   - non-redundant halfspaces\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview output (2-d, 3-d and 4-d; dual convex hull)\n\
+    Ga   - all points (i.e., transformed halfspaces) as dots\n\
+     Gp  -  coplanar points and vertices as radii\n\
+     Gv  -  vertices (i.e., non-redundant halfspaces) as spheres\n\
+    Gi   - inner planes (i.e., halfspace intersections) only\n\
+     Gn  -  no planes\n\
+     Go  -  outer planes only\n\
+    Gc	 - centrums\n\
+    Gh   - hyperplane intersections\n\
+    Gr   - ridges\n\
+    GDn  - drop dimension n in 3-d and 4-d output\n\
+\n\
+Print options:\n\
+    PAn  - keep n largest facets (i.e., intersections) by area\n\
+    Pdk:n- drop facet if normal[k] <= n (default 0.0)\n\
+    PDk:n- drop facet if normal[k] >= n\n\
+    Pg   - print good facets (needs 'QGn' or 'QVn')\n\
+    PFn  - keep facets whose area is at least n\n\
+    PG   - print neighbors of good facets\n\
+    PMn  - keep n facets with most merges\n\
+    Po   - force output.  If error, output neighborhood of facet\n\
+    Pp   - do not report precision problems\n\
+\n\
+    .    - list of all options\n\
+    -    - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt2
+    synopsis for qhull 
+*/  
+char qh_prompt2[]= "\n\
+qhalf- halfspace intersection about a point.  Qhull %s\n\
+    input (stdin): [dim, 1, interior point], dim+1, n, coefficients+offset\n\
+    comments start with a non-numeric character\n\
+\n\
+options (qhalf.htm):\n\
+    Hn,n - specify coordinates of interior point\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+    Tv   - verify result: structure, convexity, and redundancy\n\
+    .    - concise list of all options\n\
+    -    - one-line description of all options\n\
+\n\
+output options (subset):\n\
+    s    - summary of results (default)\n\
+    Fp   - intersection coordinates\n\
+    Fv   - non-redundant halfspaces incident to each intersection\n\
+    Fx   - non-redundant halfspaces\n\
+    o    - OFF file format (dual convex hull)\n\
+    G    - Geomview output (dual convex hull)\n\
+    m    - Mathematica output (dual convex hull)\n\
+    QVn  - print intersections for halfspace n, -n if not\n\
+    TO file - output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+    rbox d | qconvex FQ n | qhalf s H0,0,0 Fp\n\
+    rbox c | qconvex FQ FV n | qhalf s i\n\
+    rbox c | qconvex FQ FV n | qhalf s o\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt3
+    concise prompt for qhull 
+*/  
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper_case options take an argument.\n\
+\n\
+ incidences     Geomview       mathematica    OFF_format     point_dual\n\
+ summary        facet_dump\n\
+\n\
+ Fc_redundant   Fd_cdd_in      FF_dump_xridge FIDs           Fmerges\n\
+ Fneighbors     FN_intersect   FOptions       Fp_coordinates FP_nearest\n\
+ FQhalf         Fsummary       Fv_halfspace   FMaple         Fx_non_redundant\n\
+\n\
+ Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
+ Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
+\n\
+ PArea_keep     Pdrop d0:0D0   Pgood          PFacet_area_keep\n\
+ PGood_neighbors PMerge_keep   Poutput_forced Pprecision_not\n\
+\n\
+ Qbk:0Bk:0_drop Qcoplanar      QG_half_good   Qi_redundant   QJoggle\n\
+ Qsearch_1st    Qtriangulate   QVertex_good\n\
+\n\
+ T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
+ TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
+ TWide_trace    TVertex_stop   TCone_stop\n\
+\n\
+ Angle_max      Centrum_size   Random_dist    Ucoplanar_max  Wide_outside\n\
+";
+
+/*---------------------------------
+  
+  main( argc, argv )
+    processes the command line, calls qhull() to do the work, and exits
+  
+  design:
+    initializes data structures
+    reads points
+    finishes initialization
+    computes convex hull and other structures
+    checks the result
+    writes the output
+    frees memory
+*/
+int main(int argc, char *argv[]) {
+  int curlong, totlong; /* used !qh_NOmem */
+  int exitcode, numpoints, dim;
+  coordT *points;
+  boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+  SIOUXSettings.showstatusline= false;
+  SIOUXSettings.tabspaces= 1;
+  SIOUXSettings.rows= 40;
+  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
+  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
+    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+  argc= ccommand(&argv);
+#endif
+
+  if ((argc == 1) && isatty( 0 /*stdin*/)) {      
+    fprintf(stdout, qh_prompt2, qh_version);
+    exit(qh_ERRnone);
+  }
+  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompta, qh_version, 
+        qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+    exit(qh_ERRnone);
+  }
+  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompt3, qh_version);
+    exit(qh_ERRnone);
+  }
+  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
+  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+  if (!exitcode) {
+    qh_option ("Halfspace", NULL, NULL);
+    qh HALFspace= True;    /* 'H'   */
+    qh_checkflags (qh qhull_command, hidden_options);
+    qh_initflags (qh qhull_command);
+    if (qh SCALEinput) {
+      fprintf(qh ferr, "\
+qhull error: options 'Qbk:n' and 'QBk:n' are not used with qhalf.\n\
+             Use 'Qbk:0Bk:0 to drop dimension k.\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    points= qh_readpoints (&numpoints, &dim, &ismalloc);
+    if (dim >= 5) {
+      qh_option ("Qxact_merge", NULL, NULL);
+      qh MERGEexact= True; /* 'Qx' always */
+    }
+    qh_init_B (points, numpoints, dim, ismalloc);
+    qh_qhull();
+    qh_check_output();
+    qh_produce_output();
+    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points();
+    exitcode= qh_ERRnone;
+  }
+  qh NOerrexit= True;  /* no more setjmp */
+#ifdef qh_NOmem
+  qh_freeqhull( True);
+#else
+  qh_freeqhull( False);
+  qh_memfreeshort (&curlong, &totlong);
+  if (curlong || totlong) 
+    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+       totlong, curlong);
+#endif
+  return exitcode;
+} /* main */
+

Added: trunk/scipy/spatial/qhull/src/qhull.c
===================================================================
--- trunk/scipy/spatial/qhull/src/qhull.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qhull.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,1396 @@
+/*
  ---------------------------------
+
+   qhull.c
+   Quickhull algorithm for convex hulls
+
+   qhull() and top-level routines
+
+   see qh-qhull.htm, qhull.h, unix.c
+
+   see qhull_a.h for internal functions
+
+   copyright (c) 1993-2003 The Geometry Center        
+*/
+
+#include "qhull_a.h" 
+
+/*============= functions in alphabetic order after qhull() =======*/
+
+/*---------------------------------
+  
+  qh_qhull()
+    compute DIM3 convex hull of qh.num_points starting at qh.first_point
+    qh contains all global options and variables
+
+  returns:
+    returns polyhedron
+      qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices,
+    
+    returns global variables
+      qh.hulltime, qh.max_outside, qh.interior_point, qh.max_vertex, qh.min_vertex
+    
+    returns precision constants
+      qh.ANGLEround, centrum_radius, cos_max, DISTround, MAXabs_coord, ONEmerge
+
+  notes:
+    unless needed for output
+      qh.max_vertex and qh.min_vertex are max/min due to merges
+      
+  see:
+    to add individual points to either qh.num_points
+      use qh_addpoint()
+      
+    if qh.GETarea
+      qh_produceoutput() returns qh.totarea and qh.totvol via qh_getarea()
+
+  design:
+    record starting time
+    initialize hull and partition points
+    build convex hull
+    unless early termination
+      update facet->maxoutside for vertices, coplanar, and near-inside points
+    error if temporary sets exist
+    record end time
+*/
+
+void qh_qhull (void) {
+  int numoutside;
+
+  qh hulltime= qh_CPUclock;
+  if (qh RERUN || qh JOGGLEmax < REALmax/2) 
+    qh_build_withrestart();
+  else {
+    qh_initbuild();
+    qh_buildhull();
+  }
+  if (!qh STOPpoint && !qh STOPcone) {
+    if (qh ZEROall_ok && !qh TESTvneighbors && qh MERGEexact)
+      qh_checkzero( qh_ALL);
+    if (qh ZEROall_ok && !qh TESTvneighbors && !qh WAScoplanar) {
+      trace2((qh ferr, "qh_qhull: all facets are clearly convex and no coplanar points.  Post-merging and check of maxout not needed.\n"));
+      qh DOcheckmax= False;
+    }else {
+      if (qh MERGEexact || (qh hull_dim > qh_DIMreduceBuild && qh PREmerge))
+        qh_postmerge ("First post-merge", qh premerge_centrum, qh premerge_cos, 
+             (qh POSTmerge ? False : qh TESTvneighbors));
+      else if (!qh POSTmerge && qh TESTvneighbors) 
+        qh_postmerge ("For testing vertex neighbors", qh premerge_centrum,
+             qh premerge_cos, True); 
+      if (qh POSTmerge)
+        qh_postmerge ("For post-merging", qh postmerge_centrum, 
+             qh postmerge_cos, qh TESTvneighbors);
+      if (qh visible_list == qh facet_list) { /* i.e., merging done */
+        qh findbestnew= True;
+        qh_partitionvisible (/*visible_list, newfacet_list*/ !qh_ALL, &numoutside);
+        qh findbestnew= False;
+        qh_deletevisible (/*qh visible_list*/);
+        qh_resetlists (False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+      }
+    }
+    if (qh DOcheckmax){
+      if (qh REPORTfreq) {
+	qh_buildtracing (NULL, NULL); 
+	fprintf (qh ferr, "\nTesting all coplanar points.\n");
+      }
+      qh_check_maxout();
+    }
+    if (qh KEEPnearinside && !qh maxoutdone)  
+      qh_nearcoplanar();
+  }
+  if (qh_setsize ((setT*)qhmem.tempstack) != 0) {
+    fprintf (qh ferr, "qhull internal error (qh_qhull): temporary sets not empty (%d)\n",
+	     qh_setsize ((setT*)qhmem.tempstack));
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  qh hulltime= qh_CPUclock - qh hulltime;
+  qh QHULLfinished= True;
+  trace1((qh ferr, "qh_qhull: algorithm completed\n"));
+} /* qhull */
+
+/*---------------------------------
+  
+  qh_addpoint( furthest, facet, checkdist )
+    add point (usually furthest point) above facet to hull 
+    if checkdist, 
+      check that point is above facet.
+      if point is not outside of the hull, uses qh_partitioncoplanar()
+      assumes that facet is defined by qh_findbestfacet()
+    else if facet specified,
+      assumes that point is above facet (major damage if below)
+    for Delaunay triangulations, 
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates. 
+
+  returns:
+    returns False if user requested an early termination
+     qh.visible_list, newfacet_list, delvertex_list, NEWfacets may be defined
+    updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
+    clear qh.maxoutdone (will need to call qh_check_maxout() for facet->maxoutside)
+    if unknown point, adds a pointer to qh.other_points
+      do not deallocate the point's coordinates
+  
+  notes:
+    assumes point is near its best facet and not at a local minimum of a lens
+      distributions.  Use qh_findbestfacet to avoid this case.
+    uses qh.visible_list, qh.newfacet_list, qh.delvertex_list, qh.NEWfacets
+
+  see also:
+    qh_triangulate() -- triangulate non-simplicial facets
+
+  design:
+    check point in qh.first_point/.num_points
+    if checkdist
+      if point not above facet
+        partition coplanar point 
+        exit
+    exit if pre STOPpoint requested
+    find horizon and visible facets for point
+    make new facets for point to horizon
+    make hyperplanes for point
+    compute balance statistics
+    match neighboring new facets
+    update vertex neighbors and delete interior vertices
+    exit if STOPcone requested
+    merge non-convex new facets
+    if merge found, many merges, or 'Qf'
+       use qh_findbestnew() instead of qh_findbest()
+    partition outside points from visible facets
+    delete visible facets
+    check polyhedron if requested
+    exit if post STOPpoint requested
+    reset working lists of facets and vertices
+*/
+boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist) {
+  int goodvisible, goodhorizon;
+  vertexT *vertex;
+  facetT *newfacet;
+  realT dist, newbalance, pbalance;
+  boolT isoutside= False;
+  int numpart, numpoints, numnew, firstnew;
+
+  qh maxoutdone= False;
+  if (qh_pointid (furthest) == -1)
+    qh_setappend (&qh other_points, furthest);
+  if (!facet) {
+    fprintf (qh ferr, "qh_addpoint: NULL facet.  Need to call qh_findbestfacet first\n");
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  if (checkdist) {
+    facet= qh_findbest (furthest, facet, !qh_ALL, !qh_ISnewfacets, !qh_NOupper,
+			&dist, &isoutside, &numpart);
+    zzadd_(Zpartition, numpart);
+    if (!isoutside) {
+      zinc_(Znotmax);  /* last point of outsideset is no longer furthest. */
+      facet->notfurthest= True;
+      qh_partitioncoplanar (furthest, facet, &dist);
+      return True;
+    }
+  }
+  qh_buildtracing (furthest, facet);
+  if (qh STOPpoint < 0 && qh furthest_id == -qh STOPpoint-1) {
+    facet->notfurthest= True;
+    return False;
+  }
+  qh_findhorizon (furthest, facet, &goodvisible, &goodhorizon); 
+  if (qh ONLYgood && !(goodvisible+goodhorizon) && !qh GOODclosest) {
+    zinc_(Znotgood);  
+    facet->notfurthest= True;
+    /* last point of outsideset is no longer furthest.  This is ok
+       since all points of the outside are likely to be bad */
+    qh_resetlists (False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+    return True;
+  }
+  zzinc_(Zprocessed);
+  firstnew= qh facet_id;
+  vertex= qh_makenewfacets (furthest /*visible_list, attaches if !ONLYgood */);
+  qh_makenewplanes (/* newfacet_list */);
+  numnew= qh facet_id - firstnew;
+  newbalance= numnew - (realT) (qh num_facets-qh num_visible)
+                         * qh hull_dim/qh num_vertices;
+  wadd_(Wnewbalance, newbalance);
+  wadd_(Wnewbalance2, newbalance * newbalance);
+  if (qh ONLYgood 
+  && !qh_findgood (qh newfacet_list, goodhorizon) && !qh GOODclosest) {
+    FORALLnew_facets 
+      qh_delfacet (newfacet);
+    qh_delvertex (vertex);
+    qh_resetlists (True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+    zinc_(Znotgoodnew);
+    facet->notfurthest= True;
+    return True;
+  }
+  if (qh ONLYgood)
+    qh_attachnewfacets(/*visible_list*/);
+  qh_matchnewfacets();
+  qh_updatevertices();
+  if (qh STOPcone && qh furthest_id == qh STOPcone-1) {
+    facet->notfurthest= True;
+    return False;  /* visible_list etc. still defined */
+  }
+  qh findbestnew= False;
+  if (qh PREmerge || qh MERGEexact) {
+    qh_premerge (vertex, qh premerge_centrum, qh premerge_cos);
+    if (qh_USEfindbestnew)
+      qh findbestnew= True;
+    else {
+      FORALLnew_facets {
+	if (!newfacet->simplicial) {
+	  qh findbestnew= True;  /* use qh_findbestnew instead of qh_findbest*/
+	  break;
+	}
+      }
+    }
+  }else if (qh BESToutside)
+    qh findbestnew= True;
+  qh_partitionvisible (/*visible_list, newfacet_list*/ !qh_ALL, &numpoints);
+  qh findbestnew= False;
+  qh findbest_notsharp= False;
+  zinc_(Zpbalance);
+  pbalance= numpoints - (realT) qh hull_dim /* assumes all points extreme */
+                * (qh num_points - qh num_vertices)/qh num_vertices;
+  wadd_(Wpbalance, pbalance);
+  wadd_(Wpbalance2, pbalance * pbalance);
+  qh_deletevisible (/*qh visible_list*/);
+  zmax_(Zmaxvertex, qh num_vertices);
+  qh NEWfacets= False;
+  if (qh IStracing >= 4) {
+    if (qh num_facets < 2000)
+      qh_printlists();
+    qh_printfacetlist (qh newfacet_list, NULL, True);
+    qh_checkpolygon (qh facet_list);
+  }else if (qh CHECKfrequently) {
+    if (qh num_facets < 50)
+      qh_checkpolygon (qh facet_list);
+    else
+      qh_checkpolygon (qh newfacet_list);
+  }
+  if (qh STOPpoint > 0 && qh furthest_id == qh STOPpoint-1) 
+    return False; 
+  qh_resetlists (True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+  /* qh_triangulate(); to test qh.TRInormals */
+  trace2((qh ferr, "qh_addpoint: added p%d new facets %d new balance %2.2g point balance %2.2g\n",
+    qh_pointid (furthest), numnew, newbalance, pbalance));
+  return True;
+} /* addpoint */
+
+/*---------------------------------
+  
+  qh_build_withrestart()
+    allow restarts due to qh.JOGGLEmax while calling qh_buildhull()
+    qh.FIRSTpoint/qh.NUMpoints is point array
+        it may be moved by qh_joggleinput()
+*/
+void qh_build_withrestart (void) {
+  int restart;
+
+  qh ALLOWrestart= True;
+  while (True) {
+    restart= setjmp (qh restartexit); /* simple statement for CRAY J916 */
+    if (restart) {       /* only from qh_precision() */
+      zzinc_(Zretry);
+      wmax_(Wretrymax, qh JOGGLEmax);
+      qh ERREXITcalled= False;
+      qh STOPcone= True; /* if break, prevents normal output */
+    }
+    if (!qh RERUN && qh JOGGLEmax < REALmax/2) {
+      if (qh build_cnt > qh_JOGGLEmaxretry) {
+	fprintf(qh ferr, "\n\
+qhull precision error: %d attempts to construct a convex hull\n\
+        with joggled input.  Increase joggle above 'QJ%2.2g'\n\
+	or modify qh_JOGGLE... parameters in user.h\n",
+	   qh build_cnt, qh JOGGLEmax);
+	qh_errexit (qh_ERRqhull, NULL, NULL);
+      }
+      if (qh build_cnt && !restart)
+	break;
+    }else if (qh build_cnt && qh build_cnt >= qh RERUN)
+      break;
+    qh STOPcone= False;
+    qh_freebuild (True);  /* first call is a nop */
+    qh build_cnt++;
+    if (!qh qhull_optionsiz)
+      qh qhull_optionsiz= strlen (qh qhull_options);
+    else { 
+      qh qhull_options [qh qhull_optionsiz]= '\0';
+      qh qhull_optionlen= 80;
+    }
+    qh_option("_run", &qh build_cnt, NULL);
+    if (qh build_cnt == qh RERUN) {
+      qh IStracing= qh TRACElastrun;  /* duplicated from qh_initqhull_globals */
+      if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
+        qh TRACElevel= (qh IStracing? qh IStracing : 3);
+        qh IStracing= 0;
+      }
+      qhmem.IStracing= qh IStracing;
+    }
+    if (qh JOGGLEmax < REALmax/2)
+      qh_joggleinput();
+    qh_initbuild();
+    qh_buildhull();
+    if (qh JOGGLEmax < REALmax/2 && !qh MERGING)
+      qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
+  }
+  qh ALLOWrestart= False;
+} /* qh_build_withrestart */
+
+/*---------------------------------
+  
+  qh_buildhull()
+    construct a convex hull by adding outside points one at a time
+
+  returns:
+  
+  notes:
+    may be called multiple times
+    checks facet and vertex lists for incorrect flags
+    to recover from STOPcone, call qh_deletevisible and qh_resetlists
+
+  design:
+    check visible facet and newfacet flags
+    check newlist vertex flags and qh.STOPcone/STOPpoint
+    for each facet with a furthest outside point
+      add point to facet
+      exit if qh.STOPcone or qh.STOPpoint requested
+    if qh.NARROWhull for initial simplex
+      partition remaining outside points to coplanar sets
+*/
+void qh_buildhull(void) {
+  facetT *facet;
+  pointT *furthest;
+  vertexT *vertex;
+  int id;
+  
+  trace1((qh ferr, "qh_buildhull: start build hull\n"));
+  FORALLfacets {
+    if (facet->visible || facet->newfacet) {
+      fprintf (qh ferr, "qhull internal error (qh_buildhull): visible or new facet f%d in facet list\n",
+                   facet->id);    
+      qh_errexit (qh_ERRqhull, facet, NULL);
+    }
+  }
+  FORALLvertices {
+    if (vertex->newlist) {
+      fprintf (qh ferr, "qhull internal error (qh_buildhull): new vertex f%d in vertex list\n",
+                   vertex->id);
+      qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
+      qh_errexit (qh_ERRqhull, NULL, NULL);
+    }
+    id= qh_pointid (vertex->point);
+    if ((qh STOPpoint>0 && id == qh STOPpoint-1) ||
+	(qh STOPpoint<0 && id == -qh STOPpoint-1) ||
+	(qh STOPcone>0 && id == qh STOPcone-1)) {
+      trace1((qh ferr,"qh_buildhull: stop point or cone P%d in initial hull\n", id));
+      return;
+    }
+  }
+  qh facet_next= qh facet_list;      /* advance facet when processed */
+  while ((furthest= qh_nextfurthest (&facet))) {
+    qh num_outside--;  /* if ONLYmax, furthest may not be outside */
+    if (!qh_addpoint (furthest, facet, qh ONLYmax))
+      break;
+  }
+  if (qh NARROWhull) /* move points from outsideset to coplanarset */
+    qh_outcoplanar( /* facet_list */ );
+  if (qh num_outside && !furthest) {
+    fprintf (qh ferr, "qhull internal error (qh_buildhull): %d outside points were never processed.\n", qh num_outside);
+    qh_errexit (qh_ERRqhull, NULL, NULL);
+  }
+  trace1((qh ferr, "qh_buildhull: completed the hull construction\n"));
+} /* buildhull */
+  
+
+/*---------------------------------
+  
+  qh_buildtracing( furthest, facet )
+    trace an iteration of qh_buildhull() for furthest point and facet
+    if !furthest, prints progress message
+
+  returns:
+    tracks progress with qh.lastreport
+    updates qh.furthest_id (-3 if furthest is NULL)
+    also resets visit_id, vertext_visit on wrap around
+
+  see:
+    qh_tracemerging()
+
+  design:
+    if !furthest
+      print progress message
+      exit
+    if 'TFn' iteration
+      print progress message
+    else if tracing
+      trace furthest point and facet
+    reset qh.visit_id and qh.vertex_visit if overflow may occur
+    set qh.furthest_id for tracing
+*/
+void qh_buildtracing (pointT *furthest, facetT *facet) {
+  realT dist= 0;
+  float cpu;
+  int total, furthestid;
+  time_t timedata;
+  struct tm *tp;
+  vertexT *vertex;
+
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  if (!furthest) {
+    time (&timedata);
+    tp= localtime (&timedata);
+    cpu= qh_CPUclock - qh hulltime;
+    cpu /= qh_SECticks;
+    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+    fprintf (qh ferr, "\n\
+At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
+ The current hull contains %d facets and %d vertices.  Last point was p%d\n",
+      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
+      total, qh num_facets, qh num_vertices, qh furthest_id);
+    return;
+  }
+  furthestid= qh_pointid (furthest);
+  if (qh TRACEpoint == furthestid) {
+    qh IStracing= qh TRACElevel;
+    qhmem.IStracing= qh TRACElevel;
+  }else if (qh TRACEpoint != -1 && qh TRACEdist < REALmax/2) {
+    qh IStracing= 0;
+    qhmem.IStracing= 0;
+  }
+  if (qh REPORTfreq && (qh facet_id-1 > qh lastreport+qh REPORTfreq)) {
+    qh lastreport= qh facet_id-1;
+    time (&timedata);
+    tp= localtime (&timedata);
+    cpu= qh_CPUclock - qh hulltime;
+    cpu /= qh_SECticks;
+    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+    zinc_(Zdistio);
+    qh_distplane (furthest, facet, &dist);
+    fprintf (qh ferr, "\n\
+At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
+ The current hull contains %d facets and %d vertices.  There are %d\n\
+ outside points.  Next is point p%d (v%d), %2.2g above f%d.\n",
+      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
+      total, qh num_facets, qh num_vertices, qh num_outside+1,
+      furthestid, qh vertex_id, dist, getid_(facet));
+  }else if (qh IStracing >=1) {
+    cpu= qh_CPUclock - qh hulltime;
+    cpu /= qh_SECticks;
+    qh_distplane (furthest, facet, &dist);
+    fprintf (qh ferr, "qh_addpoint: add p%d (v%d) to hull of %d facets (%2.2g above f%d) and %d outside at %4.4g CPU secs.  Previous was p%d.\n",
+      furthestid, qh vertex_id, qh num_facets, dist,
+      getid_(facet), qh num_outside+1, cpu, qh furthest_id);
+  }
+  if (qh visit_id > (unsigned) INT_MAX) {
+    qh visit_id= 0;
+    FORALLfacets
+      facet->visitid= qh visit_id;
+  }
+  if (qh vertex_visit > (unsigned) INT_MAX) {
+    qh vertex_visit= 0;
+    FORALLvertices
+      vertex->visitid= qh vertex_visit;
+  }
+  qh furthest_id= furthestid;
+  qh RANDOMdist= qh old_randomdist;
+} /* buildtracing */
+
+/*---------------------------------
+  
+  qh_errexit2( exitcode, facet, otherfacet )
+    return exitcode to system after an error
+    report two facets
+
+  returns:
+    assumes exitcode non-zero
+
+  see:
+    normally use qh_errexit() in user.c (reports a facet and a ridge)
+*/
+void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet) {
+  
+  qh_errprint("ERRONEOUS", facet, otherfacet, NULL, NULL);
+  qh_errexit (exitcode, NULL, NULL);
+} /* errexit2 */
+
+
+/*---------------------------------
+  
+  qh_findhorizon( point, facet, goodvisible, goodhorizon )
+    given a visible facet, find the point's horizon and visible facets
+    for all facets, !facet-visible
+
+  returns:
+    returns qh.visible_list/num_visible with all visible facets 
+      marks visible facets with ->visible 
+    updates count of good visible and good horizon facets
+    updates qh.max_outside, qh.max_vertex, facet->maxoutside
+
+  see:
+    similar to qh_delpoint()
+
+  design:
+    move facet to qh.visible_list at end of qh.facet_list
+    for all visible facets
+     for each unvisited neighbor of a visible facet
+       compute distance of point to neighbor
+       if point above neighbor
+         move neighbor to end of qh.visible_list
+       else if point is coplanar with neighbor
+         update qh.max_outside, qh.max_vertex, neighbor->maxoutside
+         mark neighbor coplanar (will create a samecycle later)
+         update horizon statistics         
+*/
+void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible, int *goodhorizon) {
+  facetT *neighbor, **neighborp, *visible;
+  int numhorizon= 0, coplanar= 0;
+  realT dist;
+  
+  trace1((qh ferr,"qh_findhorizon: find horizon for point p%d facet f%d\n",qh_pointid(point),facet->id));
+  *goodvisible= *goodhorizon= 0;
+  zinc_(Ztotvisible);
+  qh_removefacet(facet);  /* visible_list at end of qh facet_list */
+  qh_appendfacet(facet);
+  qh num_visible= 1;
+  if (facet->good)
+    (*goodvisible)++;
+  qh visible_list= facet;
+  facet->visible= True;
+  facet->f.replace= NULL;
+  if (qh IStracing >=4)
+    qh_errprint ("visible", facet, NULL, NULL, NULL);
+  qh visit_id++;
+  FORALLvisible_facets {
+    if (visible->tricoplanar && !qh TRInormals) {
+      fprintf (qh ferr, "qh_findhorizon: does not work for tricoplanar facets.  Use option 'Q11'\n");
+      qh_errexit (qh_ERRqhull, visible, NULL);
+    }
+    visible->visitid= qh visit_id;
+    FOREACHneighbor_(visible) {
+      if (neighbor->visitid == qh visit_id) 
+        continue;
+      neighbor->visitid= qh visit_id;
+      zzinc_(Znumvisibility);
+      qh_distplane(point, neighbor, &dist);
+      if (dist > qh MINvisible) {
+        zinc_(Ztotvisible);
+	qh_removefacet(neighbor);  /* append to end of qh visible_list */
+	qh_appendfacet(neighbor);
+	neighbor->visible= True;
+        neighbor->f.replace= NULL;
+	qh num_visible++;
+	if (neighbor->good)
+	  (*goodvisible)++;
+        if (qh IStracing >=4)
+          qh_errprint ("visible", neighbor, NULL, NULL, NULL);
+      }else {
+ 	if (dist > - qh MAXcoplanar) {
+    	  neighbor->coplanar= True;
+          zzinc_(Zcoplanarhorizon);
+          qh_precision ("coplanar horizon");
+	  coplanar++;
+	  if (qh MERGING) {
+	    if (dist > 0) {
+	      maximize_(qh max_outside, dist);
+	      maximize_(qh max_vertex, dist);
+#if qh_MAXoutside
+	      maximize_(neighbor->maxoutside, dist);
+#endif
+	    }else
+	      minimize_(qh min_vertex, dist);  /* due to merge later */
+	  }
+      	  trace2((qh ferr, "qh_findhorizon: point p%d is coplanar to horizon f%d, dist=%2.7g < qh MINvisible (%2.7g)\n",
+	      qh_pointid(point), neighbor->id, dist, qh MINvisible));
+	}else
+    	  neighbor->coplanar= False;
+    	zinc_(Ztothorizon);
+        numhorizon++;
+	if (neighbor->good)
+	  (*goodhorizon)++;
+        if (qh IStracing >=4)
+          qh_errprint ("horizon", neighbor, NULL, NULL, NULL);
+      }
+    }
+  }
+  if (!numhorizon) {
+    qh_precision ("empty horizon");
+    fprintf(qh ferr, "qhull precision error (qh_findhorizon): empty horizon\n\
+Point p%d was above all facets.\n", qh_pointid(point));
+    qh_printfacetlist (qh facet_list, NULL, True);
+    qh_errexit(qh_ERRprec, NULL, NULL);
+  }
+  trace1((qh ferr, "qh_findhorizon: %d horizon facets (good %d), %d visible (good %d), %d coplanar\n", 
+       numhorizon, *goodhorizon, qh num_visible, *goodvisible, coplanar));
+  if (qh IStracing >= 4 && qh num_facets < 50) 
+    qh_printlists ();
+} /* findhorizon */
+
+/*---------------------------------
+  
+  qh_nextfurthest( visible )
+    returns next furthest point and visible facet for qh_addpoint()
+    starts search at qh.facet_next
+
+  returns:
+    removes furthest point from outside set
+    NULL if none available
+    advances qh.facet_next over facets with empty outside sets  
+
+  design:
+    for each facet from qh.facet_next
+      if empty outside set
+        advance qh.facet_next
+      else if qh.NARROWhull
+        determine furthest outside point
+        if furthest point is not outside
+          advance qh.facet_next (point will be coplanar)
+    remove furthest point from outside set
+*/
+pointT *qh_nextfurthest (facetT **visible) {
+  facetT *facet;
+  int size, index;
+  realT randr, dist;
+  pointT *furthest;
+
+  while ((facet= qh facet_next) != qh facet_tail) {
+    if (!facet->outsideset) {
+      qh facet_next= facet->next;
+      continue;
+    }
+    SETreturnsize_(facet->outsideset, size);
+    if (!size) {
+      qh_setfree (&facet->outsideset);
+      qh facet_next= facet->next;
+      continue;
+    }
+    if (qh NARROWhull) {
+      if (facet->notfurthest) 
+	qh_furthestout (facet);
+      furthest= (pointT*)qh_setlast (facet->outsideset);
+#if qh_COMPUTEfurthest
+      qh_distplane (furthest, facet, &dist);
+      zinc_(Zcomputefurthest);
+#else
+      dist= facet->furthestdist;
+#endif
+      if (dist < qh MINoutside) { /* remainder of outside set is coplanar for qh_outcoplanar */
+	qh facet_next= facet->next;
+	continue;
+      }
+    }
+    if (!qh RANDOMoutside && !qh VIRTUALmemory) {
+      if (qh PICKfurthest) {
+	qh_furthestnext (/* qh facet_list */);
+	facet= qh facet_next;
+      }
+      *visible= facet;
+      return ((pointT*)qh_setdellast (facet->outsideset));
+    }
+    if (qh RANDOMoutside) {
+      int outcoplanar = 0;
+      if (qh NARROWhull) {
+        FORALLfacets {
+	  if (facet == qh facet_next)
+	    break;
+	  if (facet->outsideset)
+  	    outcoplanar += qh_setsize( facet->outsideset);
+	}
+      }
+      randr= qh_RANDOMint;
+      randr= randr/(qh_RANDOMmax+1);
+      index= (int)floor((qh num_outside - outcoplanar) * randr);
+      FORALLfacet_(qh facet_next) {
+        if (facet->outsideset) {
+          SETreturnsize_(facet->outsideset, size);
+          if (!size)
+            qh_setfree (&facet->outsideset);
+          else if (size > index) {
+            *visible= facet;
+            return ((pointT*)qh_setdelnth (facet->outsideset, index));
+          }else
+            index -= size;
+        }
+      }
+      fprintf (qh ferr, "qhull internal error (qh_nextfurthest): num_outside %d is too low\nby at least %d, or a random real %g >= 1.0\n",
+              qh num_outside, index+1, randr);
+      qh_errexit (qh_ERRqhull, NULL, NULL);
+    }else { /* VIRTUALmemory */
+      facet= qh facet_tail->previous;
+      if (!(furthest= (pointT*)qh_setdellast(facet->outsideset))) {
+        if (facet->outsideset)
+          qh_setfree (&facet->outsideset);
+        qh_removefacet (facet);
+        qh_prependfacet (facet, &qh facet_list);
+        continue;
+      }
+      *visible= facet;
+      return furthest;
+    }
+  }
+  return NULL;
+} /* nextfurthest */
+
+/*---------------------------------
+  
+  qh_partitionall( vertices, points, numpoints )
+    partitions all points in points/numpoints to the outsidesets of facets
+    vertices= vertices in qh.facet_list (not partitioned)
+
+  returns:
+    builds facet->outsideset
+    does not partition qh.GOODpoint
+    if qh.ONLYgood && !qh.MERGING, 
+      does not partition qh.GOODvertex
+
+  notes:
+    faster if qh.facet_list sorted by anticipated size of outside set
+
+  design:
+    initialize pointset with all points
+    remove vertices from pointset
+    remove qh.GOODpointp from pointset (unless it's qh.STOPcone or qh.STOPpoint)
+    for all facets
+      for all remaining points in pointset
+        compute distance from point to facet
+        if point is outside facet
+          remove point from pointset (by not reappending)
+          update bestpoint
+          append point or old bestpoint to facet's outside set
+      append bestpoint to facet's outside set (furthest)
+    for all points remaining in pointset
+      partition point into facets' outside sets and coplanar sets
+*/
+void qh_partitionall(setT *vertices, pointT *points, int numpoints){
+  setT *pointset;
+  vertexT *vertex, **vertexp;
+  pointT *point, **pointp, *bestpoint;
+  int size, point_i, point_n, point_end, remaining, i, id;
+  facetT *facet;
+  realT bestdist= -REALmax, dist, distoutside;
+    
+  trace1((qh ferr, "qh_partitionall: partition all points into outside sets\n"));
+  pointset= qh_settemp (numpoints);
+  qh num_outside= 0;
+  pointp= SETaddr_(pointset, pointT);
+  for (i=numpoints, point= points; i--; point += qh hull_dim)
+    *(pointp++)= point;
+  qh_settruncate (pointset, numpoints);
+  FOREACHvertex_(vertices) {
+    if ((id= qh_pointid(vertex->point)) >= 0)
+      SETelem_(pointset, id)= NULL;
+  }
+  id= qh_pointid (qh GOODpointp);
+  if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
+    SETelem_(pointset, id)= NULL;
+  if (qh GOODvertexp && qh ONLYgood && !qh MERGING) { /* matches qhull()*/
+    if ((id= qh_pointid(qh GOODvertexp)) >= 0)
+      SETelem_(pointset, id)= NULL;
+  }
+  if (!qh BESToutside) {  /* matches conditional for qh_partitionpoint below */
+    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
+    zval_(Ztotpartition)= qh num_points - qh hull_dim - 1; /*misses GOOD... */
+    remaining= qh num_facets;
+    point_end= numpoints;
+    FORALLfacets {
+      size= point_end/(remaining--) + 100;
+      facet->outsideset= qh_setnew (size);
+      bestpoint= NULL;
+      point_end= 0;
+      FOREACHpoint_i_(pointset) {
+        if (point) {
+          zzinc_(Zpartitionall);
+          qh_distplane (point, facet, &dist);
+          if (dist < distoutside)
+            SETelem_(pointset, point_end++)= point;
+          else {
+	    qh num_outside++;
+            if (!bestpoint) {
+              bestpoint= point;
+              bestdist= dist;
+            }else if (dist > bestdist) {
+              qh_setappend (&facet->outsideset, bestpoint);
+              bestpoint= point;
+              bestdist= dist;
+            }else 
+              qh_setappend (&facet->outsideset, point);
+          }
+        }
+      }
+      if (bestpoint) {
+        qh_setappend (&facet->outsideset, bestpoint);
+#if !qh_COMPUTEfurthest
+	facet->furthestdist= bestdist;
+#endif
+      }else
+        qh_setfree (&facet->outsideset);
+      qh_settruncate (pointset, point_end);
+    }
+  }
+  /* if !qh BESToutside, pointset contains points not assigned to outsideset */
+  if (qh BESToutside || qh MERGING || qh KEEPcoplanar || qh KEEPinside) {
+    qh findbestnew= True;
+    FOREACHpoint_i_(pointset) { 
+      if (point)
+        qh_partitionpoint(point, qh facet_list);
+    }
+    qh findbestnew= False;
+  }
+  zzadd_(Zpartitionall, zzval_(Zpartition));
+  zzval_(Zpartition)= 0;
+  qh_settempfree(&pointset);
+  if (qh IStracing >= 4)
+    qh_printfacetlist (qh facet_list, NULL, True);
+} /* partitionall */
+
+
+/*---------------------------------
+  
+  qh_partitioncoplanar( point, facet, dist )
+    partition coplanar point to a facet
+    dist is distance from point to facet
+    if dist NULL, 
+      searches for bestfacet and does nothing if inside
+    if qh.findbestnew set, 
+      searches new facets instead of using qh_findbest()
+
+  returns:
+    qh.max_ouside updated
+    if qh.KEEPcoplanar or qh.KEEPinside
+      point assigned to best coplanarset
+  
+  notes:
+    facet->maxoutside is updated at end by qh_check_maxout
+
+  design:
+    if dist undefined
+      find best facet for point
+      if point sufficiently below facet (depends on qh.NEARinside and qh.KEEPinside)
+        exit
+    if keeping coplanar/nearinside/inside points
+      if point is above furthest coplanar point
+        append point to coplanar set (it is the new furthest)
+        update qh.max_outside
+      else
+        append point one before end of coplanar set
+    else if point is clearly outside of qh.max_outside and bestfacet->coplanarset
+    and bestfacet is more than perpendicular to facet
+      repartition the point using qh_findbest() -- it may be put on an outsideset
+    else
+      update qh.max_outside
+*/
+void qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist) {
+  facetT *bestfacet;
+  pointT *oldfurthest;
+  realT bestdist, dist2, angle;
+  int numpart= 0, oldfindbest;
+  boolT isoutside;
+
+  qh WAScoplanar= True;
+  if (!dist) {
+    if (qh findbestnew)
+      bestfacet= qh_findbestnew (point, facet, &bestdist, qh_ALL, &isoutside, &numpart);
+    else
+      bestfacet= qh_findbest (point, facet, qh_ALL, !qh_ISnewfacets, qh DELAUNAY, 
+                          &bestdist, &isoutside, &numpart);
+    zinc_(Ztotpartcoplanar);
+    zzadd_(Zpartcoplanar, numpart);
+    if (!qh DELAUNAY && !qh KEEPinside) { /*  for 'd', bestdist skips upperDelaunay facets */
+      if (qh KEEPnearinside) {
+        if (bestdist < -qh NEARinside) { 
+          zinc_(Zcoplanarinside);
+	  trace4((qh ferr, "qh_partitioncoplanar: point p%d is more than near-inside facet f%d dist %2.2g findbestnew %d\n",
+		  qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
+          return;
+        }
+      }else if (bestdist < -qh MAXcoplanar) {
+	  trace4((qh ferr, "qh_partitioncoplanar: point p%d is inside facet f%d dist %2.2g findbestnew %d\n",
+		  qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
+        zinc_(Zcoplanarinside);
+        return;
+      }
+    }
+  }else {
+    bestfacet= facet;
+    bestdist= *dist;
+  }
+  if (bestdist > qh max_outside) {
+    if (!dist && facet != bestfacet) { 
+      zinc_(Zpartangle);
+      angle= qh_getangle(facet->normal, bestfacet->normal);
+      if (angle < 0) {
+	/* typically due to deleted vertex and coplanar facets, e.g.,
+	     RBOX 1000 s Z1 G1e-13 t1001185205 | QHULL Tv */
+	zinc_(Zpartflip);
+	trace2((qh ferr, "qh_partitioncoplanar: repartition point p%d from f%d.  It is above flipped facet f%d dist %2.2g\n",
+		qh_pointid(point), facet->id, bestfacet->id, bestdist));
+	oldfindbest= qh findbestnew;
+        qh findbestnew= False;
+	qh_partitionpoint(point, bestfacet);
+        qh findbestnew= oldfindbest;
+	return;
+      }
+    }
+    qh max_outside= bestdist;
+    if (bestdist > qh TRACEdist) {
+      fprintf (qh ferr, "qh_partitioncoplanar: ====== p%d from f%d increases max_outside to %2.2g of f%d last p%d\n",
+		     qh_pointid(point), facet->id, bestdist, bestfacet->id, qh furthest_id);
+      qh_errprint ("DISTANT", facet, bestfacet, NULL, NULL);
+    }
+  }
+  if (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside) {
+    oldfurthest= (pointT*)qh_setlast (bestfacet->coplanarset);
+    if (oldfurthest) {
+      zinc_(Zcomputefurthest);
+      qh_distplane (oldfurthest, bestfacet, &dist2);
+    }
+    if (!oldfurthest || dist2 < bestdist) 
+      qh_setappend(&bestfacet->coplanarset, point);
+    else 
+      qh_setappend2ndlast(&bestfacet->coplanarset, point);
+  }
+  trace4((qh ferr, "qh_partitioncoplanar: point p%d is coplanar with facet f%d (or inside) dist %2.2g\n",
+	  qh_pointid(point), bestfacet->id, bestdist));
+} /* partitioncoplanar */
+
+/*---------------------------------
+  
+  qh_partitionpoint( point, facet )
+    assigns point to an outside set, coplanar set, or inside set (i.e., dropt)
+    if qh.findbestnew
+      uses qh_findbestnew() to search all new facets
+    else
+      uses qh_findbest()
+  
+  notes:
+    after qh_distplane(), this and qh_findbest() are most expensive in 3-d
+
+  design:
+    find best facet for point 
+      (either exhaustive search of new facets or directed search from facet)
+    if qh.NARROWhull
+      retain coplanar and nearinside points as outside points
+    if point is outside bestfacet
+      if point above furthest point for bestfacet
+        append point to outside set (it becomes the new furthest)
+        if outside set was empty
+          move bestfacet to end of qh.facet_list (i.e., after qh.facet_next)
+        update bestfacet->furthestdist
+      else
+        append point one before end of outside set
+    else if point is coplanar to bestfacet
+      if keeping coplanar points or need to update qh.max_outside
+        partition coplanar point into bestfacet
+    else if near-inside point        
+      partition as coplanar point into bestfacet
+    else is an inside point
+      if keeping inside points 
+        partition as coplanar point into bestfacet
+*/
+void qh_partitionpoint (pointT *point, facetT *facet) {
+  realT bestdist;
+  boolT isoutside;
+  facetT *bestfacet;
+  int numpart;
+#if qh_COMPUTEfurthest
+  realT dist;
+#endif
+
+  if (qh findbestnew)
+    bestfacet= qh_findbestnew (point, facet, &bestdist, qh BESToutside, &isoutside, &numpart);
+  else
+    bestfacet= qh_findbest (point, facet, qh BESToutside, qh_ISnewfacets, !qh_NOupper,
+			  &bestdist, &isoutside, &numpart);
+  zinc_(Ztotpartition);
+  zzadd_(Zpartition, numpart);
+  if (qh NARROWhull) {
+    if (qh DELAUNAY && !isoutside && bestdist >= -qh MAXcoplanar)
+      qh_precision ("nearly incident point (narrow hull)");
+    if (qh KEEPnearinside) {
+      if (bestdist >= -qh NEARinside)
+	isoutside= True;
+    }else if (bestdist >= -qh MAXcoplanar)
+      isoutside= True;
+  }
+
+  if (isoutside) {
+    if (!bestfacet->outsideset 
+    || !qh_setlast (bestfacet->outsideset)) {
+      qh_setappend(&(bestfacet->outsideset), point);
+      if (!bestfacet->newfacet) {
+        qh_removefacet (bestfacet);  /* make sure it's after qh facet_next */
+        qh_appendfacet (bestfacet);
+      }
+#if !qh_COMPUTEfurthest
+      bestfacet->furthestdist= bestdist;
+#endif
+    }else {
+#if qh_COMPUTEfurthest
+      zinc_(Zcomputefurthest);
+      qh_distplane (oldfurthest, bestfacet, &dist);
+      if (dist < bestdist) 
+	qh_setappend(&(bestfacet->outsideset), point);
+      else
+	qh_setappend2ndlast(&(bestfacet->outsideset), point);
+#else
+      if (bestfacet->furthestdist < bestdist) {
+	qh_setappend(&(bestfacet->outsideset), point);
+	bestfacet->furthestdist= bestdist;
+      }else
+	qh_setappend2ndlast(&(bestfacet->outsideset), point);
+#endif
+    }
+    qh num_outside++;
+    trace4((qh ferr, "qh_partitionpoint: point p%d is outside facet f%d new? %d(or narrowhull)\n",
+	  qh_pointid(point), bestfacet->id, bestfacet->newfacet));
+  }else if (qh DELAUNAY || bestdist >= -qh MAXcoplanar) { /* for 'd', bestdist skips upperDelaunay facets */
+    zzinc_(Zcoplanarpart);
+    if (qh DELAUNAY)
+      qh_precision ("nearly incident point");
+    if ((qh KEEPcoplanar + qh KEEPnearinside) || bestdist > qh max_outside) 
+      qh_partitioncoplanar (point, bestfacet, &bestdist);
+    else {
+      trace4((qh ferr, "qh_partitionpoint: point p%d is coplanar to facet f%d (dropped)\n",
+	  qh_pointid(point), bestfacet->id));
+    }
+  }else if (qh KEEPnearinside && bestdist > -qh NEARinside) {
+    zinc_(Zpartnear);
+    qh_partitioncoplanar (point, bestfacet, &bestdist);
+  }else {
+    zinc_(Zpartinside);
+    trace4((qh ferr, "qh_partitionpoint: point p%d is inside all facets, closest to f%d dist %2.2g\n",
+	  qh_pointid(point), bestfacet->id, bestdist));
+    if (qh KEEPinside)
+      qh_partitioncoplanar (point, bestfacet, &bestdist);
+  }
+} /* partitionpoint */
+
+/*---------------------------------
+  
+  qh_partitionvisible( allpoints, numoutside )
+    partitions points in visible facets to qh.newfacet_list
+    qh.visible_list= visible facets
+    for visible facets
+      1st neighbor (if any) points to a horizon facet or a new facet
+    if allpoints (not used),
+      repartitions coplanar points
+
+  returns:
+    updates outside sets and coplanar sets of qh.newfacet_list
+    updates qh.num_outside (count of outside points)
+  
+  notes:
+    qh.findbest_notsharp should be clear (extra work if set)
+
+  design:
+    for all visible facets with outside set or coplanar set
+      select a newfacet for visible facet
+      if outside set
+        partition outside set into new facets
+      if coplanar set and keeping coplanar/near-inside/inside points
+        if allpoints
+          partition coplanar set into new facets, may be assigned outside
+        else
+          partition coplanar set into coplanar sets of new facets
+    for each deleted vertex
+      if allpoints
+        partition vertex into new facets, may be assigned outside
+      else
+        partition vertex into coplanar sets of new facets
+*/
+void qh_partitionvisible(/*visible_list*/ boolT allpoints, int *numoutside) {
+  facetT *visible, *newfacet;
+  pointT *point, **pointp;
+  int coplanar=0, size;
+  unsigned count;
+  vertexT *vertex, **vertexp;
+  
+  if (qh ONLYmax)
+    maximize_(qh MINoutside, qh max_vertex);
+  *numoutside= 0;
+  FORALLvisible_facets {
+    if (!visible->outsideset && !visible->coplanarset)
+      continue;
+    newfacet= visible->f.replace;
+    count= 0;
+    while (newfacet && newfacet->visible) {
+      newfacet= newfacet->f.replace;
+      if (count++ > qh facet_id)
+	qh_infiniteloop (visible);
+    }
+    if (!newfacet)
+      newfacet= qh newfacet_list;
+    if (newfacet == qh facet_tail) {
+      fprintf (qh ferr, "qhull precision error (qh_partitionvisible): all new facets deleted as\n        degenerate facets. Can not continue.\n");
+      qh_errexit (qh_ERRprec, NULL, NULL);
+    }
+    if (visible->outsideset) {
+      size= qh_setsize (visible->outsideset);
+      *numoutside += size;
+      qh num_outside -= size;
+      FOREACHpoint_(visible->outsideset) 
+        qh_partitionpoint (point, newfacet);
+    }
+    if (visible->coplanarset && (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside)) {
+      size= qh_setsize (visible->coplanarset);
+      coplanar += size;
+      FOREACHpoint_(visible->coplanarset) {
+        if (allpoints) /* not used */
+          qh_partitionpoint (point, newfacet);
+        else
+          qh_partitioncoplanar (point, newfacet, NULL);
+      }
+    }
+  }
+  FOREACHvertex_(qh del_vertices) {
+    if (vertex->point) {
+      if (allpoints) /* not used */
+        qh_partitionpoint (vertex->point, qh newfacet_list);
+      else
+        qh_partitioncoplanar (vertex->point, qh newfacet_list, NULL);
+    }
+  }
+  trace1((qh ferr,"qh_partitionvisible: partitioned %d points from outsidesets and %d points from coplanarsets\n", *numoutside, coplanar));
+} /* partitionvisible */
+
+
+
+/*---------------------------------
+  
+  qh_precision( reason )
+    restart on precision errors if not merging and if 'QJn'
+*/
+void qh_precision (char *reason) {
+
+  if (qh ALLOWrestart && !qh PREmerge && !qh MERGEexact) {
+    if (qh JOGGLEmax < REALmax/2) {
+      trace0((qh ferr, "qh_precision: qhull restart because of %s\n", reason));
+      longjmp(qh restartexit, qh_ERRprec);
+    }
+  }
+} /* qh_precision */
+
+/*---------------------------------
+  
+  qh_printsummary( fp )
+    prints summary to fp
+
+  notes:
+    not in io.c so that user_eg.c can prevent io.c from loading
+    qh_printsummary and qh_countfacets must match counts
+
+  design:
+    determine number of points, vertices, and coplanar points
+    print summary
+*/
+void qh_printsummary(FILE *fp) {
+  realT ratio, outerplane, innerplane;
+  float cpu;
+  int size, id, nummerged, numvertices, numcoplanars= 0, nonsimplicial=0;
+  int goodused;
+  facetT *facet;
+  char *s;
+  int numdel= zzval_(Zdelvertextot);
+  int numtricoplanars= 0;
+
+  size= qh num_points + qh_setsize (qh other_points);
+  numvertices= qh num_vertices - qh_setsize (qh del_vertices);
+  id= qh_pointid (qh GOODpointp);
+  FORALLfacets {
+    if (facet->coplanarset)
+      numcoplanars += qh_setsize( facet->coplanarset);
+    if (facet->good) {
+      if (facet->simplicial) {
+	if (facet->keepcentrum && facet->tricoplanar)
+	  numtricoplanars++;
+      }else if (qh_setsize(facet->vertices) != qh hull_dim)
+	nonsimplicial++;
+    }
+  }
+  if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
+    size--;
+  if (qh STOPcone || qh STOPpoint)
+      fprintf (fp, "\nAt a premature exit due to 'TVn', 'TCn', 'TRn', or precision error.");
+  if (qh UPPERdelaunay)
+    goodused= qh GOODvertex + qh GOODpoint + qh SPLITthresholds;
+  else if (qh DELAUNAY)
+    goodused= qh GOODvertex + qh GOODpoint + qh GOODthreshold;
+  else
+    goodused= qh num_good;
+  nummerged= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+  if (qh VORONOI) {
+    if (qh UPPERdelaunay)
+      fprintf (fp, "\n\
+Furthest-site Voronoi vertices by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    else
+      fprintf (fp, "\n\
+Voronoi diagram by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    fprintf(fp, "  Number of Voronoi regions%s: %d\n",
+              qh ATinfinity ? " and at-infinity" : "", numvertices);
+    if (numdel)
+      fprintf(fp, "  Total number of deleted points due to merging: %d\n", numdel); 
+    if (numcoplanars - numdel > 0) 
+      fprintf(fp, "  Number of nearly incident points: %d\n", numcoplanars - numdel); 
+    else if (size - numvertices - numdel > 0) 
+      fprintf(fp, "  Total number of nearly incident points: %d\n", size - numvertices - numdel); 
+    fprintf(fp, "  Number of%s Voronoi vertices: %d\n", 
+              goodused ? " 'good'" : "", qh num_good);
+    if (nonsimplicial) 
+      fprintf(fp, "  Number of%s non-simplicial Voronoi vertices: %d\n", 
+              goodused ? " 'good'" : "", nonsimplicial);
+  }else if (qh DELAUNAY) {
+    if (qh UPPERdelaunay)
+      fprintf (fp, "\n\
+Furthest-site Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    else
+      fprintf (fp, "\n\
+Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    fprintf(fp, "  Number of input sites%s: %d\n", 
+              qh ATinfinity ? " and at-infinity" : "", numvertices);
+    if (numdel)
+      fprintf(fp, "  Total number of deleted points due to merging: %d\n", numdel); 
+    if (numcoplanars - numdel > 0) 
+      fprintf(fp, "  Number of nearly incident points: %d\n", numcoplanars - numdel); 
+    else if (size - numvertices - numdel > 0)
+      fprintf(fp, "  Total number of nearly incident points: %d\n", size - numvertices - numdel); 
+    fprintf(fp, "  Number of%s Delaunay regions: %d\n", 
+              goodused ? " 'good'" : "", qh num_good);
+    if (nonsimplicial) 
+      fprintf(fp, "  Number of%s non-simplicial Delaunay regions: %d\n", 
+              goodused ? " 'good'" : "", nonsimplicial);
+  }else if (qh HALFspace) {
+    fprintf (fp, "\n\
+Halfspace intersection by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    fprintf(fp, "  Number of halfspaces: %d\n", size);
+    fprintf(fp, "  Number of non-redundant halfspaces: %d\n", numvertices);
+    if (numcoplanars) {
+      if (qh KEEPinside && qh KEEPcoplanar)
+      	s= "similar and redundant";
+      else if (qh KEEPinside)
+        s= "redundant";
+      else
+        s= "similar"; 
+      fprintf(fp, "  Number of %s halfspaces: %d\n", s, numcoplanars);
+    } 
+    fprintf(fp, "  Number of intersection points: %d\n", qh num_facets - qh num_visible);
+    if (goodused)
+      fprintf(fp, "  Number of 'good' intersection points: %d\n", qh num_good);
+    if (nonsimplicial) 
+      fprintf(fp, "  Number of%s non-simplicial intersection points: %d\n", 
+              goodused ? " 'good'" : "", nonsimplicial);
+  }else {
+    fprintf (fp, "\n\
+Convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    fprintf(fp, "  Number of vertices: %d\n", numvertices);
+    if (numcoplanars) {
+      if (qh KEEPinside && qh KEEPcoplanar)
+      	s= "coplanar and interior";
+      else if (qh KEEPinside)
+        s= "interior";
+      else
+        s= "coplanar"; 
+      fprintf(fp, "  Number of %s points: %d\n", s, numcoplanars);
+    } 
+    fprintf(fp, "  Number of facets: %d\n", qh num_facets - qh num_visible);
+    if (goodused)
+      fprintf(fp, "  Number of 'good' facets: %d\n", qh num_good);
+    if (nonsimplicial) 
+      fprintf(fp, "  Number of%s non-simplicial facets: %d\n", 
+              goodused ? " 'good'" : "", nonsimplicial);
+  }
+  if (numtricoplanars)
+      fprintf(fp, "  Number of triangulated facets: %d\n", numtricoplanars);
+  fprintf(fp, "\nStatistics for: %s | %s", 
+                      qh rbox_command, qh qhull_command);
+  if (qh ROTATErandom != INT_MIN)
+    fprintf(fp, " QR%d\n\n", qh ROTATErandom);
+  else
+    fprintf(fp, "\n\n");
+  fprintf(fp, "  Number of points processed: %d\n", zzval_(Zprocessed));
+  fprintf(fp, "  Number of hyperplanes created: %d\n", zzval_(Zsetplane));
+  if (qh DELAUNAY)
+    fprintf(fp, "  Number of facets in hull: %d\n", qh num_facets - qh num_visible);
+  fprintf(fp, "  Number of distance tests for qhull: %d\n", zzval_(Zpartition)+
+      zzval_(Zpartitionall)+zzval_(Znumvisibility)+zzval_(Zpartcoplanar));
+#if 0  /* NOTE: must print before printstatistics() */
+  {realT stddev, ave;
+  fprintf(fp, "  average new facet balance: %2.2g\n",
+	  wval_(Wnewbalance)/zval_(Zprocessed));
+  stddev= qh_stddev (zval_(Zprocessed), wval_(Wnewbalance), 
+                                 wval_(Wnewbalance2), &ave);
+  fprintf(fp, "  new facet standard deviation: %2.2g\n", stddev);
+  fprintf(fp, "  average partition balance: %2.2g\n",
+	  wval_(Wpbalance)/zval_(Zpbalance));
+  stddev= qh_stddev (zval_(Zpbalance), wval_(Wpbalance), 
+                                 wval_(Wpbalance2), &ave);
+  fprintf(fp, "  partition standard deviation: %2.2g\n", stddev);
+  }
+#endif
+  if (nummerged) {
+    fprintf(fp,"  Number of distance tests for merging: %d\n",zzval_(Zbestdist)+
+          zzval_(Zcentrumtests)+zzval_(Zdistconvex)+zzval_(Zdistcheck)+
+          zzval_(Zdistzero));
+    fprintf(fp,"  Number of distance tests for checking: %d\n",zzval_(Zcheckpart));
+    fprintf(fp,"  Number of merged facets: %d\n", nummerged);
+  }
+  if (!qh RANDOMoutside && qh QHULLfinished) {
+    cpu= qh hulltime;
+    cpu /= qh_SECticks;
+    wval_(Wcpu)= cpu;
+    fprintf (fp, "  CPU seconds to compute hull (after input): %2.4g\n", cpu);
+  }
+  if (qh RERUN) {
+    if (!qh PREmerge && !qh MERGEexact)
+      fprintf(fp, "  Percentage of runs with precision errors: %4.1f\n",
+	   zzval_(Zretry)*100.0/qh build_cnt);  /* careful of order */
+  }else if (qh JOGGLEmax < REALmax/2) {
+    if (zzval_(Zretry))
+      fprintf(fp, "  After %d retries, input joggled by: %2.2g\n",
+         zzval_(Zretry), qh JOGGLEmax);
+    else
+      fprintf(fp, "  Input joggled by: %2.2g\n", qh JOGGLEmax);
+  }
+  if (qh totarea != 0.0) 
+    fprintf(fp, "  %s facet area:   %2.8g\n", 
+	    zzval_(Ztotmerge) ? "Approximate" : "Total", qh totarea);
+  if (qh totvol != 0.0) 
+    fprintf(fp, "  %s volume:       %2.8g\n", 
+	    zzval_(Ztotmerge) ? "Approximate" : "Total", qh totvol);
+  if (qh MERGING) {
+    qh_outerinner (NULL, &outerplane, &innerplane);
+    if (outerplane > 2 * qh DISTround) {
+      fprintf(fp, "  Maximum distance of %spoint above facet: %2.2g", 
+	    (qh QHULLfinished ? "" : "merged "), outerplane);
+      ratio= outerplane/(qh ONEmerge + qh DISTround);
+      /* don't report ratio if MINoutside is large */
+      if (ratio > 0.05 && 2* qh ONEmerge > qh MINoutside && qh JOGGLEmax > REALmax/2)
+        fprintf (fp, " (%.1fx)\n", ratio);
+      else
+        fprintf (fp, "\n");
+    }
+    if (innerplane < -2 * qh DISTround) {
+      fprintf(fp, "  Maximum distance of %svertex below facet: %2.2g", 
+	    (qh QHULLfinished ? "" : "merged "), innerplane);
+      ratio= -innerplane/(qh ONEmerge+qh DISTround);
+      if (ratio > 0.05 && qh JOGGLEmax > REALmax/2)
+        fprintf (fp, " (%.1fx)\n", ratio);
+      else
+        fprintf (fp, "\n");
+    }
+  }
+  fprintf(fp, "\n");
+} /* printsummary */
+
+

Added: trunk/scipy/spatial/qhull/src/qhull.h
===================================================================
--- trunk/scipy/spatial/qhull/src/qhull.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qhull.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,1030 @@
+/*
  ---------------------------------
+
+   qhull.h
+   user-level header file for using qhull.a library
+
+   see qh-qhull.htm, qhull_a.h
+
+   copyright (c) 1993-2003, The Geometry Center
+
+   NOTE: access to qh_qh is via the 'qh' macro.  This allows
+   qh_qh to be either a pointer or a structure.  An example
+   of using qh is "qh DROPdim" which accesses the DROPdim
+   field of qh_qh.  Similarly, access to qh_qhstat is via
+   the 'qhstat' macro.
+
+   includes function prototypes for qhull.c, geom.c, global.c, io.c, user.c
+
+   use mem.h for mem.c
+   use qset.h for qset.c
+
+   see unix.c for an example of using qhull.h
+
+   recompile qhull if you change this file
+*/
+
+#ifndef qhDEFqhull
+#define qhDEFqhull 1
+
+/*=========================== -included files ==============*/
+
+#include 
+#include 
+#include 
+
+#if __MWERKS__ && __POWERPC__
+#include  
+#include  
+#include	
+#endif
+
+#ifndef __STDC__
+#ifndef __cplusplus
+#if     !_MSC_VER
+#error  Neither __STDC__ nor __cplusplus is defined.  Please use strict ANSI C or C++ to compile
+#error  Qhull.  You may need to turn off compiler extensions in your project configuration.  If
+#error  your compiler is a standard C compiler, you can delete this warning from qhull.h
+#endif
+#endif
+#endif
+
+#include "user.h"      /* user defineable constants */
+
+/*============ constants and basic types ====================*/
+
+extern char *qh_version; /* defined in global.c */
+
+/*----------------------------------
+
+  coordT
+    coordinates and coefficients are stored as realT (i.e., double)
+
+  notes:
+    could use 'float' for data and 'double' for calculations (realT vs. coordT)
+      This requires many type casts, and adjusted error bounds.
+      Also C compilers may do expressions in double anyway.
+*/
+#define coordT realT
+
+/*----------------------------------
+
+  pointT
+    a point is an array of DIM3 coordinates
+*/
+#define pointT coordT
+
+/*----------------------------------
+
+  flagT
+    Boolean flag as a bit
+*/
+#define flagT unsigned int
+
+/*----------------------------------
+
+  boolT
+    boolean value, either True or False
+
+  notes:
+    needed for portability
+*/
+#define boolT unsigned int
+#ifdef False
+#undef False
+#endif
+#ifdef True
+#undef True
+#endif
+#define False 0
+#define True 1
+
+/*----------------------------------
+
+  qh_CENTER
+    to distinguish facet->center
+*/
+typedef enum
+{
+    qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum
+}
+qh_CENTER;
+
+/*----------------------------------
+
+  qh_PRINT
+    output formats for printing (qh.PRINTout).
+    'Fa' 'FV' 'Fc' 'FC' 
+       
+
+   notes:
+   some of these names are similar to qh names.  The similar names are only
+   used in switch statements in qh_printbegin() etc.
+*/
+typedef enum {qh_PRINTnone= 0, 
+  qh_PRINTarea, qh_PRINTaverage,           /* 'Fa' 'FV' 'Fc' 'FC' */
+  qh_PRINTcoplanars, qh_PRINTcentrums, 
+  qh_PRINTfacets, qh_PRINTfacets_xridge,   /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
+  qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors, 
+  qh_PRINTnormals, qh_PRINTouter, qh_PRINTmaple, /* 'n' 'Fo' 'i' 'm' 'Fm' 'FM', 'o' */
+  qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff, 
+  qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
+  qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize, 
+  qh_PRINTsummary, qh_PRINTtriangles,      /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
+  qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
+  qh_PRINTEND} qh_PRINT;
+
+/*----------------------------------
+
+  qh_ALL
+    argument flag for selecting everything
+*/
+#define qh_ALL      True
+#define qh_NOupper  True     /* argument for qh_findbest */
+#define qh_IScheckmax  True     /* argument for qh_findbesthorizon */
+#define qh_ISnewfacets  True     /* argument for qh_findbest */
+#define qh_RESETvisible  True     /* argument for qh_resetlists */
+
+/*----------------------------------
+
+  qh_ERR
+    Qhull exit codes, for indicating errors
+*/
+#define qh_ERRnone  0    /* no error occurred during qhull */
+#define qh_ERRinput 1    /* input inconsistency */
+#define qh_ERRsingular 2 /* singular input data */
+#define qh_ERRprec  3    /* precision error */
+#define qh_ERRmem   4    /* insufficient memory, matches mem.h */
+#define qh_ERRqhull 5    /* internal error detected, matches mem.h */
+
+/* ============ -structures- ====================
+   each of the following structures is defined by a typedef
+   all realT and coordT fields occur at the beginning of a structure
+        (otherwise space may be wasted due to alignment)
+   define all flags together and pack into 32-bit number
+*/
+
+typedef struct vertexT vertexT;
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;          /* defined in qset.h */
+#endif
+
+/*----------------------------------
+
+  facetT
+    defines a facet
+
+  notes:
+   qhull() generates the hull as a list of facets.
+
+  topological information:
+    f.previous,next     doubly-linked list of facets
+    f.vertices          set of vertices
+    f.ridges            set of ridges
+    f.neighbors         set of neighbors
+    f.toporient         True if facet has top-orientation (else bottom)
+
+  geometric information:
+    f.offset,normal     hyperplane equation
+    f.maxoutside        offset to outer plane -- all points inside
+    f.center            centrum for testing convexity
+    f.simplicial        True if facet is simplicial
+    f.flipped           True if facet does not include qh.interior_point
+
+  for constructing hull:
+    f.visible           True if facet on list of visible facets (will be deleted)
+    f.newfacet          True if facet on list of newly created facets
+    f.coplanarset       set of points coplanar with this facet
+                        (includes near-inside points for later testing)
+    f.outsideset        set of points outside of this facet
+    f.furthestdist      distance to furthest point of outside set
+    f.visitid           marks visited facets during a loop
+    f.replace           replacement facet for to-be-deleted, visible facets
+    f.samecycle,newcycle cycle of facets for merging into horizon facet
+
+  see below for other flags and fields
+*/
+struct facetT {
+#if !qh_COMPUTEfurthest
+  coordT   furthestdist;/* distance to furthest point of outsideset */
+#endif
+#if qh_MAXoutside
+  coordT   maxoutside;  /* max computed distance of point to facet
+  			Before QHULLfinished this is an approximation
+  			since maxdist not always set for mergefacet
+			Actual outer plane is +DISTround and
+			computed outer plane is +2*DISTround */
+#endif
+  coordT   offset;      /* exact offset of hyperplane from origin */
+  coordT  *normal;      /* normal of hyperplane, hull_dim coefficients */
+			/*   if tricoplanar, shared with a neighbor */
+  union {               /* in order of testing */
+   realT   area;        /* area of facet, only in io.c if  ->isarea */
+   facetT *replace;	/*  replacement facet if ->visible and NEWfacets
+  			     is NULL only if qh_mergedegen_redundant or interior */
+   facetT *samecycle;   /*  cycle of facets from the same visible/horizon intersection,
+   			     if ->newfacet */
+   facetT *newcycle;    /*  in horizon facet, current samecycle of new facets */ 
+   facetT *trivisible;  /* visible facet for ->tricoplanar facets during qh_triangulate() */
+   facetT *triowner;    /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
+  }f;
+  coordT  *center;      /*  centrum for convexity, qh CENTERtype == qh_AScentrum */
+      			/*  Voronoi center, qh CENTERtype == qh_ASvoronoi */
+			/*   if tricoplanar, shared with a neighbor */
+  facetT  *previous;    /* previous facet in the facet_list */
+  facetT  *next;        /* next facet in the facet_list */
+  setT    *vertices;    /* vertices for this facet, inverse sorted by ID 
+                           if simplicial, 1st vertex was apex/furthest */
+  setT    *ridges;      /* explicit ridges for nonsimplicial facets.
+  			   for simplicial facets, neighbors defines ridge */
+  setT    *neighbors;   /* neighbors of the facet.  If simplicial, the kth
+			   neighbor is opposite the kth vertex, and the first
+			   neighbor is the horizon facet for the first vertex*/
+  setT    *outsideset;  /* set of points outside this facet
+		           if non-empty, last point is furthest
+			   if NARROWhull, includes coplanars for partitioning*/
+  setT    *coplanarset; /* set of points coplanar with this facet
+  			   > qh.min_vertex and <= facet->max_outside
+                           a point is assigned to the furthest facet
+		           if non-empty, last point is furthest away */
+  unsigned visitid;     /* visit_id, for visiting all neighbors,
+			   all uses are independent */
+  unsigned id;	        /* unique identifier from qh facet_id */
+  unsigned nummerge:9;  /* number of merges */
+#define qh_MAXnummerge 511 /*     2^9-1, 32 flags total, see "flags:" in io.c */
+  flagT    tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
+			  /*   all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
+			  /*   all tricoplanars share the same apex */
+                          /*   if ->degenerate, does not span facet (one logical ridge) */
+                          /*   one tricoplanar has ->keepcentrum and ->coplanarset */
+                          /*   during qh_triangulate, f.trivisible points to original facet */
+  flagT	   newfacet:1;  /* True if facet on qh newfacet_list (new or merged) */
+  flagT	   visible:1;   /* True if visible facet (will be deleted) */
+  flagT    toporient:1; /* True if created with top orientation
+			   after merging, use ridge orientation */
+  flagT    simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
+  flagT    seen:1;      /* used to perform operations only once, like visitid */
+  flagT    seen2:1;     /* used to perform operations only once, like visitid */
+  flagT	   flipped:1;   /* True if facet is flipped */
+  flagT    upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
+  flagT    notfurthest:1; /* True if last point of outsideset is not furthest*/
+
+/*-------- flags primarily for output ---------*/
+  flagT	   good:1;      /* True if a facet marked good for output */
+  flagT    isarea:1;    /* True if facet->f.area is defined */
+
+/*-------- flags for merging ------------------*/
+  flagT    dupridge:1;  /* True if duplicate ridge in facet */
+  flagT    mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
+                            ->normal defined (also defined for mergeridge2) */
+  flagT    mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
+  flagT    coplanar:1;  /* True if horizon facet is coplanar at last use */
+  flagT     mergehorizon:1; /* True if will merge into horizon (->coplanar) */
+  flagT	    cycledone:1;/* True if mergecycle_all already done */
+  flagT    tested:1;    /* True if facet convexity has been tested (false after merge */
+  flagT    keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
+  flagT	   newmerge:1;  /* True if facet is newly merged for reducevertices */
+  flagT	   degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
+  flagT	   redundant:1;  /* True if facet is redundant (degen_mergeset) */
+};
+
+
+/*----------------------------------
+
+  ridgeT
+    defines a ridge
+
+  notes:
+  a ridge is DIM3-1 simplex between two neighboring facets.  If the
+  facets are non-simplicial, there may be more than one ridge between
+  two facets.  E.G. a 4-d hypercube has two triangles between each pair
+  of neighboring facets.
+
+  topological information:
+    vertices            a set of vertices
+    top,bottom          neighboring facets with orientation
+
+  geometric information:
+    tested              True if ridge is clearly convex
+    nonconvex           True if ridge is non-convex
+*/
+struct ridgeT {
+  setT    *vertices;    /* vertices belonging to this ridge, inverse sorted by ID 
+                           NULL if a degen ridge (matchsame) */
+  facetT  *top;         /* top facet this ridge is part of */
+  facetT  *bottom;      /* bottom facet this ridge is part of */
+  unsigned id:24;       /* unique identifier, =>room for 8 flags */
+  flagT    seen:1;      /* used to perform operations only once */
+  flagT    tested:1;    /* True when ridge is tested for convexity */
+  flagT    nonconvex:1; /* True if getmergeset detected a non-convex neighbor
+			   only one ridge between neighbors may have nonconvex */
+};
+
+/*----------------------------------
+
+  vertexT
+     defines a vertex
+
+  topological information:
+    next,previous       doubly-linked list of all vertices
+    neighbors           set of adjacent facets (only if qh.VERTEXneighbors)
+
+  geometric information:
+    point               array of DIM3 coordinates
+*/
+struct vertexT {
+  vertexT *next;        /* next vertex in vertex_list */
+  vertexT *previous;    /* previous vertex in vertex_list */
+  pointT  *point;       /* hull_dim coordinates (coordT) */
+  setT    *neighbors;   /* neighboring facets of vertex, qh_vertexneighbors()
+			   inits in io.c or after first merge */
+  unsigned visitid; /* for use with qh vertex_visit */
+  unsigned id:24;   /* unique identifier, =>room for 8 flags */
+  flagT    seen:1;      /* used to perform operations only once */
+  flagT    seen2:1;     /* another seen flag */
+  flagT    delridge:1;  /* vertex was part of a deleted ridge */
+  flagT	   deleted:1;   /* true if vertex on qh del_vertices */
+  flagT    newlist:1;   /* true if vertex on qh newvertex_list */
+};
+
+/*======= -global variables -qh ============================*/
+
+/*----------------------------------
+
+  qh
+   all global variables for qhull are in qh, qhmem, and qhstat
+
+  notes:
+   qhmem is defined in mem.h and qhstat is defined in stat.h
+   Access to qh_qh is via the "qh" macro.  See qh_QHpointer in user.h
+*/
+typedef struct qhT qhT;
+#if qh_QHpointer
+#define qh qh_qh->
+extern qhT *qh_qh;     /* allocated in global.c */
+#else
+#define qh qh_qh.
+extern qhT qh_qh;
+#endif
+
+struct qhT {
+
+/*----------------------------------
+
+  qh constants
+    configuration flags and constants for Qhull
+
+  notes:
+    The user configures Qhull by defining flags.  They are
+    copied into qh by qh_setflags().  qh-quick.htm#options defines the flags.
+*/
+  boolT ALLpoints;        /* true 'Qs' if search all points for initial simplex */
+  boolT ANGLEmerge;	  /* true 'Qa' if sort potential merges by angle */
+  boolT APPROXhull;       /* true 'Wn' if MINoutside set */
+  realT MINoutside;       /*   'Wn' min. distance for an outside point */
+  boolT ATinfinity;       /* true 'Qz' if point num_points-1 is "at-infinity"
+                             for improving precision in Delaunay triangulations */
+  boolT AVOIDold;         /* true 'Q4' if avoid old->new merges */
+  boolT BESToutside;      /* true 'Qf' if partition points into best outsideset */
+  boolT CDDinput;         /* true 'Pc' if input uses CDD format (1.0/offset first) */
+  boolT CDDoutput;        /* true 'PC' if print normals in CDD format (offset first) */
+  boolT CHECKfrequently;  /* true 'Tc' if checking frequently */
+  realT premerge_cos;     /*   'A-n'   cos_max when pre merging */
+  realT postmerge_cos;    /*   'An'    cos_max when post merging */
+  boolT DELAUNAY;         /* true 'd' if computing DELAUNAY triangulation */
+  boolT DOintersections;  /* true 'Gh' if print hyperplane intersections */
+  int   DROPdim;          /* drops dim 'GDn' for 4-d -> 3-d output */
+  boolT FORCEoutput;      /* true 'Po' if forcing output despite degeneracies */
+  int   GOODpoint;        /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
+  pointT *GOODpointp;     /*   the actual point */
+  boolT GOODthreshold;    /* true if qh lower_threshold/upper_threshold defined
+  			     false if qh SPLITthreshold */
+  int   GOODvertex;       /* 1+n, good facet if vertex for point n */
+  pointT *GOODvertexp;     /*   the actual point */
+  boolT HALFspace;        /* true 'Hn,n,n' if halfspace intersection */
+  int   IStracing;        /* trace execution, 0=none, 1=least, 4=most, -1=events */
+  int   KEEParea;         /* 'PAn' number of largest facets to keep */
+  boolT KEEPcoplanar;     /* true 'Qc' if keeping nearest facet for coplanar points */
+  boolT KEEPinside;       /* true 'Qi' if keeping nearest facet for inside points
+			      set automatically if 'd Qc' */
+  int   KEEPmerge;        /* 'PMn' number of facets to keep with most merges */
+  realT KEEPminArea;      /* 'PFn' minimum facet area to keep */
+  realT MAXcoplanar;      /* 'Un' max distance below a facet to be coplanar*/
+  boolT MERGEexact;	  /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
+  boolT MERGEindependent; /* true 'Q2' if merging independent sets */
+  boolT MERGING;          /* true if exact-, pre- or post-merging, with angle and centrum tests */
+  realT   premerge_centrum;  /*   'C-n' centrum_radius when pre merging.  Default is round-off */
+  realT   postmerge_centrum; /*   'Cn' centrum_radius when post merging.  Default is round-off */
+  boolT MERGEvertices;	  /* true 'Q3' if merging redundant vertices */
+  realT MINvisible;       /* 'Vn' min. distance for a facet to be visible */
+  boolT NOnarrow;         /* true 'Q10' if no special processing for narrow distributions */
+  boolT NOnearinside;     /* true 'Q8' if ignore near-inside points when partitioning */
+  boolT NOpremerge;       /* true 'Q0' if no defaults for C-0 or Qx */
+  boolT ONLYgood; 	  /* true 'Qg' if process points with good visible or horizon facets */
+  boolT ONLYmax; 	  /* true 'Qm' if only process points that increase max_outside */
+  boolT PICKfurthest;     /* true 'Q9' if process furthest of furthest points*/
+  boolT POSTmerge;        /* true if merging after buildhull (Cn or An) */
+  boolT PREmerge;         /* true if merging during buildhull (C-n or A-n) */
+  			/* NOTE: some of these names are similar to qh_PRINT names */
+  boolT PRINTcentrums;	  /* true 'Gc' if printing centrums */
+  boolT PRINTcoplanar;    /* true 'Gp' if printing coplanar points */
+  int	PRINTdim;      	  /* print dimension for Geomview output */
+  boolT PRINTdots;        /* true 'Ga' if printing all points as dots */
+  boolT PRINTgood;        /* true 'Pg' if printing good facets */
+  boolT PRINTinner;	  /* true 'Gi' if printing inner planes */
+  boolT PRINTneighbors;	  /* true 'PG' if printing neighbors of good facets */
+  boolT PRINTnoplanes;	  /* true 'Gn' if printing no planes */
+  boolT PRINToptions1st;  /* true 'FO' if printing options to stderr */
+  boolT PRINTouter;	  /* true 'Go' if printing outer planes */
+  boolT PRINTprecision;   /* false 'Pp' if not reporting precision problems */
+  qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
+  boolT PRINTridges;      /* true 'Gr' if print ridges */
+  boolT PRINTspheres;     /* true 'Gv' if print vertices as spheres */
+  boolT PRINTstatistics;  /* true 'Ts' if printing statistics to stderr */
+  boolT PRINTsummary;     /* true 's' if printing summary to stderr */
+  boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
+  boolT PROJECTdelaunay;  /* true if DELAUNAY, no readpoints() and
+			     need projectinput() for Delaunay in qh_init_B */
+  int   PROJECTinput;     /* number of projected dimensions 'bn:0Bn:0' */
+  boolT QUICKhelp;	  /* true if quick help message for degen input */
+  boolT RANDOMdist;       /* true if randomly change distplane and setfacetplane */
+  realT RANDOMfactor;     /*    maximum random perturbation */
+  realT RANDOMa;         /*  qh_randomfactor is randr * RANDOMa + RANDOMb */
+  realT RANDOMb;
+  boolT RANDOMoutside;    /* true if select a random outside point */
+  int	REPORTfreq;       /* buildtracing reports every n facets */
+  int   REPORTfreq2;	  /* tracemerging reports every REPORTfreq/2 facets */
+  int	RERUN;            /* 'TRn' rerun qhull n times (qh.build_cnt) */
+  int	ROTATErandom;	  /* 'QRn' seed, 0 time, >= rotate input */
+  boolT SCALEinput;       /* true 'Qbk' if scaling input */
+  boolT SCALElast;        /* true 'Qbb' if scale last coord to max prev coord */
+  boolT SETroundoff;      /* true 'E' if qh DISTround is predefined */
+  boolT SKIPcheckmax;	  /* true 'Q5' if skip qh_check_maxout */
+  boolT SKIPconvex;       /* true 'Q6' if skip convexity testing during pre-merge */
+  boolT SPLITthresholds;  /* true if upper_/lower_threshold defines a region
+                               used only for printing (not for qh ONLYgood) */
+  int	STOPcone;         /* 'TCn' 1+n for stopping after cone for point n*/
+			  /*       also used by qh_build_withresart for err exit*/
+  int	STOPpoint;        /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
+			                adding point n */
+  int	TESTpoints;	  /* 'QTn' num of test points after qh.num_points.  Test points always coplanar. */
+  boolT TESTvneighbors;   /*  true 'Qv' if test vertex neighbors at end */
+  int   TRACElevel;       /* 'Tn' conditional IStracing level */
+  int	TRACElastrun;	  /*  qh.TRACElevel applies to last qh.RERUN */
+  int   TRACEpoint;       /* 'TPn' start tracing when point n is a vertex */
+  realT TRACEdist;        /* 'TWn' start tracing when merge distance too big */
+  int   TRACEmerge;       /* 'TMn' start tracing before this merge */
+  boolT TRIangulate;	  /* true 'Qt' if triangulate non-simplicial facets */
+  boolT TRInormals;	  /* true 'Q11' if triangulate duplicates normals (sets Qt) */
+  boolT UPPERdelaunay;    /* true 'Qu' if computing furthest-site Delaunay */
+  boolT VERIFYoutput;     /* true 'Tv' if verify output at end of qhull */
+  boolT VIRTUALmemory;    /* true 'Q7' if depth-first processing in buildhull */
+  boolT VORONOI;	  /* true 'v' if computing Voronoi diagram */
+
+  /*--------input constants ---------*/
+  realT AREAfactor;       /* 1/(hull_dim-1)! for converting det's to area */
+  boolT DOcheckmax;       /* true if calling qh_check_maxout (qh_initqhull_globals) */
+  char	*feasible_string;  /* feasible point 'Hn,n,n' for halfspace intersection */
+  coordT *feasible_point;  /*    as coordinates, both malloc'd */
+  boolT GETarea;          /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
+  boolT KEEPnearinside;   /* true if near-inside points in coplanarset */
+  int 	hull_dim;         /* dimension of hull, set by initbuffers */
+  int 	input_dim;	  /* dimension of input, set by initbuffers */
+  int 	num_points;       /* number of input points */
+  pointT *first_point;    /* array of input points, see POINTSmalloc */
+  boolT POINTSmalloc;     /*   true if qh first_point/num_points allocated */
+  pointT *input_points;   /* copy of original qh.first_point for input points for qh_joggleinput */
+  boolT input_malloc;     /* true if qh input_points malloc'd */
+  char 	qhull_command[256];/* command line that invoked this program */
+  char 	rbox_command[256]; /* command line that produced the input points */
+  char  qhull_options[512];/* descriptive list of options */
+  int   qhull_optionlen;  /*    length of last line */
+  int   qhull_optionsiz;  /*     size of qhull_options before qh_initbuild */
+  boolT VERTEXneighbors;  /* true if maintaining vertex neighbors */
+  boolT ZEROcentrum;      /* true if 'C-0' or 'C-0 Qx'.  sets ZEROall_ok */
+  realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
+                             must set either GOODthreshold or SPLITthreshold
+  			     if Delaunay, default is 0.0 for upper envelope */
+  realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
+  realT *upper_bound;     /* scale point[k] to new upper bound */
+  realT *lower_bound;     /* scale point[k] to new lower bound
+  			     project if both upper_ and lower_bound == 0 */
+
+/*----------------------------------
+
+  qh precision constants
+    precision constants for Qhull
+
+  notes:
+    qh_detroundoff() computes the maximum roundoff error for distance
+    and other computations.  It also sets default values for the
+    qh constants above.
+*/
+  realT ANGLEround;       /* max round off error for angles */
+  realT centrum_radius;   /* max centrum radius for convexity (roundoff added) */
+  realT cos_max;	  /* max cosine for convexity (roundoff added) */
+  realT DISTround;        /* max round off error for distances, 'E' overrides */
+  realT MAXabs_coord;     /* max absolute coordinate */
+  realT MAXlastcoord;     /* max last coordinate for qh_scalelast */
+  realT MAXsumcoord;      /* max sum of coordinates */
+  realT MAXwidth;         /* max rectilinear width of point coordinates */
+  realT MINdenom_1;       /* min. abs. value for 1/x */
+  realT MINdenom;         /*    use divzero if denominator < MINdenom */
+  realT MINdenom_1_2;     /* min. abs. val for 1/x that allows normalization */
+  realT MINdenom_2;       /*    use divzero if denominator < MINdenom_2 */
+  realT MINlastcoord;     /* min. last coordinate for qh_scalelast */
+  boolT NARROWhull;       /* set in qh_initialhull if angle < qh_MAXnarrow */
+  realT *NEARzero;        /* hull_dim array for near zero in gausselim */
+  realT NEARinside;       /* keep points for qh_check_maxout if close to facet */
+  realT ONEmerge;         /* max distance for merging simplicial facets */
+  realT outside_err;      /* application's epsilon for coplanar points
+                             qh_check_bestdist() qh_check_points() reports error if point outside */
+  realT WIDEfacet;        /* size of wide facet for skipping ridge in
+			     area computation and locking centrum */
+  
+/*----------------------------------
+
+  qh internal constants
+    internal constants for Qhull
+*/
+  char qhull[sizeof("qhull")]; /* for checking ownership */
+  void *old_stat;         /* pointer to saved qh_qhstat, qh_save_qhull */
+  jmp_buf errexit;        /* exit label for qh_errexit, defined by setjmp() */
+  char jmpXtra[40];       /* extra bytes in case jmp_buf is defined wrong by compiler */
+  jmp_buf restartexit;    /* restart label for qh_errexit, defined by setjmp() */
+  char jmpXtra2[40];      /* extra bytes in case jmp_buf is defined wrong by compiler*/
+  FILE *fin;              /* pointer to input file, init by qh_meminit */
+  FILE *fout;             /* pointer to output file */
+  FILE *ferr;             /* pointer to error file */
+  pointT *interior_point; /* center point of the initial simplex*/
+  int   normal_size;      /* size in bytes for facet normals and point coords*/
+  int   center_size;      /* size in bytes for Voronoi centers */
+  int   TEMPsize;         /* size for small, temporary sets (in quick mem) */
+
+/*----------------------------------
+
+  qh facet and vertex lists
+    defines lists of facets, new facets, visible facets, vertices, and
+    new vertices.  Includes counts, next ids, and trace ids.
+  see:
+    qh_resetlists()
+*/
+  facetT *facet_list;     /* first facet */
+  facetT  *facet_tail;     /* end of facet_list (dummy facet) */
+  facetT *facet_next;     /* next facet for buildhull()
+    			     previous facets do not have outside sets
+                             NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
+  facetT *newfacet_list;  /* list of new facets to end of facet_list */
+  facetT *visible_list;   /* list of visible facets preceeding newfacet_list,
+                             facet->visible set */
+  int       num_visible;  /* current number of visible facets */
+  unsigned tracefacet_id;  /* set at init, then can print whenever */
+  facetT *tracefacet;     /*   set in newfacet/mergefacet, undone in delfacet*/
+  unsigned tracevertex_id;  /* set at buildtracing, can print whenever */
+  vertexT *tracevertex;     /*   set in newvertex, undone in delvertex*/
+  vertexT *vertex_list;     /* list of all vertices, to vertex_tail */
+  vertexT  *vertex_tail;    /*      end of vertex_list (dummy vertex) */
+  vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
+                             all vertices have 'newlist' set */
+  int 	num_facets;	  /* number of facets in facet_list
+			     includes visble faces (num_visible) */
+  int 	num_vertices;     /* number of vertices in facet_list */
+  int   num_outside;      /* number of points in outsidesets (for tracing and RANDOMoutside)
+                               includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
+  int   num_good;         /* number of good facets (after findgood_all) */
+  unsigned facet_id;      /* ID of next, new facet from newfacet() */
+  unsigned ridge_id;      /* ID of next, new ridge from newridge() */
+  unsigned vertex_id;     /* ID of next, new vertex from newvertex() */
+
+/*----------------------------------
+
+  qh global variables
+    defines minimum and maximum distances, next visit ids, several flags,
+    and other global variables.
+    initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
+*/
+  unsigned long hulltime; /* ignore time to set up input and randomize */
+                          /*   use unsigned to avoid wrap-around errors */
+  boolT ALLOWrestart;     /* true if qh_precision can use qh.restartexit */
+  int   build_cnt;        /* number of calls to qh_initbuild */
+  qh_CENTER CENTERtype;   /* current type of facet->center, qh_CENTER */
+  int 	furthest_id;      /* pointid of furthest point, for tracing */
+  facetT *GOODclosest;    /* closest facet to GOODthreshold in qh_findgood */
+  realT JOGGLEmax;        /* set 'QJn' if randomly joggle input */
+  boolT maxoutdone;       /* set qh_check_maxout(), cleared by qh_addpoint() */
+  realT max_outside;      /* maximum distance from a point to a facet,
+			       before roundoff, not simplicial vertices
+			       actual outer plane is +DISTround and
+			       computed outer plane is +2*DISTround */
+  realT max_vertex;       /* maximum distance (>0) from vertex to a facet,
+			       before roundoff, due to a merge */
+  realT min_vertex;       /* minimum distance (<0) from vertex to a facet,
+			       before roundoff, due to a merge
+			       if qh.JOGGLEmax, qh_makenewplanes sets it
+  			       recomputed if qh.DOcheckmax, default -qh.DISTround */
+  boolT NEWfacets;        /* true while visible facets invalid due to new or merge
+			      from makecone/attachnewfacets to deletevisible */
+  boolT findbestnew;	  /* true if partitioning calls qh_findbestnew */
+  boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
+  boolT NOerrexit;        /* true if qh.errexit is not available */
+  realT PRINTcradius;     /* radius for printing centrums */
+  realT PRINTradius;      /* radius for printing vertex spheres and points */
+  boolT POSTmerging;      /* true when post merging */
+  int 	printoutvar;	  /* temporary variable for qh_printbegin, etc. */
+  int 	printoutnum;	  /* number of facets printed */
+  boolT QHULLfinished;    /* True after qhull() is finished */
+  realT totarea;          /* 'FA': total facet area computed by qh_getarea */
+  realT totvol;           /* 'FA': total volume computed by qh_getarea */
+  unsigned int visit_id;  /* unique ID for searching neighborhoods, */
+  unsigned int vertex_visit; /* unique ID for searching vertices */
+  boolT ZEROall_ok;       /* True if qh_checkzero always succeeds */
+  boolT WAScoplanar;      /* True if qh_partitioncoplanar (qh_check_maxout) */
+  
+/*----------------------------------
+
+  qh global sets
+    defines sets for merging, initial simplex, hashing, extra input points,
+    and deleted vertices
+*/
+  setT *facet_mergeset;   /* temporary set of merges to be done */
+  setT *degen_mergeset;   /* temporary set of degenerate and redundant merges */
+  setT *hash_table;	  /* hash table for matching ridges in qh_matchfacets
+                             size is setsize() */
+  setT *other_points;     /* additional points (first is qh interior_point) */
+  setT *del_vertices;     /* vertices to partition and delete with visible
+                             facets.  Have deleted set for checkfacet */
+
+/*----------------------------------
+
+  qh global buffers
+    defines buffers for maxtrix operations, input, and error messages
+*/
+  coordT *gm_matrix;      /* (dim+1)Xdim matrix for geom.c */
+  coordT **gm_row;        /* array of gm_matrix rows */
+  char* line;             /* malloc'd input line of maxline+1 chars */
+  int maxline;
+  coordT *half_space;     /* malloc'd input array for halfspace (qh normal_size+coordT) */
+  coordT *temp_malloc;    /* malloc'd input array for points */
+  
+/*----------------------------------
+
+  qh static variables
+    defines static variables for individual functions
+
+  notes:
+    do not use 'static' within a function.  Multiple instances of qhull
+    may exist.
+
+    do not assume zero initialization, 'QPn' may cause a restart
+*/
+  boolT ERREXITcalled;    /* true during errexit (prevents duplicate calls */
+  boolT firstcentrum; 	  /* for qh_printcentrum */
+  realT last_low;         /* qh_scalelast parameters for qh_setdelaunay */
+  realT last_high;
+  realT last_newhigh;
+  unsigned lastreport;    /* for qh_buildtracing */
+  int mergereport;        /* for qh_tracemerging */
+  boolT old_randomdist;   /* save RANDOMdist when io, tracing, or statistics */
+  int   ridgeoutnum;      /* number of ridges in 4OFF output */
+  void *old_qhstat;       /* for saving qh_qhstat in save_qhull() */
+  setT *old_tempstack;     /* for saving qhmem.tempstack in save_qhull */
+  setT *coplanarset;      /* set of coplanar facets for searching qh_findbesthorizon() */
+};
+
+/*=========== -macros- =========================*/
+
+/*----------------------------------
+
+  otherfacet_(ridge, facet)
+    return neighboring facet for a ridge in facet
+*/
+#define otherfacet_(ridge, facet) \
+                        (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
+
+/*----------------------------------
+
+  getid_(p)
+    return ID for facet, ridge, or vertex
+    return MAXINT if NULL (-1 causes type conversion error )
+*/
+#define getid_(p)       ((p) ? (p)->id : -1)
+
+/*============== FORALL macros ===================*/
+
+/*----------------------------------
+
+  FORALLfacets { ... }
+    assign 'facet' to each facet in qh.facet_list
+
+  notes:
+    uses 'facetT *facet;'
+    assumes last facet is a sentinel
+
+  see:
+    FORALLfacet_( facetlist )
+*/
+#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
+
+/*----------------------------------
+
+  FORALLpoints { ... }
+    assign 'point' to each point in qh.first_point, qh.num_points
+
+  declare:
+    coordT *point, *pointtemp;
+*/
+#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
+
+/*----------------------------------
+
+  FORALLpoint_( points, num) { ... }
+    assign 'point' to each point in points array of num points
+
+  declare:
+    coordT *point, *pointtemp;
+*/
+#define FORALLpoint_(points, num) for(point= (points), \
+      pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
+
+/*----------------------------------
+
+  FORALLvertices { ... }
+    assign 'vertex' to each vertex in qh.vertex_list
+
+  declare:
+    vertexT *vertex;
+
+  notes:
+    assumes qh.vertex_list terminated with a sentinel
+*/
+#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
+
+/*----------------------------------
+
+  FOREACHfacet_( facets ) { ... }
+    assign 'facet' to each facet in facets
+
+  declare:
+    facetT *facet, **facetp;
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHfacet_(facets)    FOREACHsetelement_(facetT, facets, facet)
+
+/*----------------------------------
+
+  FOREACHneighbor_( facet ) { ... }
+    assign 'neighbor' to each neighbor in facet->neighbors
+
+  FOREACHneighbor_( vertex ) { ... }
+    assign 'neighbor' to each neighbor in vertex->neighbors
+
+  declare:
+    facetT *neighbor, **neighborp;
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHneighbor_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighbor)
+
+/*----------------------------------
+
+  FOREACHpoint_( points ) { ... }
+    assign 'point' to each point in points set
+
+  declare:
+    pointT *point, **pointp;
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHpoint_(points)    FOREACHsetelement_(pointT, points, point)
+
+/*----------------------------------
+
+  FOREACHridge_( ridges ) { ... }
+    assign 'ridge' to each ridge in ridges set
+
+  declare:
+    ridgeT *ridge, **ridgep;
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHridge_(ridges)    FOREACHsetelement_(ridgeT, ridges, ridge)
+
+/*----------------------------------
+
+  FOREACHvertex_( vertices ) { ... }
+    assign 'vertex' to each vertex in vertices set
+
+  declare:
+    vertexT *vertex, **vertexp;
+
+  see:
+    FOREACHsetelement_
+*/
+#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
+
+/*----------------------------------
+
+  FOREACHfacet_i_( facets ) { ... }
+    assign 'facet' and 'facet_i' for each facet in facets set
+
+  declare:
+    facetT *facet;
+    int     facet_n, facet_i;
+
+  see:
+    FOREACHsetelement_i_
+*/
+#define FOREACHfacet_i_(facets)    FOREACHsetelement_i_(facetT, facets, facet)
+
+/*----------------------------------
+
+  FOREACHneighbor_i_( facet ) { ... }
+    assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
+
+  FOREACHneighbor_i_( vertex ) { ... }
+    assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
+
+  declare:
+    facetT *neighbor;
+    int     neighbor_n, neighbor_i;
+
+  see:
+    FOREACHsetelement_i_
+*/
+#define FOREACHneighbor_i_(facet)  FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
+
+/*----------------------------------
+
+  FOREACHpoint_i_( points ) { ... }
+    assign 'point' and 'point_i' for each point in points set
+
+  declare:
+    pointT *point;
+    int     point_n, point_i;
+
+  see:
+    FOREACHsetelement_i_
+*/
+#define FOREACHpoint_i_(points)    FOREACHsetelement_i_(pointT, points, point)
+
+/*----------------------------------
+
+  FOREACHridge_i_( ridges ) { ... }
+    assign 'ridge' and 'ridge_i' for each ridge in ridges set
+
+  declare:
+    ridgeT *ridge;
+    int     ridge_n, ridge_i;
+
+  see:
+    FOREACHsetelement_i_
+*/
+#define FOREACHridge_i_(ridges)    FOREACHsetelement_i_(ridgeT, ridges, ridge)
+
+/*----------------------------------
+
+  FOREACHvertex_i_( vertices ) { ... }
+    assign 'vertex' and 'vertex_i' for each vertex in vertices set
+
+  declare:
+    vertexT *vertex;
+    int     vertex_n, vertex_i;
+
+  see:
+    FOREACHsetelement_i_
+ */
+#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
+
+/********* -qhull.c prototypes (duplicated from qhull_a.h) **********************/
+
+void    qh_qhull (void);
+boolT   qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
+void	qh_printsummary(FILE *fp);
+
+/********* -user.c prototypes (alphabetical) **********************/
+
+void 	qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
+void 	qh_errprint(char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
+int     qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc,
+		char *qhull_cmd, FILE *outfile, FILE *errfile);
+void    qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
+void 	qh_user_memsizes (void);
+
+/***** -geom.c/geom2.c prototypes (duplicated from geom.h) ****************/
+
+facetT *qh_findbest (pointT *point, facetT *startfacet,
+		     boolT bestoutside, boolT newfacets, boolT noupper,
+		     realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbestnew (pointT *point, facetT *startfacet,
+                     realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
+boolT   qh_gram_schmidt(int dim, realT **rows);
+void    qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
+void	qh_printsummary(FILE *fp);
+void    qh_projectinput (void);
+void    qh_randommatrix (realT *buffer, int dim, realT **row);
+void    qh_rotateinput (realT **rows);
+void    qh_scaleinput (void);
+void    qh_setdelaunay (int dim, int count, pointT *points);
+coordT  *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
+
+/***** -global.c prototypes (alphabetical) ***********************/
+
+unsigned long qh_clock (void);
+void 	qh_checkflags (char *command, char *hiddenflags);
+void 	qh_freebuffers (void);
+void    qh_freeqhull (boolT allmem);
+void    qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
+void    qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc);
+void 	qh_init_qhull_command (int argc, char *argv[]);
+void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+void 	qh_initflags (char *command);
+void 	qh_initqhull_buffers (void);
+void 	qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc);
+void    qh_initqhull_mem (void);
+void 	qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile);
+void 	qh_initthresholds (char *command);
+void    qh_option (char *option, int *i, realT *r);
+#if qh_QHpointer
+void 	qh_restore_qhull (qhT **oldqh);
+qhT    *qh_save_qhull (void);
+#endif
+
+/***** -io.c prototypes (duplicated from io.h) ***********************/
+
+void    dfacet( unsigned id);
+void    dvertex( unsigned id);
+void	qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
+void	qh_produce_output(void);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+
+
+/********* -mem.c prototypes (duplicated from mem.h) **********************/
+
+void qh_meminit (FILE *ferr);
+void qh_memfreeshort (int *curlong, int *totlong);
+
+/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
+
+void    qh_check_output (void);
+void    qh_check_points (void);
+setT   *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
+facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside);
+vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
+pointT *qh_point (int id);
+setT   *qh_pointfacet (void /*qh.facet_list*/);
+int     qh_pointid (pointT *point);
+setT   *qh_pointvertex (void /*qh.facet_list*/);
+void    qh_setvoronoi_all (void);
+void	qh_triangulate (void /*qh facet_list*/);
+
+/********* -stat.c prototypes (duplicated from stat.h) **********************/
+
+void    qh_collectstatistics (void);
+void    qh_printallstatistics (FILE *fp, char *string);
+
+#endif /* qhDEFqhull */

Added: trunk/scipy/spatial/qhull/src/qhull_a.h
===================================================================
--- trunk/scipy/spatial/qhull/src/qhull_a.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qhull_a.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,127 @@
+/*
  ---------------------------------
+
+   qhull_a.h 
+   all header files for compiling qhull
+
+   see qh-qhull.htm
+
+   see qhull.h for user-level definitions
+   
+   see user.h for user-defineable constants
+   
+   defines internal functions for qhull.c global.c
+
+   copyright (c) 1993-2003, The Geometry Center
+
+   Notes:  grep for ((" and (" to catch fprintf("lkasdjf");
+           full parens around (x?y:z)
+	   use '#include qhull/qhull_a.h' to avoid name clashes
+*/
+
+#ifndef qhDEFqhulla
+#define qhDEFqhulla
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include     /* some compilers will not need float.h */
+#include 
+#include 
+#include 
+/*** uncomment here and qset.c
+     if string.h does not define memcpy()
+#include 
+*/
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+#include "geom.h"
+#include "merge.h"
+#include "poly.h"
+#include "io.h"
+#include "stat.h"
+
+#if qh_CLOCKtype == 2  /* defined in user.h from qhull.h */
+#include 
+#include 
+#include 
+#endif
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ */
+#pragma warning( disable : 4056)  /* float constant expression.  Looks like a compiler bug */
+#pragma warning( disable : 4146)  /* unary minus applied to unsigned type */
+#pragma warning( disable : 4244)  /* conversion from 'unsigned long' to 'real' */
+#pragma warning( disable : 4305)  /* conversion from 'const double' to 'float' */
+#endif
+
+/* ======= -macros- =========== */
+
+/*----------------------------------
+  
+  traceN((fp.ferr, "format\n", vars));  
+    calls fprintf if qh.IStracing >= N
+  
+  notes:
+    removing tracing reduces code size but doesn't change execution speed
+*/
+#ifndef qh_NOtrace
+#define trace0(args) {if (qh IStracing) fprintf args;}
+#define trace1(args) {if (qh IStracing >= 1) fprintf args;}
+#define trace2(args) {if (qh IStracing >= 2) fprintf args;}
+#define trace3(args) {if (qh IStracing >= 3) fprintf args;}
+#define trace4(args) {if (qh IStracing >= 4) fprintf args;}
+#define trace5(args) {if (qh IStracing >= 5) fprintf args;}
+#else /* qh_NOtrace */
+#define trace0(args) {}
+#define trace1(args) {}
+#define trace2(args) {}
+#define trace3(args) {}
+#define trace4(args) {}
+#define trace5(args) {}
+#endif /* qh_NOtrace */
+
+/***** -qhull.c prototypes (alphabetical after qhull) ********************/
+
+void 	qh_qhull (void);
+boolT   qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
+void 	qh_buildhull(void);
+void    qh_buildtracing (pointT *furthest, facetT *facet);
+void    qh_build_withrestart (void);
+void 	qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet);
+void    qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
+pointT *qh_nextfurthest (facetT **visible);
+void 	qh_partitionall(setT *vertices, pointT *points,int npoints);
+void    qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist);
+void    qh_partitionpoint (pointT *point, facetT *facet);
+void 	qh_partitionvisible(boolT allpoints, int *numpoints);
+void    qh_precision (char *reason);
+void	qh_printsummary(FILE *fp);
+
+/***** -global.c internal prototypes (alphabetical) ***********************/
+
+void    qh_appendprint (qh_PRINT format);
+void 	qh_freebuild (boolT allmem);
+void 	qh_freebuffers (void);
+void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+int     qh_strtol (const char *s, char **endp);
+double  qh_strtod (const char *s, char **endp);
+
+/***** -stat.c internal prototypes (alphabetical) ***********************/
+
+void	qh_allstatA (void);
+void	qh_allstatB (void);
+void	qh_allstatC (void);
+void	qh_allstatD (void);
+void	qh_allstatE (void);
+void	qh_allstatE2 (void);
+void	qh_allstatF (void);
+void	qh_allstatG (void);
+void	qh_allstatH (void);
+void 	qh_freebuffers (void);
+void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
+
+#endif /* qhDEFqhulla */

Added: trunk/scipy/spatial/qhull/src/qhull_interface.cpp
===================================================================
--- trunk/scipy/spatial/qhull/src/qhull_interface.cpp	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qhull_interface.cpp	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,96 @@
+/*
  ---------------------------------
+*/
+
+#include 
+#include 
+
+//--- Include qhull, so it works from with in a C++ source file
+//---
+//--- In MVC one cannot just do:
+//---
+//---    extern "C"
+//---    {
+//---      #include "qhull_a.h"
+//---    }
+//---
+//--- Because qhull_a.h includes math.h, which can not appear
+//--- inside a extern "C" declaration.
+//---
+//--- Maybe that why Numerical recipes in C avoid this problem, by removing
+//--- standard include headers from its header files and add them in the
+//--- respective source files instead.
+//---
+//--- [K. Erleben]
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#if defined(__cplusplus)
+}
+#endif
+
+/*********************************************************************/
+/*                                                                   */
+/*                                                                   */
+/*                                                                   */
+/*                                                                   */
+/*********************************************************************/
+
+void compute_convex_hull(void)
+{  
+	int dim;  	              /* dimension of points */
+	int numpoints;            /* number of points */
+	coordT *points;           /* array of coordinates for each point */ 
+	boolT ismalloc;           /* True if qhull should free points in qh_freeqhull() or reallocation */ 
+	char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
+	FILE *outfile= stdout;    /* output from qh_produce_output()			
+	                             use NULL to skip qh_produce_output() */ 
+	FILE *errfile= stderr;    /* error messages from qhull code */ 
+	int exitcode;             /* 0 if no error from qhull */
+	facetT *facet;	          /* set by FORALLfacets */
+	int curlong, totlong;	  /* memory remaining after qh_memfreeshort */
+
+   	/* initialize dim, numpoints, points[], ismalloc here */
+	exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+							flags, outfile, errfile);
+	if (!exitcode) { /* if no error */ 
+		/* 'qh facet_list' contains the convex hull */
+		FORALLfacets {
+			/* ... your code ... */ 
+		}
+	}
+	qh_freeqhull(!qh_ALL);  
+	qh_memfreeshort (&curlong, &totlong);
+	if (curlong || totlong)
+		fprintf (errfile, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n", 
+		             totlong, curlong);
+};
+
+/*********************************************************************/
+/*                                                                   */
+/*                                                                   */
+/*                                                                   */
+/*                                                                   */
+/*********************************************************************/
+
+void main() 
+{ 
+	cout << "Hello world" << endl;
+	
+	cout << "Press any key..." << endl;  
+	
+	while(!_kbhit());
+
+};

Added: trunk/scipy/spatial/qhull/src/qset.c
===================================================================
--- trunk/scipy/spatial/qhull/src/qset.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qset.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,1301 @@
+/*
  ---------------------------------
+
+   qset.c 
+   implements set manipulations needed for quickhull 
+
+   see qh-set.htm and qset.h
+
+   copyright (c) 1993-2003 The Geometry Center        
+*/
+
+#include 
+#include 
+/*** uncomment here and qhull_a.h 
+     if string.h does not define memcpy()
+#include 
+*/
+#include "qset.h"
+#include "mem.h"
+
+#ifndef qhDEFqhull
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+void    qh_errexit(int exitcode, facetT *, ridgeT *);
+#endif
+
+/*=============== internal macros ===========================*/
+
+/*---------------------------------
+   
+  SETsizeaddr_(set) 
+    return pointer to actual size+1 of set (set CANNOT be NULL!!)
+      
+  notes:
+    *SETsizeaddr==NULL or e[*SETsizeaddr-1].p==NULL
+*/
+#define SETsizeaddr_(set) (&((set)->e[(set)->maxsize].i))
+
+/*============ functions in alphabetical order ===================*/
+  
+/*----------------------------------
+   
+  qh_setaddnth( setp, nth, newelem)
+    adds newelem as n'th element of sorted or unsorted *setp
+      
+  notes:
+    *setp and newelem must be defined
+    *setp may be a temp set
+    nth=0 is first element
+    errors if nth is out of bounds
+   
+  design:
+    expand *setp if empty or full
+    move tail of *setp up one
+    insert newelem
+*/
+void qh_setaddnth(setT **setp, int nth, void *newelem) {
+  int *sizep, oldsize, i;
+  void **oldp, **newp;
+
+  if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
+    qh_setlarger(setp);
+    sizep= SETsizeaddr_(*setp);
+  }
+  oldsize= *sizep - 1;
+  if (nth < 0 || nth > oldsize) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint (qhmem.ferr, "", *setp);
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  (*sizep)++;
+  oldp= SETelemaddr_(*setp, oldsize, void);   /* NULL */
+  newp= oldp+1;
+  for (i= oldsize-nth+1; i--; )  /* move at least NULL  */
+    *(newp--)= *(oldp--);       /* may overwrite *sizep */
+  *newp= newelem;
+} /* setaddnth */
+
+
+/*----------------------------------
+   
+  setaddsorted( setp, newelem )
+    adds an newelem into sorted *setp
+      
+  notes:
+    *setp and newelem must be defined
+    *setp may be a temp set
+    nop if newelem already in set
+  
+  design:
+    find newelem's position in *setp
+    insert newelem
+*/
+void qh_setaddsorted(setT **setp, void *newelem) {
+  int newindex=0;
+  void *elem, **elemp;
+
+  FOREACHelem_(*setp) {          /* could use binary search instead */
+    if (elem < newelem)
+      newindex++;
+    else if (elem == newelem)
+      return;
+    else
+      break;
+  }
+  qh_setaddnth(setp, newindex, newelem);
+} /* setaddsorted */
+
+
+/*---------------------------------
+  
+  qh_setappend( setp, newelem)
+    append newelem to *setp
+
+  notes:
+    *setp may be a temp set
+    *setp and newelem may be NULL
+
+  design:
+    expand *setp if empty or full
+    append newelem to *setp
+    
+*/
+void qh_setappend(setT **setp, void *newelem) {
+  int *sizep;
+  void **endp;
+
+  if (!newelem)
+    return;
+  if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
+    qh_setlarger(setp);
+    sizep= SETsizeaddr_(*setp);
+  }
+  *(endp= &((*setp)->e[(*sizep)++ - 1].p))= newelem;
+  *(++endp)= NULL;
+} /* setappend */
+
+/*---------------------------------
+  
+  qh_setappend_set( setp, setA) 
+    appends setA to *setp
+
+  notes:
+    *setp can not be a temp set
+    *setp and setA may be NULL
+
+  design:
+    setup for copy
+    expand *setp if it is too small
+    append all elements of setA to *setp 
+*/
+void qh_setappend_set(setT **setp, setT *setA) {
+  int *sizep, sizeA, size;
+  setT *oldset;
+
+  if (!setA)
+    return;
+  SETreturnsize_(setA, sizeA);
+  if (!*setp)
+    *setp= qh_setnew (sizeA);
+  sizep= SETsizeaddr_(*setp);
+  if (!(size= *sizep))
+    size= (*setp)->maxsize;
+  else
+    size--;
+  if (size + sizeA > (*setp)->maxsize) {
+    oldset= *setp;
+    *setp= qh_setcopy (oldset, sizeA);
+    qh_setfree (&oldset);
+    sizep= SETsizeaddr_(*setp);
+  }
+  *sizep= size+sizeA+1;   /* memcpy may overwrite */
+  if (sizeA > 0) 
+    memcpy((char *)&((*setp)->e[size].p), (char *)&(setA->e[0].p), SETelemsize *(sizeA+1));
+} /* setappend_set */
+
+
+/*---------------------------------
+  
+  qh_setappend2ndlast( setp, newelem )
+    makes newelem the next to the last element in *setp
+
+  notes:
+    *setp must have at least one element
+    newelem must be defined
+    *setp may be a temp set
+
+  design:
+    expand *setp if empty or full
+    move last element of *setp up one
+    insert newelem
+*/
+void qh_setappend2ndlast(setT **setp, void *newelem) {
+  int *sizep;
+  void **endp, **lastp;
+  
+  if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
+    qh_setlarger(setp);
+    sizep= SETsizeaddr_(*setp);
+  }
+  endp= SETelemaddr_(*setp, (*sizep)++ -1, void); /* NULL */
+  lastp= endp-1;
+  *(endp++)= *lastp;
+  *endp= NULL;    /* may overwrite *sizep */
+  *lastp= newelem;
+} /* setappend2ndlast */
+
+
+/*---------------------------------
+  
+  qh_setcheck( set, typename, id ) 
+    check set for validity
+    report errors with typename and id
+
+  design:
+    checks that maxsize, actual size, and NULL terminator agree
+*/
+void qh_setcheck(setT *set, char *tname, int id) {
+  int maxsize, size;
+  int waserr= 0;
+
+  if (!set)
+    return;
+  SETreturnsize_(set, size);
+  maxsize= set->maxsize;
+  if (size > maxsize || !maxsize) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_setcheck): actual size %d of %s%d is greater than max size %d\n",
+	     size, tname, id, maxsize);
+    waserr= 1;
+  }else if (set->e[size].p) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_setcheck): %s%d (size %d max %d) is not null terminated.\n",
+	     tname, id, maxsize, size-1);
+    waserr= 1;
+  }
+  if (waserr) {
+    qh_setprint (qhmem.ferr, "ERRONEOUS", set);
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+} /* setcheck */
+
+
+/*---------------------------------
+  
+  qh_setcompact( set )
+    remove internal NULLs from an unsorted set
+
+  returns:
+    updated set
+
+  notes:
+    set may be NULL
+    it would be faster to swap tail of set into holes, like qh_setdel
+
+  design:
+    setup pointers into set
+    skip NULLs while copying elements to start of set 
+    update the actual size
+*/
+void qh_setcompact(setT *set) {
+  int size;
+  void **destp, **elemp, **endp, **firstp;
+
+  if (!set)
+    return;
+  SETreturnsize_(set, size);
+  destp= elemp= firstp= SETaddr_(set, void);
+  endp= destp + size;
+  while (1) {
+    if (!(*destp++ = *elemp++)) {
+      destp--;
+      if (elemp > endp)
+	break;
+    }
+  }
+  qh_settruncate (set, destp-firstp);
+} /* setcompact */
+
+
+/*---------------------------------
+  
+  qh_setcopy( set, extra )
+    make a copy of a sorted or unsorted set with extra slots
+
+  returns:
+    new set
+
+  design:
+    create a newset with extra slots
+    copy the elements to the newset
+    
+*/
+setT *qh_setcopy(setT *set, int extra) {
+  setT *newset;
+  int size;
+
+  if (extra < 0)
+    extra= 0;
+  SETreturnsize_(set, size);
+  newset= qh_setnew(size+extra);
+  *SETsizeaddr_(newset)= size+1;    /* memcpy may overwrite */
+  memcpy((char *)&(newset->e[0].p), (char *)&(set->e[0].p), SETelemsize *(size+1));
+  return (newset);
+} /* setcopy */
+
+
+/*---------------------------------
+  
+  qh_setdel( set, oldelem )
+    delete oldelem from an unsorted set
+
+  returns:
+    returns oldelem if found
+    returns NULL otherwise
+    
+  notes:
+    set may be NULL
+    oldelem must not be NULL;
+    only deletes one copy of oldelem in set
+     
+  design:
+    locate oldelem
+    update actual size if it was full
+    move the last element to the oldelem's location
+*/
+void *qh_setdel(setT *set, void *oldelem) {
+  void **elemp, **lastp;
+  int *sizep;
+
+  if (!set)
+    return NULL;
+  elemp= SETaddr_(set, void);
+  while (*elemp != oldelem && *elemp)
+    elemp++;
+  if (*elemp) {
+    sizep= SETsizeaddr_(set);
+    if (!(*sizep)--)         /*  if was a full set */
+      *sizep= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
+    lastp= SETelemaddr_(set, *sizep-1, void);
+    *elemp= *lastp;      /* may overwrite itself */
+    *lastp= NULL;
+    return oldelem;
+  }
+  return NULL;
+} /* setdel */
+
+
+/*---------------------------------
+  
+  qh_setdellast( set) 
+    return last element of set or NULL
+
+  notes:
+    deletes element from set
+    set may be NULL
+
+  design:
+    return NULL if empty
+    if full set
+      delete last element and set actual size
+    else
+      delete last element and update actual size 
+*/
+void *qh_setdellast(setT *set) {
+  int setsize;  /* actually, actual_size + 1 */
+  int maxsize;
+  int *sizep;
+  void *returnvalue;
+  
+  if (!set || !(set->e[0].p))
+    return NULL;
+  sizep= SETsizeaddr_(set);
+  if ((setsize= *sizep)) {
+    returnvalue= set->e[setsize - 2].p;
+    set->e[setsize - 2].p= NULL;
+    (*sizep)--;
+  }else {
+    maxsize= set->maxsize;
+    returnvalue= set->e[maxsize - 1].p;
+    set->e[maxsize - 1].p= NULL;
+    *sizep= maxsize;
+  }
+  return returnvalue;
+} /* setdellast */
+
+
+/*---------------------------------
+  
+  qh_setdelnth( set, nth )
+    deletes nth element from unsorted set 
+    0 is first element
+
+  returns:
+    returns the element (needs type conversion)
+
+  notes:
+    errors if nth invalid
+
+  design:
+    setup points and check nth
+    delete nth element and overwrite with last element
+*/
+void *qh_setdelnth(setT *set, int nth) {
+  void **elemp, **lastp, *elem;
+  int *sizep;
+
+
+  elemp= SETelemaddr_(set, nth, void);
+  sizep= SETsizeaddr_(set);
+  if (!(*sizep)--)         /*  if was a full set */
+    *sizep= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
+  if (nth < 0 || nth >= *sizep) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint (qhmem.ferr, "", set);
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  lastp= SETelemaddr_(set, *sizep-1, void);
+  elem= *elemp;
+  *elemp= *lastp;      /* may overwrite itself */
+  *lastp= NULL;
+  return elem;
+} /* setdelnth */
+
+/*---------------------------------
+  
+  qh_setdelnthsorted( set, nth )
+    deletes nth element from sorted set
+
+  returns:
+    returns the element (use type conversion)
+  
+  notes:
+    errors if nth invalid
+    
+  see also: 
+    setnew_delnthsorted
+
+  design:
+    setup points and check nth
+    copy remaining elements down one
+    update actual size  
+*/
+void *qh_setdelnthsorted(setT *set, int nth) {
+  void **newp, **oldp, *elem;
+  int *sizep;
+
+  sizep= SETsizeaddr_(set);
+  if (nth < 0 || (*sizep && nth >= *sizep-1) || nth >= set->maxsize) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint (qhmem.ferr, "", set);
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  newp= SETelemaddr_(set, nth, void);
+  elem= *newp;
+  oldp= newp+1;
+  while ((*(newp++)= *(oldp++)))
+    ; /* copy remaining elements and NULL */
+  if (!(*sizep)--)         /*  if was a full set */
+    *sizep= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
+  return elem;
+} /* setdelnthsorted */
+
+
+/*---------------------------------
+  
+  qh_setdelsorted( set, oldelem )
+    deletes oldelem from sorted set
+
+  returns:
+    returns oldelem if it was deleted
+  
+  notes:
+    set may be NULL
+
+  design:
+    locate oldelem in set
+    copy remaining elements down one
+    update actual size  
+*/
+void *qh_setdelsorted(setT *set, void *oldelem) {
+  void **newp, **oldp;
+  int *sizep;
+
+  if (!set)
+    return NULL;
+  newp= SETaddr_(set, void);
+  while(*newp != oldelem && *newp)
+    newp++;
+  if (*newp) {
+    oldp= newp+1;
+    while ((*(newp++)= *(oldp++)))
+      ; /* copy remaining elements */
+    sizep= SETsizeaddr_(set);
+    if (!(*sizep)--)    /*  if was a full set */
+      *sizep= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
+    return oldelem;
+  }
+  return NULL;
+} /* setdelsorted */
+
+
+/*---------------------------------
+  
+  qh_setduplicate( set, elemsize )
+    duplicate a set of elemsize elements
+
+  notes:
+    use setcopy if retaining old elements
+
+  design:
+    create a new set
+    for each elem of the old set
+      create a newelem
+      append newelem to newset
+*/
+setT *qh_setduplicate (setT *set, int elemsize) {
+  void		*elem, **elemp, *newElem;
+  setT		*newSet;
+  int		size;
+  
+  if (!(size= qh_setsize (set)))
+    return NULL;
+  newSet= qh_setnew (size);
+  FOREACHelem_(set) {
+    newElem= qh_memalloc (elemsize);
+    memcpy (newElem, elem, elemsize);
+    qh_setappend (&newSet, newElem);
+  }
+  return newSet;
+} /* setduplicate */
+
+
+/*---------------------------------
+  
+  qh_setequal(  )
+    returns 1 if two sorted sets are equal, otherwise returns 0
+
+  notes:
+    either set may be NULL
+
+  design:
+    check size of each set
+    setup pointers
+    compare elements of each set
+*/
+int qh_setequal(setT *setA, setT *setB) {
+  void **elemAp, **elemBp;
+  int sizeA, sizeB;
+  
+  SETreturnsize_(setA, sizeA);
+  SETreturnsize_(setB, sizeB);
+  if (sizeA != sizeB)
+    return 0;
+  if (!sizeA)
+    return 1;
+  elemAp= SETaddr_(setA, void);
+  elemBp= SETaddr_(setB, void);
+  if (!memcmp((char *)elemAp, (char *)elemBp, sizeA*SETelemsize))
+    return 1;
+  return 0;
+} /* setequal */
+
+
+/*---------------------------------
+  
+  qh_setequal_except( setA, skipelemA, setB, skipelemB )
+    returns 1 if sorted setA and setB are equal except for skipelemA & B
+
+  returns:
+    false if either skipelemA or skipelemB are missing
+  
+  notes:
+    neither set may be NULL
+
+    if skipelemB is NULL, 
+      can skip any one element of setB
+
+  design:
+    setup pointers
+    search for skipelemA, skipelemB, and mismatches
+    check results
+*/
+int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB) {
+  void **elemA, **elemB;
+  int skip=0;
+
+  elemA= SETaddr_(setA, void);
+  elemB= SETaddr_(setB, void);
+  while (1) {
+    if (*elemA == skipelemA) {
+      skip++;
+      elemA++;
+    }
+    if (skipelemB) {
+      if (*elemB == skipelemB) {
+        skip++;
+        elemB++;
+      }
+    }else if (*elemA != *elemB) {
+      skip++;
+      if (!(skipelemB= *elemB++))
+        return 0;
+    }
+    if (!*elemA)
+      break;
+    if (*elemA++ != *elemB++) 
+      return 0;
+  }
+  if (skip != 2 || *elemB)
+    return 0;
+  return 1;
+} /* setequal_except */
+  
+
+/*---------------------------------
+  
+  qh_setequal_skip( setA, skipA, setB, skipB )
+    returns 1 if sorted setA and setB are equal except for elements skipA & B
+
+  returns:
+    false if different size
+
+  notes:
+    neither set may be NULL
+
+  design:
+    setup pointers
+    search for mismatches while skipping skipA and skipB
+*/
+int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB) {
+  void **elemA, **elemB, **skipAp, **skipBp;
+
+  elemA= SETaddr_(setA, void);
+  elemB= SETaddr_(setB, void);
+  skipAp= SETelemaddr_(setA, skipA, void);
+  skipBp= SETelemaddr_(setB, skipB, void);
+  while (1) {
+    if (elemA == skipAp)
+      elemA++;
+    if (elemB == skipBp)
+      elemB++;
+    if (!*elemA)
+      break;
+    if (*elemA++ != *elemB++) 
+      return 0;
+  }
+  if (*elemB)
+    return 0;
+  return 1;
+} /* setequal_skip */
+  
+
+/*---------------------------------
+  
+  qh_setfree( setp )
+    frees the space occupied by a sorted or unsorted set
+
+  returns:
+    sets setp to NULL
+    
+  notes:
+    set may be NULL
+
+  design:
+    free array
+    free set
+*/
+void qh_setfree(setT **setp) {
+  int size;
+  void **freelistp;  /* used !qh_NOmem */
+  
+  if (*setp) {
+    size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize; 
+    if (size <= qhmem.LASTsize) {
+      qh_memfree_(*setp, size, freelistp);
+    }else
+      qh_memfree (*setp, size);
+    *setp= NULL;
+  }
+} /* setfree */
+
+
+/*---------------------------------
+  
+  qh_setfree2( setp, elemsize )
+    frees the space occupied by a set and its elements
+
+  notes:
+    set may be NULL
+
+  design:
+    free each element
+    free set 
+*/
+void qh_setfree2 (setT **setp, int elemsize) {
+  void		*elem, **elemp;
+  
+  FOREACHelem_(*setp)
+    qh_memfree (elem, elemsize);
+  qh_setfree (setp);
+} /* setfree2 */
+
+
+      
+/*---------------------------------
+  
+  qh_setfreelong( setp )
+    frees a set only if it's in long memory
+
+  returns:
+    sets setp to NULL if it is freed
+    
+  notes:
+    set may be NULL
+
+  design:
+    if set is large
+      free it    
+*/
+void qh_setfreelong(setT **setp) {
+  int size;
+  
+  if (*setp) {
+    size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize; 
+    if (size > qhmem.LASTsize) {
+      qh_memfree (*setp, size);
+      *setp= NULL;
+    }
+  }
+} /* setfreelong */
+
+
+/*---------------------------------
+  
+  qh_setin( set, setelem )
+    returns 1 if setelem is in a set, 0 otherwise
+
+  notes:
+    set may be NULL or unsorted
+
+  design:
+    scans set for setelem
+*/
+int qh_setin(setT *set, void *setelem) {
+  void *elem, **elemp;
+
+  FOREACHelem_(set) {
+    if (elem == setelem)
+      return 1;
+  }
+  return 0;
+} /* setin */
+
+
+/*---------------------------------
+  
+  qh_setindex( set, atelem )
+    returns the index of atelem in set.   
+    returns -1, if not in set or maxsize wrong
+
+  notes:
+    set may be NULL and may contain nulls.
+
+  design:
+    checks maxsize
+    scans set for atelem
+*/
+int qh_setindex(setT *set, void *atelem) {
+  void **elem;
+  int size, i;
+
+  SETreturnsize_(set, size);
+  if (size > set->maxsize)
+    return -1;
+  elem= SETaddr_(set, void);
+  for (i=0; i < size; i++) {
+    if (*elem++ == atelem)
+      return i;
+  }
+  return -1;
+} /* setindex */
+
+
+/*---------------------------------
+  
+  qh_setlarger( oldsetp )
+    returns a larger set that contains all elements of *oldsetp
+
+  notes:
+    the set is at least twice as large
+    if temp set, updates qhmem.tempstack
+
+  design:
+    creates a new set
+    copies the old set to the new set
+    updates pointers in tempstack
+    deletes the old set
+*/
+void qh_setlarger(setT **oldsetp) {
+  int size= 1, *sizep;
+  setT *newset, *set, **setp, *oldset;
+  void **oldp, **newp;
+
+  if (*oldsetp) {
+    oldset= *oldsetp;
+    SETreturnsize_(oldset, size);
+    qhmem.cntlarger++;
+    qhmem.totlarger += size+1;
+    newset= qh_setnew(2 * size);
+    oldp= SETaddr_(oldset, void);
+    newp= SETaddr_(newset, void);
+    memcpy((char *)newp, (char *)oldp, (size+1) * SETelemsize);
+    sizep= SETsizeaddr_(newset);
+    *sizep= size+1;
+    FOREACHset_((setT *)qhmem.tempstack) {
+      if (set == oldset)
+	*(setp-1)= newset;
+    }
+    qh_setfree(oldsetp);
+  }else 
+    newset= qh_setnew(3);
+  *oldsetp= newset;
+} /* setlarger */
+
+
+/*---------------------------------
+  
+  qh_setlast(  )
+    return last element of set or NULL (use type conversion)
+
+  notes:
+    set may be NULL
+
+  design:
+    return last element  
+*/
+void *qh_setlast(setT *set) {
+  int size;
+
+  if (set) {
+    size= *SETsizeaddr_(set);
+    if (!size) 
+      return SETelem_(set, set->maxsize - 1);
+    else if (size > 1)
+      return SETelem_(set, size - 2);
+  }
+  return NULL;
+} /* setlast */
+
+
+/*---------------------------------
+  
+  qh_setnew( setsize )
+    creates and allocates space for a set
+
+  notes:
+    setsize means the number of elements (NOT including the NULL terminator)
+    use qh_settemp/qh_setfreetemp if set is temporary
+
+  design:
+    allocate memory for set
+    roundup memory if small set
+    initialize as empty set
+*/
+setT *qh_setnew(int setsize) {
+  setT *set;
+  int sizereceived; /* used !qh_NOmem */
+  int size;
+  void **freelistp; /* used !qh_NOmem */
+
+  if (!setsize)
+    setsize++;
+  size= sizeof(setT) + setsize * SETelemsize;
+  if ((unsigned) size <= (unsigned) qhmem.LASTsize) {
+    qh_memalloc_(size, freelistp, set, setT);
+#ifndef qh_NOmem
+    sizereceived= qhmem.sizetable[ qhmem.indextable[size]];
+    if (sizereceived > size) 
+      setsize += (sizereceived - size)/SETelemsize;
+#endif
+  }else
+    set= (setT*)qh_memalloc (size);
+  set->maxsize= setsize;
+  set->e[setsize].i= 1;
+  set->e[0].p= NULL;
+  return (set);
+} /* setnew */
+
+
+/*---------------------------------
+  
+  qh_setnew_delnthsorted( set, size, nth, prepend )
+    creates a sorted set not containing nth element
+    if prepend, the first prepend elements are undefined
+
+  notes:
+    set must be defined
+    checks nth
+    see also: setdelnthsorted
+
+  design:
+    create new set
+    setup pointers and allocate room for prepend'ed entries
+    append head of old set to new set
+    append tail of old set to new set
+*/
+setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend) {
+  setT *newset;
+  void **oldp, **newp;
+  int tailsize= size - nth -1, newsize;
+
+  if (tailsize < 0) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint (qhmem.ferr, "", set);
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  newsize= size-1 + prepend;
+  newset= qh_setnew(newsize);
+  newset->e[newset->maxsize].i= newsize+1;  /* may be overwritten */
+  oldp= SETaddr_(set, void);
+  newp= SETaddr_(newset, void) + prepend;
+  switch (nth) {
+  case 0:
+    break;
+  case 1:
+    *(newp++)= *oldp++;
+    break;
+  case 2:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 3:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 4:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  default:
+    memcpy((char *)newp, (char *)oldp, nth * SETelemsize);
+    newp += nth;
+    oldp += nth;
+    break;
+  }
+  oldp++;
+  switch (tailsize) {
+  case 0:
+    break;
+  case 1:
+    *(newp++)= *oldp++;
+    break;
+  case 2:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 3:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 4:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  default:
+    memcpy((char *)newp, (char *)oldp, tailsize * SETelemsize);
+    newp += tailsize;
+  }
+  *newp= NULL;
+  return(newset);
+} /* setnew_delnthsorted */
+
+
+/*---------------------------------
+  
+  qh_setprint( fp, string, set )
+    print set elements to fp with identifying string
+
+  notes:
+    never errors
+*/
+void qh_setprint(FILE *fp, char* string, setT *set) {
+  int size, k;
+
+  if (!set)
+    fprintf (fp, "%s set is null\n", string);
+  else {
+    SETreturnsize_(set, size);
+    fprintf (fp, "%s set=%p maxsize=%d size=%d elems=",
+	     string, set, set->maxsize, size);
+    if (size > set->maxsize)
+      size= set->maxsize+1;
+    for (k=0; k < size; k++)
+      fprintf(fp, " %p", set->e[k].p);
+    fprintf(fp, "\n");
+  }
+} /* setprint */
+
+/*---------------------------------
+  
+  qh_setreplace( set, oldelem, newelem )
+    replaces oldelem in set with newelem
+
+  notes:
+    errors if oldelem not in the set
+    newelem may be NULL, but it turns the set into an indexed set (no FOREACH)
+
+  design:
+    find oldelem
+    replace with newelem
+*/
+void qh_setreplace(setT *set, void *oldelem, void *newelem) {
+  void **elemp;
+  
+  elemp= SETaddr_(set, void);
+  while(*elemp != oldelem && *elemp)
+    elemp++;
+  if (*elemp)
+    *elemp= newelem;
+  else {
+    fprintf (qhmem.ferr, "qhull internal error (qh_setreplace): elem %p not found in set\n",
+       oldelem);
+    qh_setprint (qhmem.ferr, "", set);
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+} /* setreplace */
+
+
+/*---------------------------------
+  
+  qh_setsize( set )
+    returns the size of a set
+
+  notes:
+    errors if set's maxsize is incorrect
+    same as SETreturnsize_(set)
+
+  design:
+    determine actual size of set from maxsize
+*/
+int qh_setsize(setT *set) {
+  int size, *sizep;
+  
+  if (!set)
+    return (0);
+  sizep= SETsizeaddr_(set);
+  if ((size= *sizep)) {
+    size--;
+    if (size > set->maxsize) {
+      fprintf (qhmem.ferr, "qhull internal error (qh_setsize): current set size %d is greater than maximum size %d\n",
+	       size, set->maxsize);
+      qh_setprint (qhmem.ferr, "set: ", set);
+      qh_errexit (qhmem_ERRqhull, NULL, NULL);
+    }
+  }else
+    size= set->maxsize;
+  return size;
+} /* setsize */
+
+/*---------------------------------
+  
+  qh_settemp( setsize )
+    return a stacked, temporary set of upto setsize elements
+
+  notes:
+    use settempfree or settempfree_all to release from qhmem.tempstack
+    see also qh_setnew
+
+  design:
+    allocate set
+    append to qhmem.tempstack
+    
+*/
+setT *qh_settemp(int setsize) {
+  setT *newset;
+  
+  newset= qh_setnew (setsize);
+  qh_setappend ((setT **)&qhmem.tempstack, newset);
+  if (qhmem.IStracing >= 5)
+    fprintf (qhmem.ferr, "qh_settemp: temp set %p of %d elements, depth %d\n",
+       newset, newset->maxsize, qh_setsize ((setT*)qhmem.tempstack));
+  return newset;
+} /* settemp */
+
+/*---------------------------------
+  
+  qh_settempfree( set )
+    free temporary set at top of qhmem.tempstack
+
+  notes:
+    nop if set is NULL
+    errors if set not from previous   qh_settemp
+  
+  to locate errors:
+    use 'T2' to find source and then find mis-matching qh_settemp
+
+  design:
+    check top of qhmem.tempstack
+    free it
+*/
+void qh_settempfree(setT **set) {
+  setT *stackedset;
+
+  if (!*set)
+    return;
+  stackedset= qh_settemppop ();
+  if (stackedset != *set) {
+    qh_settemppush(stackedset);
+    fprintf (qhmem.ferr, "qhull internal error (qh_settempfree): set %p (size %d) was not last temporary allocated (depth %d, set %p, size %d)\n",
+	     *set, qh_setsize(*set), qh_setsize((setT*)qhmem.tempstack)+1,
+	     stackedset, qh_setsize(stackedset));
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  qh_setfree (set);
+} /* settempfree */
+
+/*---------------------------------
+  
+  qh_settempfree_all(  )
+    free all temporary sets in qhmem.tempstack
+
+  design:
+    for each set in tempstack
+      free set
+    free qhmem.tempstack
+*/
+void qh_settempfree_all(void) {
+  setT *set, **setp;
+
+  FOREACHset_((setT *)qhmem.tempstack) 
+    qh_setfree(&set);
+  qh_setfree((setT **)&qhmem.tempstack);
+} /* settempfree_all */
+
+/*---------------------------------
+  
+  qh_settemppop(  )
+    pop and return temporary set from qhmem.tempstack 
+
+  notes:
+    the returned set is permanent
+    
+  design:
+    pop and check top of qhmem.tempstack
+*/
+setT *qh_settemppop(void) {
+  setT *stackedset;
+  
+  stackedset= (setT*)qh_setdellast((setT *)qhmem.tempstack);
+  if (!stackedset) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_settemppop): pop from empty temporary stack\n");
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  if (qhmem.IStracing >= 5)
+    fprintf (qhmem.ferr, "qh_settemppop: depth %d temp set %p of %d elements\n",
+       qh_setsize((setT*)qhmem.tempstack)+1, stackedset, qh_setsize(stackedset));
+  return stackedset;
+} /* settemppop */
+
+/*---------------------------------
+  
+  qh_settemppush( set )
+    push temporary set unto qhmem.tempstack (makes it temporary)
+
+  notes:
+    duplicates settemp() for tracing
+
+  design:
+    append set to tempstack  
+*/
+void qh_settemppush(setT *set) {
+  
+  qh_setappend ((setT**)&qhmem.tempstack, set);
+  if (qhmem.IStracing >= 5)
+    fprintf (qhmem.ferr, "qh_settemppush: depth %d temp set %p of %d elements\n",
+    qh_setsize((setT*)qhmem.tempstack), set, qh_setsize(set));
+} /* settemppush */
+
+ 
+/*---------------------------------
+  
+  qh_settruncate( set, size )
+    truncate set to size elements
+
+  notes:
+    set must be defined
+  
+  see:
+    SETtruncate_
+
+  design:
+    check size
+    update actual size of set
+*/
+void qh_settruncate (setT *set, int size) {
+
+  if (size < 0 || size > set->maxsize) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_settruncate): size %d out of bounds for set:\n", size);
+    qh_setprint (qhmem.ferr, "", set);
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  set->e[set->maxsize].i= size+1;   /* maybe overwritten */
+  set->e[size].p= NULL;
+} /* settruncate */
+    
+/*---------------------------------
+  
+  qh_setunique( set, elem )
+    add elem to unsorted set unless it is already in set
+
+  notes:
+    returns 1 if it is appended
+
+  design:
+    if elem not in set
+      append elem to set
+*/
+int qh_setunique (setT **set, void *elem) {
+
+  if (!qh_setin (*set, elem)) {
+    qh_setappend (set, elem);
+    return 1;
+  }
+  return 0;
+} /* setunique */
+    
+/*---------------------------------
+  
+  qh_setzero( set, index, size )
+    zero elements from index on
+    set actual size of set to size
+
+  notes:
+    set must be defined
+    the set becomes an indexed set (can not use FOREACH...)
+  
+  see also:
+    qh_settruncate
+    
+  design:
+    check index and size
+    update actual size
+    zero elements starting at e[index]   
+*/
+void qh_setzero (setT *set, int index, int size) {
+  int count;
+
+  if (index < 0 || index >= size || size > set->maxsize) {
+    fprintf (qhmem.ferr, "qhull internal error (qh_setzero): index %d or size %d out of bounds for set:\n", index, size);
+    qh_setprint (qhmem.ferr, "", set);
+    qh_errexit (qhmem_ERRqhull, NULL, NULL);
+  }
+  set->e[set->maxsize].i=  size+1;  /* may be overwritten */
+  count= size - index + 1;   /* +1 for NULL terminator */
+  memset ((char *)SETelemaddr_(set, index, void), 0, count * SETelemsize);
+} /* setzero */
+
+    

Added: trunk/scipy/spatial/qhull/src/qset.h
===================================================================
--- trunk/scipy/spatial/qhull/src/qset.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qset.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,468 @@
+/*
  ---------------------------------
+
+   qset.h
+     header file for qset.c that implements set
+
+   see qh-set.htm and qset.c
+   
+   only uses mem.c, malloc/free
+
+   for error handling, writes message and calls
+      qh_errexit (qhmem_ERRqhull, NULL, NULL);
+   
+   set operations satisfy the following properties:
+    - sets have a max size, the actual size (if different) is stored at the end
+    - every set is NULL terminated
+    - sets may be sorted or unsorted, the caller must distinguish this
+   
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#ifndef qhDEFset
+#define qhDEFset 1
+
+/*================= -structures- ===============*/
+
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;   /* a set is a sorted or unsorted array of pointers */
+#endif
+
+/*------------------------------------------
+   
+setT
+  a set or list of pointers with maximum size and actual size.
+
+variations:
+  unsorted, unique   -- a list of unique pointers with NULL terminator
+  			   user guarantees uniqueness
+  sorted	     -- a sorted list of unique pointers with NULL terminator
+  			   qset.c guarantees uniqueness
+  unsorted           -- a list of pointers terminated with NULL
+  indexed  	     -- an array of pointers with NULL elements 
+
+structure for set of n elements:
+
+	--------------
+	|  maxsize 
+	--------------
+	|  e[0] - a pointer, may be NULL for indexed sets
+	--------------
+	|  e[1]
+	
+	--------------
+	|  ...
+	--------------
+	|  e[n-1]
+	--------------
+	|  e[n] = NULL
+	--------------
+	|  ...
+	--------------
+	|  e[maxsize] - n+1 or NULL (determines actual size of set)
+	--------------
+
+*/
+
+/*-- setelemT -- internal type to allow both pointers and indices
+*/
+typedef union setelemT setelemT;
+union setelemT {
+  void    *p;
+  int      i;         /* integer used for e[maxSize] */
+};
+
+struct setT {
+  int maxsize;          /* maximum number of elements (except NULL) */
+  setelemT e[1];        /* array of pointers, tail is NULL */
+                        /* last slot (unless NULL) is actual size+1 
+                           e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
+                        /* this may generate a warning since e[] contains
+			   maxsize elements */
+};
+
+/*=========== -constants- =========================*/
+
+/*-------------------------------------
+   
+  SETelemsize
+    size of a set element in bytes
+*/
+#define SETelemsize sizeof(setelemT) 
+
+
+/*=========== -macros- =========================*/
+
+/*-------------------------------------
+   
+   FOREACHsetelement_(type, set, variable)
+     define FOREACH iterator
+
+   declare:  
+     assumes *variable and **variablep are declared
+     no space in "variable)" [DEC Alpha cc compiler]
+
+   each iteration:
+     variable is set element
+     variablep is one beyond variable.  
+
+   to repeat an element:
+     variablep--; / *repeat* /
+
+   at exit:
+     variable is NULL at end of loop
+
+   example:  
+     #define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet )
+
+   notes:
+     use FOREACHsetelement_i_() if need index or include NULLs
+
+   WARNING: 
+     nested loops can't use the same variable (define another FOREACH)
+   
+     needs braces if nested inside another FOREACH
+     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_(type, set, variable) \
+        if (((variable= NULL), set)) for(\
+          variable##p= (type **)&((set)->e[0].p); \
+	  (variable= *variable##p++);)
+
+/*------------------------------------------
+
+   FOREACHsetelement_i_(type, set, variable)
+     define indexed FOREACH iterator
+
+   declare:  
+     type *variable, variable_n, variable_i;
+
+   each iteration:
+     variable is set element, may be NULL
+     variable_i is index, variable_n is qh_setsize()
+
+   to repeat an element:
+     variable_i--; variable_n-- repeats for deleted element
+
+   at exit:
+     variable==NULL and variable_i==variable_n
+
+   example:
+     #define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet )
+   
+   WARNING: 
+     nested loops can't use the same variable (define another FOREACH)
+   
+     needs braces if nested inside another FOREACH
+     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_i_(type, set, variable) \
+        if (((variable= NULL), set)) for (\
+          variable##_i= 0, variable= (type *)((set)->e[0].p), \
+                   variable##_n= qh_setsize(set);\
+          variable##_i < variable##_n;\
+          variable= (type *)((set)->e[++variable##_i].p) )
+
+/*----------------------------------------
+
+   FOREACHsetelementreverse_(type, set, variable)- 
+     define FOREACH iterator in reverse order
+
+   declare:  
+     assumes *variable and **variablep are declared
+     also declare 'int variabletemp'
+
+   each iteration:
+     variable is set element
+
+   to repeat an element:
+     variabletemp++; / *repeat* /
+
+   at exit:
+     variable is NULL
+
+   example:
+     #define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex )
+  
+   notes:
+     use FOREACHsetelementreverse12_() to reverse first two elements
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse_(type, set, variable) \
+        if (((variable= NULL), set)) for(\
+	   variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\
+	   variable; variable= \
+	   ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
+
+/*-------------------------------------
+
+   FOREACHsetelementreverse12_(type, set, variable)- 
+     define FOREACH iterator with e[1] and e[0] reversed
+
+   declare:  
+     assumes *variable and **variablep are declared
+
+   each iteration:
+     variable is set element
+     variablep is one after variable.  
+
+   to repeat an element:
+     variablep--; / *repeat* /
+
+   at exit:
+     variable is NULL at end of loop
+  
+   example
+     #define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex )
+
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse12_(type, set, variable) \
+        if (((variable= NULL), set)) for(\
+          variable##p= (type **)&((set)->e[1].p); \
+	  (variable= *variable##p); \
+          variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
+	      (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
+
+/*-------------------------------------
+
+   FOREACHelem_( set )- 
+     iterate elements in a set
+
+   declare:  
+     void *elem, *elemp;
+
+   each iteration:
+     elem is set element
+     elemp is one beyond
+
+   to repeat an element:
+     elemp--; / *repeat* /
+
+   at exit:
+     elem == NULL at end of loop
+  
+   example:
+     FOREACHelem_(set) {
+     
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
+
+/*-------------------------------------
+
+   FOREACHset_( set )- 
+     iterate a set of sets
+
+   declare:  
+     setT *set, **setp;
+
+   each iteration:
+     set is set element
+     setp is one beyond
+
+   to repeat an element:
+     setp--; / *repeat* /
+
+   at exit:
+     set == NULL at end of loop
+  
+   example
+     FOREACHset_(sets) {
+     
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
+
+/*-------------------------------------------
+
+   SETindex_( set, elem )
+     return index of elem in set
+
+   notes:   
+     for use with FOREACH iteration
+
+   example:
+     i= SETindex_(ridges, ridge)
+*/
+#define SETindex_(set, elem) ((void **)elem##p - (void **)&(set)->e[1].p)
+
+/*-----------------------------------------
+
+   SETref_( elem )
+     l.h.s. for modifying the current element in a FOREACH iteration
+
+   example:
+     SETref_(ridge)= anotherridge;
+*/
+#define SETref_(elem) (elem##p[-1])
+
+/*-----------------------------------------
+
+   SETelem_(set, n)
+     return the n'th element of set
+   
+   notes:
+      assumes that n is valid [0..size] and that set is defined
+      use SETelemt_() for type cast
+*/
+#define SETelem_(set, n)           ((set)->e[n].p)
+
+/*-----------------------------------------
+
+   SETelemt_(set, n, type)
+     return the n'th element of set as a type
+   
+   notes:
+      assumes that n is valid [0..size] and that set is defined
+*/
+#define SETelemt_(set, n, type)    ((type*)((set)->e[n].p))
+
+/*-----------------------------------------
+
+   SETelemaddr_(set, n, type)
+     return address of the n'th element of a set
+   
+   notes:
+      assumes that n is valid [0..size] and set is defined 
+*/
+#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
+
+/*-----------------------------------------
+
+   SETfirst_(set)
+     return first element of set
+   
+*/
+#define SETfirst_(set)             ((set)->e[0].p)
+
+/*-----------------------------------------
+
+   SETfirstt_(set, type)
+     return first element of set as a type
+   
+*/
+#define SETfirstt_(set, type)      ((type*)((set)->e[0].p))
+
+/*-----------------------------------------
+
+   SETsecond_(set)
+     return second element of set
+   
+*/
+#define SETsecond_(set)            ((set)->e[1].p)
+
+/*-----------------------------------------
+
+   SETsecondt_(set, type)
+     return second element of set as a type
+*/
+#define SETsecondt_(set, type)     ((type*)((set)->e[1].p))
+
+/*-----------------------------------------
+
+   SETaddr_(set, type)
+       return address of set's elements
+*/
+#define SETaddr_(set,type)	   ((type **)(&((set)->e[0].p)))
+
+/*-----------------------------------------
+
+   SETreturnsize_(set, size) 
+     return size of a set
+   
+   notes:
+      set must be defined
+      use qh_setsize(set) unless speed is critical
+*/
+#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
+
+/*-----------------------------------------
+
+   SETempty_(set) 
+     return true (1) if set is empty
+   
+   notes:
+      set may be NULL
+*/
+#define SETempty_(set) 	          (!set || (SETfirst_(set) ? 0:1))
+
+/*-----------------------------------------
+
+   SETtruncate_(set)
+     return first element of set
+
+   see:
+     qh_settruncate()
+   
+*/
+#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
+      set->e[size].p= NULL;}
+
+/*======= prototypes in alphabetical order ============*/
+
+void  qh_setaddsorted(setT **setp, void *elem);
+void  qh_setaddnth(setT **setp, int nth, void *newelem);
+void  qh_setappend(setT **setp, void *elem);
+void  qh_setappend_set(setT **setp, setT *setA);
+void  qh_setappend2ndlast(setT **setp, void *elem);
+void  qh_setcheck(setT *set, char *tname, int id);
+void  qh_setcompact(setT *set);
+setT *qh_setcopy(setT *set, int extra);
+void *qh_setdel(setT *set, void *elem);
+void *qh_setdellast(setT *set);
+void *qh_setdelnth(setT *set, int nth);
+void *qh_setdelnthsorted(setT *set, int nth);
+void *qh_setdelsorted(setT *set, void *newelem);
+setT *qh_setduplicate( setT *set, int elemsize);
+int   qh_setequal(setT *setA, setT *setB);
+int   qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB);
+int   qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB);
+void  qh_setfree(setT **set);
+void  qh_setfree2( setT **setp, int elemsize);
+void  qh_setfreelong(setT **set);
+int   qh_setin(setT *set, void *setelem);
+int   qh_setindex(setT *set, void *setelem);
+void  qh_setlarger(setT **setp);
+void *qh_setlast(setT *set);
+setT *qh_setnew(int size);
+setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend);
+void  qh_setprint(FILE *fp, char* string, setT *set);
+void  qh_setreplace(setT *set, void *oldelem, void *newelem);
+int   qh_setsize(setT *set);
+setT *qh_settemp(int setsize);
+void  qh_settempfree(setT **set);
+void  qh_settempfree_all(void);
+setT *qh_settemppop(void);
+void  qh_settemppush(setT *set);
+void  qh_settruncate (setT *set, int size);
+int   qh_setunique (setT **set, void *elem);
+void  qh_setzero (setT *set, int index, int size);
+
+
+#endif /* qhDEFset */

Added: trunk/scipy/spatial/qhull/src/qvoronoi.c
===================================================================
--- trunk/scipy/spatial/qhull/src/qvoronoi.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/qvoronoi.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,318 @@
+/*
  ---------------------------------
+
+   qvoronoi.c
+     compute Voronoi diagrams and furthest-point Voronoi
+     diagrams using qhull
+
+   see unix.c for full interface
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include 
+#include 
+#include 
+#include 
+
+#elif __cplusplus
+extern "C" {
+  int isatty (int);
+}
+
+#elif _MSC_VER
+#include 
+#define isatty _isatty
+
+#else
+int isatty (int);  /* returns 1 if stdin is a tty
+		   if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*---------------------------------
+
+  qh_prompt 
+    long prompt for qhull
+    
+  notes:
+    restricted version of qhull.c
+ 
+  see:
+    concise prompt below
+*/  
+
+/* duplicated in qvoron_f.htm and qvoronoi.htm */
+char hidden_options[]=" d n m v H U Qb QB Qc Qf Qg Qi Qm Qr QR Qv Qx TR E V Fa FA FC Fp FS Ft FV Pv Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
+
+char qh_prompta[]= "\n\
+qvoronoi- compute the Voronoi diagram\n\
+    http://www.qhull.org  %s\n\
+\n\
+input (stdin):\n\
+    first lines: dimension and number of points (or vice-versa).\n\
+    other lines: point coordinates, best if one point per line\n\
+    comments:    start with a non-numeric character\n\
+\n\
+options:\n\
+    Qu   - compute furthest-site Voronoi diagram\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+\n\
+Qhull control options:\n\
+    Qz   - add point-at-infinity to Voronoi diagram\n\
+    QJn  - randomly joggle input in range [-n,n]\n\
+%s%s%s%s";  /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+    Qs   - search all points for the initial simplex\n\
+    QGn  - Voronoi vertices if visible from point n, -n if not\n\
+    QVn  - Voronoi vertices for input point n, -n if not\n\
+\n\
+";
+char qh_promptc[]= "\
+Trace options:\n\
+    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+    Tc   - check frequently during execution\n\
+    Ts   - statistics\n\
+    Tv   - verify result: structure, convexity, and in-circle test\n\
+    Tz   - send all output to stdout\n\
+    TFn  - report summary when n or more facets created\n\
+    TI file - input data from file, no spaces or single quotes\n\
+    TO file - output results to file, may be enclosed in single quotes\n\
+    TPn  - turn on tracing when point n added to hull\n\
+     TMn - turn on tracing at merge n\n\
+     TWn - trace merge facets when width > n\n\
+    TVn  - stop qhull after adding point n, -n for before (see TCn)\n\
+     TCn - stop qhull after building cone for point n (see TVn)\n\
+\n\
+Precision options:\n\
+    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
+     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
+           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
+    Wn   - min facet width for non-coincident point (before roundoff)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+    s    - summary to stderr\n\
+    p    - Voronoi vertices\n\
+    o    - OFF format (dim, Voronoi vertices, and Voronoi regions)\n\
+    i    - Delaunay regions (use 'Pp' to avoid warning)\n\
+    f    - facet dump\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+    Fc   - count plus coincident points (by Voronoi vertex)\n\
+    Fd   - use cdd format for input (homogeneous with offset first)\n\
+    FD   - use cdd format for output (offset first)\n\
+    FF   - facet dump without ridges\n\
+    Fi   - separating hyperplanes for bounded Voronoi regions\n\
+    FI   - ID for each Voronoi vertex\n\
+    Fm   - merge count for each Voronoi vertex (511 max)\n\
+    Fn   - count plus neighboring Voronoi vertices for each Voronoi vertex\n\
+    FN   - count and Voronoi vertices for each Voronoi region\n\
+    Fo   - separating hyperplanes for unbounded Voronoi regions\n\
+    FO   - options and precision constants\n\
+    FP   - nearest point and distance for each coincident point\n\
+    FQ   - command used for qvoronoi\n\
+    Fs   - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
+                    for output: #Voronoi regions, #Voronoi vertices,\n\
+                                #coincident points, #non-simplicial regions\n\
+                    #real (2), max outer plane and min vertex\n\
+    Fv   - Voronoi diagram as Voronoi vertices between adjacent input sites\n\
+    Fx   - extreme points of Delaunay triangulation (on convex hull)\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview options (2-d only)\n\
+    Ga   - all points as dots\n\
+     Gp  -  coplanar points and vertices as radii\n\
+     Gv  -  vertices as spheres\n\
+    Gi   - inner planes only\n\
+     Gn  -  no planes\n\
+     Go  -  outer planes only\n\
+    Gc	 - centrums\n\
+    Gh   - hyperplane intersections\n\
+    Gr   - ridges\n\
+    GDn  - drop dimension n in 3-d and 4-d output\n\
+\n\
+Print options:\n\
+    PAn  - keep n largest Voronoi vertices by 'area'\n\
+    Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
+    PDk:n - drop facet if normal[k] >= n\n\
+    Pg   - print good Voronoi vertices (needs 'QGn' or 'QVn')\n\
+    PFn  - keep Voronoi vertices whose 'area' is at least n\n\
+    PG   - print neighbors of good Voronoi vertices\n\
+    PMn  - keep n Voronoi vertices with most merges\n\
+    Po   - force output.  If error, output neighborhood of facet\n\
+    Pp   - do not report precision problems\n\
+\n\
+    .    - list of all options\n\
+    -    - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt2
+    synopsis for qhull 
+*/  
+char qh_prompt2[]= "\n\
+qvoronoi- compute the Voronoi diagram.  Qhull %s\n\
+    input (stdin): dimension, number of points, point coordinates\n\
+    comments start with a non-numeric character\n\
+\n\
+options (qvoronoi.htm):\n\
+    Qu   - compute furthest-site Voronoi diagram\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+    Tv   - verify result: structure, convexity, and in-circle test\n\
+    .    - concise list of all options\n\
+    -    - one-line description of all options\n\
+\n\
+output options (subset):\n\
+    s    - summary of results (default)\n\
+    p    - Voronoi vertices\n\
+    o    - OFF file format (dim, Voronoi vertices, and Voronoi regions)\n\
+    FN   - count and Voronoi vertices for each Voronoi region\n\
+    Fv   - Voronoi diagram as Voronoi vertices between adjacent input sites\n\
+    Fi   - separating hyperplanes for bounded regions, 'Fo' for unbounded\n\
+    G    - Geomview output (2-d only)\n\
+    QVn  - Voronoi vertices for input point n, -n if not\n\
+    TO file- output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+rbox c P0 D2 | qvoronoi s o         rbox c P0 D2 | qvoronoi Fi\n\
+rbox c P0 D2 | qvoronoi Fo          rbox c P0 D2 | qvoronoi Fv\n\
+rbox c P0 D2 | qvoronoi s Qu Fv     rbox c P0 D2 | qvoronoi Qu Fo\n\
+rbox c G1 d D2 | qvoronoi s p       rbox c G1 d D2 | qvoronoi QJ s p\n\
+rbox c P0 D2 | qvoronoi s Fv QV0\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt3
+    concise prompt for qhull 
+*/  
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper-case options take an argument.\n\
+\n\
+ OFF_format     p_vertices     i_delaunay     summary        facet_dump\n\
+\n\
+ Fcoincident    Fd_cdd_in      FD_cdd_out     FF-dump-xridge Fi_bounded\n\
+ Fxtremes       Fmerges        Fneighbors     FNeigh_region  FOptions\n\
+ Fo_unbounded   FPoint_near    FQvoronoi      Fsummary       Fvoronoi\n\
+ FIDs\n\
+\n\
+ Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
+ Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
+\n\
+ PArea_keep     Pdrop d0:0D0   Pgood          PFacet_area_keep\n\
+ PGood_neighbors PMerge_keep   Poutput_forced Pprecision_not\n\
+\n\
+ QG_vertex_good QJoggle        Qsearch_1st    Qtriangulate   Qupper_voronoi\n\
+ QV_point_good  Qzinfinite\n\
+\n\
+ T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
+ TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
+ TWide_trace    TVertex_stop   TCone_stop\n\
+\n\
+ Angle_max      Centrum_size   Random_dist    Wide_outside\n\
+";
+
+/*---------------------------------
+  
+  main( argc, argv )
+    processes the command line, calls qhull() to do the work, and exits
+  
+  design:
+    initializes data structures
+    reads points
+    finishes initialization
+    computes convex hull and other structures
+    checks the result
+    writes the output
+    frees memory
+*/
+int main(int argc, char *argv[]) {
+  int curlong, totlong; /* used !qh_NOmem */
+  int exitcode, numpoints, dim;
+  coordT *points;
+  boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+  SIOUXSettings.showstatusline= false;
+  SIOUXSettings.tabspaces= 1;
+  SIOUXSettings.rows= 40;
+  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
+  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
+    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+  argc= ccommand(&argv);
+#endif
+
+  if ((argc == 1) && isatty( 0 /*stdin*/)) {      
+    fprintf(stdout, qh_prompt2, qh_version);
+    exit(qh_ERRnone);
+  }
+  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompta, qh_version,
+		qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+    exit(qh_ERRnone);
+  }
+  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompt3, qh_version);
+    exit(qh_ERRnone);
+  }
+  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
+  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+  if (!exitcode) {
+    qh_option ("voronoi  _bbound-last  _coplanar-keep", NULL, NULL);
+    qh DELAUNAY= True;     /* 'v'   */
+    qh VORONOI= True; 
+    qh SCALElast= True;    /* 'Qbb' */
+    qh_checkflags (qh qhull_command, hidden_options);
+    qh_initflags (qh qhull_command);
+    points= qh_readpoints (&numpoints, &dim, &ismalloc);
+    if (dim >= 5) {
+      qh_option ("_merge-exact", NULL, NULL);
+      qh MERGEexact= True; /* 'Qx' always */
+    }
+    qh_init_B (points, numpoints, dim, ismalloc);
+    qh_qhull();
+    qh_check_output();
+    qh_produce_output();
+    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points();
+    exitcode= qh_ERRnone;
+  }
+  qh NOerrexit= True;  /* no more setjmp */
+#ifdef qh_NOmem
+  qh_freeqhull( True);
+#else
+  qh_freeqhull( False);
+  qh_memfreeshort (&curlong, &totlong);
+  if (curlong || totlong) 
+    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+       totlong, curlong);
+#endif
+  return exitcode;
+} /* main */
+

Added: trunk/scipy/spatial/qhull/src/rbox.c
===================================================================
--- trunk/scipy/spatial/qhull/src/rbox.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/rbox.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,788 @@
+/*
  ---------------------------------
+
+   rbox.c
+     Generate input points for qhull.
+   
+   notes:
+     50 points generated for 'rbox D4'
+
+     This code needs a full rewrite.  It needs separate procedures for each 
+     distribution with common, helper procedures.
+   
+   WARNING: 
+     incorrect range if qh_RANDOMmax is defined wrong (user.h)
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "user.h"
+#if __MWERKS__ && __POWERPC__
+#include 
+#include 
+#include 
+#include 
+#endif
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ */
+#pragma warning( disable : 4244)  /* conversion from double to int */
+#endif
+
+#define MINVALUE 0.8
+#define MAXdim 200
+#define PI 3.1415926535897932384
+#define DEFAULTzbox 1e6
+
+char prompt[]= "\n\
+-rbox- generate various point distributions.  Default is random in cube.\n\
+\n\
+args (any order, space separated):                    Version: 2001/06/24\n\
+  3000    number of random points in cube, lens, spiral, sphere or grid\n\
+  D3      dimension 3-d\n\
+  c       add a unit cube to the output ('c G2.0' sets size)\n\
+  d       add a unit diamond to the output ('d G2.0' sets size)\n\
+  l       generate a regular 3-d spiral\n\
+  r       generate a regular polygon, ('r s Z1 G0.1' makes a cone)\n\
+  s       generate cospherical points\n\
+  x       generate random points in simplex, may use 'r' or 'Wn'\n\
+  y       same as 'x', plus simplex\n\
+  Pn,m,r  add point [n,m,r] first, pads with 0\n\
+\n\
+  Ln      lens distribution of radius n.  Also 's', 'r', 'G', 'W'.\n\
+  Mn,m,r  lattice (Mesh) rotated by [n,-m,0], [m,n,0], [0,0,r], ...\n\
+          '27 M1,0,1' is {0,1,2} x {0,1,2} x {0,1,2}.  Try 'M3,4 z'.\n\
+  W0.1    random distribution within 0.1 of the cube's or sphere's surface\n\
+  Z0.5 s  random points in a 0.5 disk projected to a sphere\n\
+  Z0.5 s G0.6 same as Z0.5 within a 0.6 gap\n\
+\n\
+  Bn      bounding box coordinates, default %2.2g\n\
+  h       output as homogeneous coordinates for cdd\n\
+  n       remove command line from the first line of output\n\
+  On      offset coordinates by n\n\
+  t       use time as the random number seed (default is command line)\n\
+  tn      use n as the random number seed\n\
+  z       print integer coordinates, default 'Bn' is %2.2g\n\
+";
+
+/* ------------------------------ prototypes ----------------*/
+int roundi( double a);
+void out1( double a);
+void out2n( double a, double b);
+void out3n( double a, double b, double c);
+int     qh_rand( void);
+void    qh_srand( int seed);
+
+
+/* ------------------------------ globals -------------------*/
+
+    FILE *fp;
+    int isinteger= 0;
+    double out_offset= 0.0;
+
+
+/*--------------------------------------------
+-rbox-  main procedure of rbox application
+*/
+int main(int argc, char **argv) {
+    int i,j,k;
+    int gendim;
+    int cubesize, diamondsize, seed=0, count, apex;
+    int dim=3 , numpoints= 0, totpoints, addpoints=0;
+    int issphere=0, isaxis=0,  iscdd= 0, islens= 0, isregular=0, iswidth=0, addcube=0;
+    int isgap=0, isspiral=0, NOcommand= 0, adddiamond=0, istime=0;
+    int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
+    double width=0.0, gap=0.0, radius= 0.0;
+    double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
+    double *simplex, *simplexp;
+    int nthroot, mult[MAXdim];
+    double norm, factor, randr, rangap, lensangle= 0, lensbase= 1;
+    double anglediff, angle, x, y, cube= 0.0, diamond= 0.0;
+    double box= qh_DEFAULTbox; /* scale all numbers before output */
+    double randmax= qh_RANDOMmax;
+    char command[200], *s, seedbuf[200];    
+    time_t timedata;
+
+#if __MWERKS__ && __POWERPC__
+    char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+    SIOUXSettings.showstatusline= False;
+    SIOUXSettings.tabspaces= 1;
+    SIOUXSettings.rows= 40;
+    if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
+    || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+    || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
+      	fprintf ( stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+    argc= ccommand(&argv);
+#endif
+    if (argc == 1) {
+ 	printf (prompt, box, DEFAULTzbox);
+    	exit(1);
+    }
+    if ((s = strrchr( argv[0], '\\'))) /* Borland gives full path */
+      strcpy (command, s+1);
+    else
+      strcpy (command, argv[0]);
+    if ((s= strstr (command, ".EXE"))
+    ||  (s= strstr (command, ".exe")))
+      *s= '\0';
+    /* ============= read flags =============== */
+    for (i=1; i < argc; i++) {
+  	if (strlen (command) + strlen(argv[i]) + 1 < sizeof(command) ) {
+	    strcat (command, " ");
+	    strcat (command, argv[i]);
+	}
+        if (isdigit (argv[i][0])) {
+      	    numpoints= atoi (argv[i]);
+      	    continue;
+	}
+	if (argv[i][0] == '-')
+	  (argv[i])++;
+        switch (argv[i][0]) {
+	  case 'c':
+	    addcube= 1;
+	    if (i+1 < argc && argv[i+1][0] == 'G')
+	      cube= (double) atof (&argv[++i][1]);
+	    break;
+	  case 'd':
+	    adddiamond= 1;
+	    if (i+1 < argc && argv[i+1][0] == 'G')
+	      diamond= (double) atof (&argv[++i][1]);
+	    break;
+	  case 'h':
+	    iscdd= 1;
+            break;
+	  case 'l':
+	    isspiral= 1;
+            break;
+	  case 'n':
+	    NOcommand= 1;
+	    break;
+	  case 'r':
+	    isregular= 1;
+	    break;
+	  case 's':
+	    issphere= 1;
+            break;
+	  case 't':
+	    istime= 1;
+	    if (isdigit (argv[i][1]))
+	      seed= atoi (&argv[i][1]);
+	    else {
+	      seed= time (&timedata);
+	      sprintf (seedbuf, "%d", seed);
+	      strcat (command, seedbuf);
+	    }
+            break;
+	  case 'x':
+	    issimplex= 1;
+	    break;
+	  case 'y':
+	    issimplex2= 1;
+	    break;
+	  case 'z':
+	    isinteger= 1;
+	    break;
+	  case 'B':
+	    box= (double) atof (&argv[i][1]);
+	    isbox= 1;
+	    break;
+	  case 'D':
+	    dim= atoi (&argv[i][1]);
+	    if (dim < 1
+	    || dim > MAXdim) {
+		fprintf (stderr, "rbox error: dim %d too large or too small\n", dim);
+		exit (1);
+	    }
+            break;
+	  case 'G':
+	    if (argv[i][1])
+	      gap= (double) atof (&argv[i][1]);
+	    else
+	      gap= 0.5;
+	    isgap= 1;
+	    break;
+	  case 'L':
+	    if (argv[i][1])
+	      radius= (double) atof (&argv[i][1]);
+	    else
+	      radius= 10;
+	    islens= 1;
+	    break;
+	  case 'M':
+	    ismesh= 1;
+    	    s= argv[i]+1;
+	    if (*s)
+	      meshn= strtod (s, &s);
+	    if (*s == ',')
+	      meshm= strtod (++s, &s);
+	    else
+	      meshm= 0.0;
+	    if (*s == ',')
+	      meshr= strtod (++s, &s);
+	    else
+	      meshr= sqrt (meshn*meshn + meshm*meshm);
+	    if (*s) {
+	      fprintf (stderr, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
+	      meshn= 3.0, meshm=4.0, meshr=5.0;
+	    }
+	    break;
+	  case 'O':
+	    out_offset= (double) atof (&argv[i][1]);
+	    break;
+	  case 'P':
+	    addpoints++;
+	    break;
+	  case 'W':
+	    width= (double) atof (&argv[i][1]);
+	    iswidth= 1;
+	    break;
+	  case 'Z':
+	    if (argv[i][1])
+	      radius= (double) atof (&argv[i][1]);
+	    else
+	      radius= 1.0;
+	    isaxis= 1;
+	    break;
+	  default:
+            fprintf (stderr, "rbox warning: unknown flag %s.\nExecute 'rbox' without arguments for documentation.\n", argv[i]);
+	}
+    }
+    /* ============= defaults, constants, and sizes =============== */
+    if (isinteger && !isbox)
+      box= DEFAULTzbox;
+    if (addcube) {
+      cubesize= floor(ldexp(1.0,dim)+0.5);
+      if (cube == 0.0)
+        cube= box;
+    }else
+      cubesize= 0;
+    if (adddiamond) {
+      diamondsize= 2*dim;
+      if (diamond == 0.0)
+        diamond= box;
+    }else
+      diamondsize= 0;
+    if (islens) {
+      if (isaxis) {
+  	fprintf (stderr, "rbox error: can not combine 'Ln' with 'Zn'\n");
+  	exit(1);
+      }
+      if (radius <= 1.0) {
+  	fprintf (stderr, "rbox error: lens radius %.2g should be greater than 1.0\n",
+  	       radius);
+  	exit(1);
+      }
+      lensangle= asin (1.0/radius);
+      lensbase= radius * cos (lensangle);
+    }
+    if (!numpoints) {
+      if (issimplex2)
+	; /* ok */
+      else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
+	fprintf (stderr, "rbox error: missing count\n");
+	exit(1);
+      }else if (adddiamond + addcube + addpoints)
+	; /* ok */
+      else { 
+	numpoints= 50;  /* ./rbox D4 is the test case */
+	issphere= 1;
+      }
+    }
+    if ((issimplex + islens + isspiral + ismesh > 1) 
+    || (issimplex + issphere + isspiral + ismesh > 1)) {
+      fprintf (stderr, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
+      exit(1);
+    }
+    fp= stdout;
+    /* ============= print header with total points =============== */
+    if (issimplex || ismesh)
+      totpoints= numpoints;
+    else if (issimplex2)
+      totpoints= numpoints+dim+1;
+    else if (isregular) {
+      totpoints= numpoints;
+      if (dim == 2) {
+      	if (islens)
+      	  totpoints += numpoints - 2;
+      }else if (dim == 3) {
+      	if (islens)
+      	  totpoints += 2 * numpoints;
+        else if (isgap)
+          totpoints += 1 + numpoints;
+        else
+          totpoints += 2;
+      }
+    }else
+      totpoints= numpoints + isaxis;
+    totpoints += cubesize + diamondsize + addpoints;
+    if (iscdd) 
+      fprintf(fp, "%s\nbegin\n        %d %d %s\n", 
+            NOcommand ? "" : command, 
+            totpoints, dim+1,
+            isinteger ? "integer" : "real");
+    else if (NOcommand)
+      fprintf(fp,  "%d\n%d\n", dim, totpoints);
+    else
+      fprintf(fp,  "%d %s\n%d\n", dim, command, totpoints);
+    /* ============= seed randoms =============== */
+    if (istime == 0) {
+      for (s=command; *s; s++) {
+	if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
+	  i= 'x';
+	else
+	  i= *s;
+	seed= 11*seed + i;
+      }
+    } /* else, seed explicitly set to n or to time */
+    qh_RANDOMseed_(seed);
+    /* ============= explicit points =============== */
+    for (i=1; i < argc; i++) {
+      if (argv[i][0] == 'P') {
+	s= argv[i]+1;
+	count= 0;
+	if (iscdd)
+	  out1( 1.0);
+	while (*s) {
+	  out1( strtod (s, &s));
+	  count++;
+	  if (*s) { 
+	    if (*s++ != ',') {
+	      fprintf (stderr, "rbox error: missing comma after coordinate in %s\n\n", argv[i]);
+	      exit (1);
+	    }
+          }
+	}
+	if (count < dim) {
+	  for (k= dim-count; k--; )
+	    out1( 0.0);
+	}else if (count > dim) {
+	  fprintf (stderr, "rbox error: %d coordinates instead of %d coordinates in %s\n\n", 
+                 count, dim, argv[i]);
+	  exit (1);
+	}
+	fprintf (fp, "\n");
+      }
+    }
+    /* ============= simplex distribution =============== */
+    if (issimplex+issimplex2) {
+      if (!(simplex= malloc( dim * (dim+1) * sizeof(double)))) {
+	fprintf (stderr, "insufficient memory for simplex\n");
+	exit(0);
+      }
+      simplexp= simplex;
+      if (isregular) {
+        for (i= 0; i randmax/2)
+	    coord[dim-1]= -coord[dim-1];
+	/* ============= project 'Wn' point toward boundary =============== */
+	}else if (iswidth && !issphere) {
+	  j= qh_RANDOMint % gendim;
+	  if (coord[j] < 0)
+	    coord[j]= -1.0 - coord[j] * width;
+	  else
+	    coord[j]= 1.0 - coord[j] * width;
+	}
+	/* ============= write point =============== */
+	if (iscdd)
+	  out1( 1.0);
+	for (k=0; k < dim; k++) 
+	  out1( coord[k] * box);
+	fprintf (fp, "\n");
+      }
+    }
+    /* ============= write cube vertices =============== */
+    if (addcube) {
+      for (j=0; j=0; k--) {
+	  if (j & ( 1 << k))
+	    out1( cube);
+	  else
+	    out1( -cube);
+	}
+	fprintf (fp, "\n");
+      }
+    }
+    /* ============= write diamond vertices =============== */
+    if (adddiamond) {
+      for (j=0; j=0; k--) {
+	  if (j/2 != k)
+	    out1( 0.0);
+	  else if (j & 0x1)
+	    out1( diamond);
+	  else
+	    out1( -diamond);
+	}
+	fprintf (fp, "\n");
+      }
+    }
+    if (iscdd)
+      fprintf (fp, "end\nhull\n");
+    return 0;
+  } /* rbox */
+
+/*------------------------------------------------
+-outxxx - output functions
+*/
+int roundi( double a) {
+  if (a < 0.0) {
+    if (a - 0.5 < INT_MIN) {
+      fprintf(stderr, "rbox input error: coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
+      exit (1);
+    }
+    return a - 0.5;
+  }else {
+    if (a + 0.5 > INT_MAX) {
+      fprintf(stderr, "rbox input error: coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
+      exit (1);
+    }
+    return a + 0.5;
+  }
+} /* roundi */
+
+void out1(double a) {
+
+  if (isinteger) 
+    fprintf(fp, "%d ", roundi( a+out_offset));
+  else
+    fprintf(fp, qh_REAL_1, a+out_offset);
+} /* out1 */
+
+void out2n( double a, double b) {
+
+  if (isinteger)
+    fprintf(fp, "%d %d\n", roundi(a+out_offset), roundi(b+out_offset));
+  else
+    fprintf(fp, qh_REAL_2n, a+out_offset, b+out_offset);
+} /* out2n */
+
+void out3n( double a, double b, double c) { 
+
+  if (isinteger)
+    fprintf(fp, "%d %d %d\n", roundi(a+out_offset), roundi(b+out_offset), roundi(c+out_offset));
+  else
+    fprintf(fp, qh_REAL_3n, a+out_offset, b+out_offset, c+out_offset);
+} /* out3n */
+
+/*-------------------------------------------------
+-rand & srand- generate pseudo-random number between 1 and 2^31 -2
+  from Park & Miller's minimimal standard random number generator
+  Communications of the ACM, 31:1192-1201, 1988.
+notes:
+  does not use 0 or 2^31 -1
+  this is silently enforced by qh_srand()
+  copied from geom2.c
+*/
+static int seed = 1;  /* global static */
+
+int qh_rand( void) {
+#define qh_rand_a 16807
+#define qh_rand_m 2147483647
+#define qh_rand_q 127773  /* m div a */
+#define qh_rand_r 2836    /* m mod a */
+  int lo, hi, test;
+
+  hi = seed / qh_rand_q;  /* seed div q */
+  lo = seed % qh_rand_q;  /* seed mod q */
+  test = qh_rand_a * lo - qh_rand_r * hi;
+  if (test > 0)
+    seed= test;
+  else
+    seed= test + qh_rand_m;
+  return seed;
+} /* rand */
+
+void qh_srand( int newseed) {
+  if (newseed < 1)
+    seed= 1;
+  else if (newseed >= qh_rand_m)
+    seed= qh_rand_m - 1;
+  else
+    seed= newseed;
+} /* qh_srand */
+

Added: trunk/scipy/spatial/qhull/src/stat.c
===================================================================
--- trunk/scipy/spatial/qhull/src/stat.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/stat.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,702 @@
+/*
  ---------------------------------
+
+   stat.c 
+   contains all statistics that are collected for qhull
+
+   see qh-stat.htm and stat.h
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#include "qhull_a.h"
+
+/*============ global data structure ==========*/
+
+#if qh_QHpointer
+qhstatT *qh_qhstat=NULL;  /* global data structure */
+#else
+qhstatT qh_qhstat;   /* add "={0}" if this causes a compiler error */
+#endif
+
+/*========== functions in alphabetic order ================*/
+
+/*---------------------------------
+  
+  qh_allstatA()
+    define statistics in groups of 20
+
+  notes:
+    (otherwise, 'gcc -O2' uses too much memory)
+    uses qhstat.next
+*/
+void qh_allstatA (void) {
+  
+   /* zdef_(type,name,doc,average) */
+  zzdef_(zdoc, Zdoc2, "precision statistics", -1);
+  zdef_(zinc, Znewvertex, NULL, -1);
+  zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet (not 0s)", Znewvertex);
+  zzdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1);
+  zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1);
+  zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1);
+  zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1);
+
+  qhstat precision= qhstat next;  /* call qh_precision for each of these */
+  zzdef_(zdoc, Zdoc3, "precision problems (corrected unless 'Q0' or an error)", -1);
+  zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1);
+  zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1);
+  zzdef_(zinc, Zflippedfacets, "flipped facets", -1);
+  zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1);
+  zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1);
+  zzdef_(zinc, Zminnorm, "degenerate hyperplanes recomputed with gaussian elimination", -1);
+  zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1);
+  zzdef_(zinc, Zback0, "zero divisors during back substitute", -1);
+  zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1);
+  zzdef_(zinc, Zmultiridge, "ridges with multiple neighbors", -1);
+}
+void qh_allstatB (void) {
+  zzdef_(zdoc, Zdoc1, "summary information", -1);
+  zdef_(zinc, Zvertices, "number of vertices in output", -1);
+  zdef_(zinc, Znumfacets, "number of facets in output", -1);
+  zdef_(zinc, Znonsimplicial, "number of non-simplicial facets in output", -1);
+  zdef_(zinc, Znowsimplicial, "number of simplicial facets that were merged", -1);
+  zdef_(zinc, Znumridges, "number of ridges in output", -1);
+  zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets);
+  zdef_(zmax, Zmaxridges, "maximum number of ridges", -1);
+  zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets);
+  zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1);
+  zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets);
+  zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1);
+  zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices);
+  zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1);
+  zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1);
+  zdef_(zinc, Ztotvertices, "vertices created altogether", -1);
+  zzdef_(zinc, Zsetplane, "facets created altogether", -1);
+  zdef_(zinc, Ztotridges, "ridges created altogether", -1);
+  zdef_(zinc, Zpostfacets, "facets before post merge", -1);
+  zdef_(zadd, Znummergetot, "average merges per facet (at most 511)", Znumfacets);
+  zdef_(zmax, Znummergemax, "  maximum merges for a facet (at most 511)", -1);
+  zdef_(zinc, Zangle, NULL, -1);
+  zdef_(wadd, Wangle, "average angle (cosine) of facet normals for all ridges", Zangle);
+  zdef_(wmax, Wanglemax, "  maximum angle (cosine) of facet normals across a ridge", -1);
+  zdef_(wmin, Wanglemin, "  minimum angle (cosine) of facet normals across a ridge", -1);
+  zdef_(wadd, Wareatot, "total area of facets", -1);
+  zdef_(wmax, Wareamax, "  maximum facet area", -1);
+  zdef_(wmin, Wareamin, "  minimum facet area", -1);
+}  
+void qh_allstatC (void) {
+  zdef_(zdoc, Zdoc9, "build hull statistics", -1);
+  zzdef_(zinc, Zprocessed, "points processed", -1);
+  zzdef_(zinc, Zretry, "retries due to precision problems", -1);
+  zdef_(wmax, Wretrymax, "  max. random joggle", -1);
+  zdef_(zmax, Zmaxvertex, "max. vertices at any one time", -1);
+  zdef_(zinc, Ztotvisible, "ave. visible facets per iteration", Zprocessed);
+  zdef_(zinc, Zinsidevisible, "  ave. visible facets without an horizon neighbor", Zprocessed);
+  zdef_(zadd, Zvisfacettot,  "  ave. facets deleted per iteration", Zprocessed);
+  zdef_(zmax, Zvisfacetmax,  "    maximum", -1);
+  zdef_(zadd, Zvisvertextot, "ave. visible vertices per iteration", Zprocessed);
+  zdef_(zmax, Zvisvertexmax, "    maximum", -1);
+  zdef_(zinc, Ztothorizon, "ave. horizon facets per iteration", Zprocessed);
+  zdef_(zadd, Znewfacettot,  "ave. new or merged facets per iteration", Zprocessed);
+  zdef_(zmax, Znewfacetmax,  "    maximum (includes initial simplex)", -1);
+  zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed);
+  zdef_(wadd, Wnewbalance2, "  standard deviation", -1);
+  zdef_(wadd, Wpbalance, "average partition balance", Zpbalance);
+  zdef_(wadd, Wpbalance2, "  standard deviation", -1);
+  zdef_(zinc, Zpbalance, "  number of trials", -1);
+  zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1);
+  zdef_(zinc, Zdetsimplex, "determinants computed (area & initial hull)", -1);
+  zdef_(zinc, Znoarea, "determinants not computed because vertex too low", -1);
+  zdef_(zinc, Znotmax, "points ignored (not above max_outside)", -1);
+  zdef_(zinc, Znotgood, "points ignored (not above a good facet)", -1);
+  zdef_(zinc, Znotgoodnew, "points ignored (didn't create a good new facet)", -1);
+  zdef_(zinc, Zgoodfacet, "good facets found", -1);
+  zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1);
+  zdef_(zinc, Zdistvertex, "distance tests to report minimum vertex", -1);
+  zdef_(zinc, Ztotcheck, "points checked for facets' outer planes", -1);
+  zzdef_(zinc, Zcheckpart, "  ave. distance tests per check", Ztotcheck);
+}
+void qh_allstatD(void) {
+  zdef_(zdoc, Zdoc4, "partitioning statistics (see previous for outer planes)", -1);
+  zzdef_(zadd, Zdelvertextot, "total vertices deleted", -1);
+  zdef_(zmax, Zdelvertexmax, "    maximum vertices deleted per iteration", -1);
+  zdef_(zinc, Zfindbest, "calls to findbest", -1);
+  zdef_(zadd, Zfindbesttot, " ave. facets tested", Zfindbest);
+  zdef_(zmax, Zfindbestmax, " max. facets tested", -1);
+  zdef_(zadd, Zfindcoplanar, " ave. coplanar search", Zfindbest);
+  zdef_(zinc, Zfindnew, "calls to findbestnew", -1);
+  zdef_(zadd, Zfindnewtot, " ave. facets tested", Zfindnew);
+  zdef_(zmax, Zfindnewmax, " max. facets tested", -1);
+  zdef_(zinc, Zfindnewjump, " ave. clearly better", Zfindnew);
+  zdef_(zinc, Zfindnewsharp, " calls due to qh_sharpnewfacets", -1);
+  zdef_(zinc, Zfindhorizon, "calls to findhorizon", -1);
+  zdef_(zadd, Zfindhorizontot, " ave. facets tested", Zfindhorizon);
+  zdef_(zmax, Zfindhorizonmax, " max. facets tested", -1);
+  zdef_(zinc, Zfindjump,       " ave. clearly better", Zfindhorizon);
+  zdef_(zinc, Zparthorizon, " horizon facets better than bestfacet", -1);
+  zdef_(zinc, Zpartangle, "angle tests for repartitioned coplanar points", -1);
+  zdef_(zinc, Zpartflip, "  repartitioned coplanar points for flipped orientation", -1);
+}
+void qh_allstatE(void) {
+  zdef_(zinc, Zpartinside, "inside points", -1);
+  zdef_(zinc, Zpartnear, "  inside points kept with a facet", -1);
+  zdef_(zinc, Zcoplanarinside, "  inside points that were coplanar with a facet", -1);
+  zdef_(zinc, Zbestlower, "calls to findbestlower", -1);
+  zdef_(zinc, Zbestlowerv, "  with search of vertex neighbors", -1);
+  zdef_(wadd, Wmaxout, "difference in max_outside at final check", -1);
+  zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1);
+  zdef_(zinc, Ztotpartition, "partitions of a point", -1);
+  zzdef_(zinc, Zpartition, "distance tests for partitioning", -1);
+  zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1); 
+  zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1); 
+  zdef_(zinc, Zdistgood, "distance tests for checking good point", -1); 
+  zdef_(zinc, Zdistio, "distance tests for output", -1); 
+  zdef_(zinc, Zdiststat, "distance tests for statistics", -1); 
+  zdef_(zinc, Zdistplane, "total number of distance tests", -1);
+  zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1);
+  zzdef_(zinc, Zpartcoplanar, "   distance tests for these partitions", -1);
+  zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1);
+}
+void qh_allstatE2(void) {
+  zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1);
+  zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1);
+  zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup);
+  zdef_(zinc, Zhashridge, "total lookups of subridges (duplicates and boundary)", -1);
+  zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge);
+  zdef_(zinc, Zdupsame, "duplicated ridges in same merge cycle", -1);
+  zdef_(zinc, Zdupflip, "duplicated ridges with flipped facets", -1);
+
+  zdef_(zdoc, Zdoc6, "statistics for determining merges", -1);
+  zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1);
+  zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices",-1);
+  zzdef_(zinc, Zbestdist, "distance tests for best merge", -1);
+  zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1);
+  zzdef_(zinc, Zdistzero, "distance tests for checking simplicial convexity", -1);
+  zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1);
+  zdef_(zinc, Zcoplanarcentrum, "coplanar centrums in getmergeset", -1);
+  zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1);
+}
+void qh_allstatF(void) {
+  zdef_(zdoc, Zdoc7, "statistics for merging", -1);
+  zdef_(zinc, Zpremergetot, "merge iterations", -1);
+  zdef_(zadd, Zmergeinittot, "ave. initial non-convex ridges per iteration", Zpremergetot);
+  zdef_(zadd, Zmergeinitmax, "  maximum", -1);
+  zdef_(zadd, Zmergesettot, "  ave. additional non-convex ridges per iteration", Zpremergetot);
+  zdef_(zadd, Zmergesetmax, "  maximum additional in one pass", -1);
+  zdef_(zadd, Zmergeinittot2, "initial non-convex ridges for post merging", -1);
+  zdef_(zadd, Zmergesettot2, "  additional non-convex ridges", -1);
+  zdef_(wmax, Wmaxoutside, "max distance of vertex or coplanar point above facet (w/roundoff)", -1);
+  zdef_(wmin, Wminvertex, "max distance of merged vertex below facet (or roundoff)", -1);
+  zdef_(zinc, Zwidefacet, "centrums frozen due to a wide merge", -1);
+  zdef_(zinc, Zwidevertices, "centrums frozen due to extra vertices", -1);
+  zzdef_(zinc, Ztotmerge, "total number of facets or cycles of facets merged", -1);
+  zdef_(zinc, Zmergesimplex, "merged a simplex", -1);
+  zdef_(zinc, Zonehorizon, "simplices merged into coplanar horizon", -1);
+  zzdef_(zinc, Zcyclehorizon, "cycles of facets merged into coplanar horizon", -1);
+  zzdef_(zadd, Zcyclefacettot, "  ave. facets per cycle", Zcyclehorizon);
+  zdef_(zmax, Zcyclefacetmax, "  max. facets", -1);
+  zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1);
+  zdef_(zinc, Zmergenew, "new facets merged", -1);
+  zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1);
+  zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1);
+  zdef_(zinc, Zcyclevertex, "vertices deleted by merging into coplanar horizon", -1);
+  zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1);
+  zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1);
+  zdef_(zinc, Zneighbor, "merges due to redundant neighbors", -1);
+  zdef_(zadd, Ztestvneighbor, "non-convex vertex neighbors", -1); 
+}
+void qh_allstatG(void) {
+  zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1);
+  zdef_(wadd, Wacoplanartot, "  average merge distance", Zacoplanar);
+  zdef_(wmax, Wacoplanarmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1);
+  zdef_(wadd, Wcoplanartot, "  average merge distance", Zcoplanar);
+  zdef_(wmax, Wcoplanarmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zconcave, "merges due to concave facets", -1);
+  zdef_(wadd, Wconcavetot, "  average merge distance", Zconcave);
+  zdef_(wmax, Wconcavemax, "  maximum merge distance", -1);
+  zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1);
+  zdef_(wadd, Wavoidoldtot, "  average merge distance", Zavoidold);
+  zdef_(wmax, Wavoidoldmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zdegen, "merges due to degenerate facets", -1);
+  zdef_(wadd, Wdegentot, "  average merge distance", Zdegen);
+  zdef_(wmax, Wdegenmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1);
+  zdef_(wadd, Wflippedtot, "  average merge distance", Zflipped);
+  zdef_(wmax, Wflippedmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zduplicate, "merges due to duplicated ridges", -1);
+  zdef_(wadd, Wduplicatetot, "  average merge distance", Zduplicate);
+  zdef_(wmax, Wduplicatemax, "  maximum merge distance", -1);
+}
+void qh_allstatH(void) {
+  zdef_(zdoc, Zdoc8, "renamed vertex statistics", -1);
+  zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1);
+  zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1);
+  zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1);
+  zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1);
+  zdef_(zinc, Zdupridge, "  duplicate ridges detected", -1);
+  zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1);
+  zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1);
+  zdef_(zinc, Zdropdegen, "degenerate facets due to dropped neighbors", -1);
+  zdef_(zinc, Zdelfacetdup, "  facets deleted because of no neighbors", -1);
+  zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1);
+  zdef_(zinc, Zremvertexdel, "  deleted", -1);
+  zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1);
+  zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1);
+  zdef_(zinc, Zintersect, "intersections found redundant vertices", -1);
+  zdef_(zadd, Zintersecttot, "   ave. number found per vertex", Zintersect);
+  zdef_(zmax, Zintersectmax, "   max. found for a vertex", -1);
+  zdef_(zinc, Zvertexridge, NULL, -1);
+  zdef_(zadd, Zvertexridgetot, "  ave. number of ridges per tested vertex", Zvertexridge);
+  zdef_(zmax, Zvertexridgemax, "  max. number of ridges per tested vertex", -1);
+
+  zdef_(zdoc, Zdoc10, "memory usage statistics (in bytes)", -1);
+  zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1);
+  zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1);
+  zdef_(zadd, Zmempoints, "for input points and outside and coplanar sets",-1);
+  zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1);
+} /* allstat */
+
+void qh_allstatI(void) {
+  qhstat vridges= qhstat next;
+  zzdef_(zdoc, Zdoc11, "Voronoi ridge statistics", -1);
+  zzdef_(zinc, Zridge, "non-simplicial Voronoi vertices for all ridges", -1);
+  zzdef_(wadd, Wridge, "  ave. distance to ridge", Zridge);
+  zzdef_(wmax, Wridgemax, "  max. distance to ridge", -1);
+  zzdef_(zinc, Zridgemid, "bounded ridges", -1);
+  zzdef_(wadd, Wridgemid, "  ave. distance of midpoint to ridge", Zridgemid);
+  zzdef_(wmax, Wridgemidmax, "  max. distance of midpoint to ridge", -1);
+  zzdef_(zinc, Zridgeok, "bounded ridges with ok normal", -1);
+  zzdef_(wadd, Wridgeok, "  ave. angle to ridge", Zridgeok);
+  zzdef_(wmax, Wridgeokmax, "  max. angle to ridge", -1);
+  zzdef_(zinc, Zridge0, "bounded ridges with near-zero normal", -1);
+  zzdef_(wadd, Wridge0, "  ave. angle to ridge", Zridge0);
+  zzdef_(wmax, Wridge0max, "  max. angle to ridge", -1);
+
+  zdef_(zdoc, Zdoc12, "Triangulation statistics (Qt)", -1);
+  zdef_(zinc, Ztricoplanar, "non-simplicial facets triangulated", -1);
+  zdef_(zadd, Ztricoplanartot, "  ave. new facets created (may be deleted)", Ztricoplanar);
+  zdef_(zmax, Ztricoplanarmax, "  max. new facets created", -1);
+  zdef_(zinc, Ztrinull, "null new facets deleted (duplicated vertex)", -1);
+  zdef_(zinc, Ztrimirror, "mirrored pairs of new facets deleted (same vertices)", -1);
+  zdef_(zinc, Ztridegen, "degenerate new facets in output (same ridge)", -1);
+} /* allstat */
+
+/*---------------------------------
+  
+  qh_allstatistics()
+    reset printed flag for all statistics
+*/
+void qh_allstatistics (void) {
+  int i;
+  
+  for (i=ZEND; i--; ) 
+    qhstat printed[i]= False;
+} /* allstatistics */
+
+#if qh_KEEPstatistics
+/*---------------------------------
+  
+  qh_collectstatistics()
+    collect statistics for qh.facet_list
+
+*/
+void qh_collectstatistics (void) {
+  facetT *facet, *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  realT dotproduct, dist;
+  int sizneighbors, sizridges, sizvertices, i;
+  
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  zval_(Zmempoints)= qh num_points * qh normal_size + 
+                             sizeof (qhT) + sizeof (qhstatT);
+  zval_(Zmemfacets)= 0;
+  zval_(Zmemridges)= 0;
+  zval_(Zmemvertices)= 0;
+  zval_(Zangle)= 0;
+  wval_(Wangle)= 0.0;
+  zval_(Znumridges)= 0;
+  zval_(Znumfacets)= 0;
+  zval_(Znumneighbors)= 0;
+  zval_(Znumvertices)= 0;
+  zval_(Znumvneighbors)= 0;
+  zval_(Znummergetot)= 0;
+  zval_(Znummergemax)= 0;
+  zval_(Zvertices)= qh num_vertices - qh_setsize (qh del_vertices);
+  if (qh MERGING || qh APPROXhull || qh JOGGLEmax < REALmax/2)
+    wmax_(Wmaxoutside, qh max_outside);
+  if (qh MERGING)
+    wmin_(Wminvertex, qh min_vertex);
+  FORALLfacets
+    facet->seen= False;
+  if (qh DELAUNAY) {
+    FORALLfacets {
+      if (facet->upperdelaunay != qh UPPERdelaunay)
+        facet->seen= True; /* remove from angle statistics */
+    }
+  }
+  FORALLfacets {
+    if (facet->visible && qh NEWfacets)
+      continue;
+    sizvertices= qh_setsize (facet->vertices);
+    sizneighbors= qh_setsize (facet->neighbors);
+    sizridges= qh_setsize (facet->ridges);
+    zinc_(Znumfacets);
+    zadd_(Znumvertices, sizvertices);
+    zmax_(Zmaxvertices, sizvertices);
+    zadd_(Znumneighbors, sizneighbors);
+    zmax_(Zmaxneighbors, sizneighbors);
+    zadd_(Znummergetot, facet->nummerge);
+    i= facet->nummerge; /* avoid warnings */
+    zmax_(Znummergemax, i); 
+    if (!facet->simplicial) {
+      if (sizvertices == qh hull_dim) {
+	zinc_(Znowsimplicial);
+      }else {
+        zinc_(Znonsimplicial);
+      }
+    }
+    if (sizridges) {
+      zadd_(Znumridges, sizridges);
+      zmax_(Zmaxridges, sizridges);
+    }
+    zadd_(Zmemfacets, sizeof (facetT) + qh normal_size + 2*sizeof (setT) 
+       + SETelemsize * (sizneighbors + sizvertices));
+    if (facet->ridges) {
+      zadd_(Zmemridges,
+	 sizeof (setT) + SETelemsize * sizridges + sizridges * 
+         (sizeof (ridgeT) + sizeof (setT) + SETelemsize * (qh hull_dim-1))/2);
+    }
+    if (facet->outsideset)
+      zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->outsideset));
+    if (facet->coplanarset)
+      zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->coplanarset));
+    if (facet->seen) /* Delaunay upper envelope */
+      continue;
+    facet->seen= True;
+    FOREACHneighbor_(facet) {
+      if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge
+	  || neighbor->seen || !facet->normal || !neighbor->normal)
+	continue;
+      dotproduct= qh_getangle(facet->normal, neighbor->normal);
+      zinc_(Zangle);
+      wadd_(Wangle, dotproduct);
+      wmax_(Wanglemax, dotproduct)
+      wmin_(Wanglemin, dotproduct)
+    }
+    if (facet->normal) {
+      FOREACHvertex_(facet->vertices) {
+        zinc_(Zdiststat);
+        qh_distplane(vertex->point, facet, &dist);
+        wmax_(Wvertexmax, dist);
+        wmin_(Wvertexmin, dist);
+      }
+    }
+  }
+  FORALLvertices {
+    if (vertex->deleted)
+      continue;
+    zadd_(Zmemvertices, sizeof (vertexT));
+    if (vertex->neighbors) {
+      sizneighbors= qh_setsize (vertex->neighbors);
+      zadd_(Znumvneighbors, sizneighbors);
+      zmax_(Zmaxvneighbors, sizneighbors);
+      zadd_(Zmemvertices, sizeof (vertexT) + SETelemsize * sizneighbors);
+    }
+  }
+  qh RANDOMdist= qh old_randomdist;
+} /* collectstatistics */
+#endif /* qh_KEEPstatistics */
+
+/*---------------------------------
+  
+  qh_freestatistics(  )
+    free memory used for statistics
+*/
+void qh_freestatistics (void) {
+
+#if qh_QHpointer
+  free (qh_qhstat);
+  qh_qhstat= NULL;
+#endif
+} /* freestatistics */
+
+/*---------------------------------
+  
+  qh_initstatistics(  )
+    allocate and initialize statistics
+
+  notes:
+    uses malloc() instead of qh_memalloc() since mem.c not set up yet
+*/
+void qh_initstatistics (void) {
+  int i;
+  realT realx;
+  int intx;
+
+#if qh_QHpointer
+  if (!(qh_qhstat= (qhstatT *)malloc (sizeof(qhstatT)))) {
+    fprintf (qhmem.ferr, "qhull error (qh_initstatistics): insufficient memory\n");
+    exit (1);  /* can not use qh_errexit() */
+  }
+#endif
+  
+  qhstat next= 0;
+  qh_allstatA();
+  qh_allstatB();
+  qh_allstatC();
+  qh_allstatD();
+  qh_allstatE();
+  qh_allstatE2();
+  qh_allstatF();
+  qh_allstatG();
+  qh_allstatH();
+  qh_allstatI();
+  if (qhstat next > sizeof(qhstat id)) {
+    fprintf (qhmem.ferr, "qhull error (qh_initstatistics): increase size of qhstat.id[].\n\
+      qhstat.next %d should be <= sizeof(qhstat id) %d\n", qhstat next, sizeof(qhstat id));
+#if 0 /* for locating error, Znumridges should be duplicated */
+    for (i=0; i < ZEND; i++) {
+      int j;
+      for (j=i+1; j < ZEND; j++) {
+	if (qhstat id[i] == qhstat id[j]) {
+          fprintf (qhmem.ferr, "qhull error (qh_initstatistics): duplicated statistic %d at indices %d and %d\n", 
+	      qhstat id[i], i, j);
+	}
+      }
+    }
+#endif 
+    exit (1);  /* can not use qh_errexit() */
+  }
+  qhstat init[zinc].i= 0;
+  qhstat init[zadd].i= 0;
+  qhstat init[zmin].i= INT_MAX;
+  qhstat init[zmax].i= INT_MIN;
+  qhstat init[wadd].r= 0;
+  qhstat init[wmin].r= REALmax;
+  qhstat init[wmax].r= -REALmax;
+  for (i=0; i < ZEND; i++) {
+    if (qhstat type[i] > ZTYPEreal) {
+      realx= qhstat init[(unsigned char)(qhstat type[i])].r;
+      qhstat stats[i].r= realx;
+    }else if (qhstat type[i] != zdoc) {
+      intx= qhstat init[(unsigned char)(qhstat type[i])].i;
+      qhstat stats[i].i= intx;
+    }
+  }
+} /* initstatistics */
+
+/*---------------------------------
+  
+  qh_newstats(  )
+    returns True if statistics for zdoc
+
+  returns:
+    next zdoc
+*/
+boolT qh_newstats (int index, int *nextindex) {
+  boolT isnew= False;
+  int start, i;
+
+  if (qhstat type[qhstat id[index]] == zdoc) 
+    start= index+1;
+  else
+    start= index;
+  for (i= start; i < qhstat next && qhstat type[qhstat id[i]] != zdoc; i++) {
+    if (!qh_nostatistic(qhstat id[i]) && !qhstat printed[qhstat id[i]])
+	isnew= True;
+  }
+  *nextindex= i;
+  return isnew;
+} /* newstats */
+
+/*---------------------------------
+  
+  qh_nostatistic( index )
+    true if no statistic to print
+*/
+boolT qh_nostatistic (int i) {
+  
+  if ((qhstat type[i] > ZTYPEreal
+       &&qhstat stats[i].r == qhstat init[(unsigned char)(qhstat type[i])].r)
+      || (qhstat type[i] < ZTYPEreal
+	  &&qhstat stats[i].i == qhstat init[(unsigned char)(qhstat type[i])].i))
+    return True;
+  return False;
+} /* nostatistic */
+
+#if qh_KEEPstatistics
+/*---------------------------------
+  
+  qh_printallstatistics( fp, string )
+    print all statistics with header 'string'
+*/
+void qh_printallstatistics (FILE *fp, char *string) {
+
+  qh_allstatistics();
+  qh_collectstatistics();
+  qh_printstatistics (fp, string);
+  qh_memstatistics (fp);
+}
+
+
+/*---------------------------------
+  
+  qh_printstatistics( fp, string )
+    print statistics to a file with header 'string'
+    skips statistics with qhstat.printed[] (reset with qh_allstatistics)
+
+  see: 
+    qh_printallstatistics()
+*/
+void qh_printstatistics (FILE *fp, char *string) {
+  int i, k;
+  realT ave;
+  
+  if (qh num_points != qh num_vertices) {
+    wval_(Wpbalance)= 0;
+    wval_(Wpbalance2)= 0;
+  }else
+    wval_(Wpbalance2)= qh_stddev (zval_(Zpbalance), wval_(Wpbalance), 
+                                 wval_(Wpbalance2), &ave);
+  wval_(Wnewbalance2)= qh_stddev (zval_(Zprocessed), wval_(Wnewbalance), 
+                                 wval_(Wnewbalance2), &ave);
+  fprintf (fp, "\n\
+%s\n\
+ qhull invoked by: %s | %s\n%s with options:\n%s\n", string, qh rbox_command, 
+     qh qhull_command, qh_version, qh qhull_options);
+  fprintf (fp, "\nprecision constants:\n\
+ %6.2g max. abs. coordinate in the (transformed) input ('Qbd:n')\n\
+ %6.2g max. roundoff error for distance computation ('En')\n\
+ %6.2g max. roundoff error for angle computations\n\
+ %6.2g min. distance for outside points ('Wn')\n\
+ %6.2g min. distance for visible facets ('Vn')\n\
+ %6.2g max. distance for coplanar facets ('Un')\n\
+ %6.2g max. facet width for recomputing centrum and area\n\
+", 
+  qh MAXabs_coord, qh DISTround, qh ANGLEround, qh MINoutside, 
+        qh MINvisible, qh MAXcoplanar, qh WIDEfacet);
+  if (qh KEEPnearinside)
+    fprintf(fp, "\
+ %6.2g max. distance for near-inside points\n", qh NEARinside);
+  if (qh premerge_cos < REALmax/2) fprintf (fp, "\
+ %6.2g max. cosine for pre-merge angle\n", qh premerge_cos);
+  if (qh PREmerge) fprintf (fp, "\
+ %6.2g radius of pre-merge centrum\n", qh premerge_centrum);
+  if (qh postmerge_cos < REALmax/2) fprintf (fp, "\
+ %6.2g max. cosine for post-merge angle\n", qh postmerge_cos);
+  if (qh POSTmerge) fprintf (fp, "\
+ %6.2g radius of post-merge centrum\n", qh postmerge_centrum);
+  fprintf (fp, "\
+ %6.2g max. distance for merging two simplicial facets\n\
+ %6.2g max. roundoff error for arithmetic operations\n\
+ %6.2g min. denominator for divisions\n\
+  zero diagonal for Gauss: ", qh ONEmerge, REALepsilon, qh MINdenom);
+  for (k=0; k < qh hull_dim; k++)
+    fprintf (fp, "%6.2e ", qh NEARzero[k]);
+  fprintf (fp, "\n\n");
+  for (i=0 ; i < qhstat next; ) 
+    qh_printstats (fp, i, &i);
+} /* printstatistics */
+#endif /* qh_KEEPstatistics */
+
+/*---------------------------------
+  
+  qh_printstatlevel( fp, id )
+    print level information for a statistic
+
+  notes:
+    nop if id >= ZEND, printed, or same as initial value
+*/
+void qh_printstatlevel (FILE *fp, int id, int start) {
+#define NULLfield "       "
+
+  if (id >= ZEND || qhstat printed[id])
+    return;
+  if (qhstat type[id] == zdoc) {
+    fprintf (fp, "%s\n", qhstat doc[id]);
+    return;
+  }
+  start= 0; /* not used */
+  if (qh_nostatistic(id) || !qhstat doc[id])
+    return;
+  qhstat printed[id]= True;
+  if (qhstat count[id] != -1 
+      && qhstat stats[(unsigned char)(qhstat count[id])].i == 0)
+    fprintf (fp, " *0 cnt*");
+  else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] == -1)
+    fprintf (fp, "%7.2g", qhstat stats[id].r);
+  else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] != -1)
+    fprintf (fp, "%7.2g", qhstat stats[id].r/ qhstat stats[(unsigned char)(qhstat count[id])].i);
+  else if (qhstat type[id] < ZTYPEreal && qhstat count[id] == -1)
+    fprintf (fp, "%7d", qhstat stats[id].i);
+  else if (qhstat type[id] < ZTYPEreal && qhstat count[id] != -1)
+    fprintf (fp, "%7.3g", (realT) qhstat stats[id].i / qhstat stats[(unsigned char)(qhstat count[id])].i);
+  fprintf (fp, " %s\n", qhstat doc[id]);
+} /* printstatlevel */
+
+
+/*---------------------------------
+  
+  qh_printstats( fp, index, nextindex )
+    print statistics for a zdoc group
+
+  returns:
+    next zdoc if non-null
+*/
+void qh_printstats (FILE *fp, int index, int *nextindex) {
+  int j, nexti;
+
+  if (qh_newstats (index, &nexti)) {
+    fprintf (fp, "\n");
+    for (j=index; j--------------------------------
+  
+  qh_stddev( num, tot, tot2, ave )
+    compute the standard deviation and average from statistics
+
+    tot2 is the sum of the squares
+  notes:
+    computes r.m.s.: 
+      (x-ave)^2 
+      == x^2 - 2x tot/num +   (tot/num)^2
+      == tot2 - 2 tot tot/num + tot tot/num 
+      == tot2 - tot ave
+*/
+realT qh_stddev (int num, realT tot, realT tot2, realT *ave) {
+  realT stddev;
+
+  *ave= tot/num;
+  stddev= sqrt (tot2/num - *ave * *ave);
+  return stddev;
+} /* stddev */
+
+#endif /* qh_KEEPstatistics */ 
+
+#if !qh_KEEPstatistics
+void    qh_collectstatistics (void) {}
+void    qh_printallstatistics (FILE *fp, char *string) {};
+void    qh_printstatistics (FILE *fp, char *string) {}
+#endif
+

Added: trunk/scipy/spatial/qhull/src/stat.h
===================================================================
--- trunk/scipy/spatial/qhull/src/stat.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/stat.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,522 @@
+  /*
  ---------------------------------
+
+   stat.h 
+     contains all statistics that are collected for qhull
+
+   see qh-stat.htm and stat.c
+
+   copyright (c) 1993-2003, The Geometry Center
+
+   recompile qhull if you change this file
+
+   Integer statistics are Z* while real statistics are W*.  
+
+   define maydebugx to call a routine at every statistic event
+
+*/
+
+#ifndef qhDEFstat
+#define qhDEFstat 1
+
+
+/*---------------------------------
+
+  qh_KEEPstatistics
+    0 turns off statistic gathering (except zzdef/zzinc/zzadd/zzval/wwval)
+*/
+#ifndef qh_KEEPstatistics
+#define qh_KEEPstatistics 1
+#endif
+
+/*---------------------------------
+
+  Zxxx for integers, Wxxx for reals
+
+  notes:
+    be sure that all statistics are defined in stat.c
+      otherwise initialization may core dump
+    can pick up all statistics by:
+      grep '[zw].*_[(][ZW]' *.c >z.x
+    remove trailers with query">-
+    remove leaders with  query-replace-regexp [ ^I]+  (
+*/
+#if qh_KEEPstatistics
+enum statistics {     /* alphabetical after Z/W */
+    Zacoplanar,
+    Wacoplanarmax,
+    Wacoplanartot,
+    Zangle,
+    Wangle,
+    Wanglemax,
+    Wanglemin,
+    Zangletests,
+    Wareatot,
+    Wareamax,
+    Wareamin,
+    Zavoidold,
+    Wavoidoldmax,
+    Wavoidoldtot,
+    Zback0,
+    Zbestcentrum,
+    Zbestdist,
+    Zbestlower,
+    Zbestlowerv,
+    Zcentrumtests,
+    Zcheckpart,
+    Zcomputefurthest,
+    Zconcave,
+    Wconcavemax,
+    Wconcavetot,
+    Zconcaveridges,
+    Zconcaveridge,
+    Zcoplanar,
+    Wcoplanarmax,
+    Wcoplanartot,
+    Zcoplanarangle,
+    Zcoplanarcentrum,
+    Zcoplanarhorizon,
+    Zcoplanarinside,
+    Zcoplanarpart,
+    Zcoplanarridges,
+    Wcpu,
+    Zcyclefacetmax,
+    Zcyclefacettot,
+    Zcyclehorizon,
+    Zcyclevertex,
+    Zdegen,
+    Wdegenmax,
+    Wdegentot,
+    Zdegenvertex,
+    Zdelfacetdup, 
+    Zdelridge,
+    Zdelvertextot,
+    Zdelvertexmax,
+    Zdetsimplex,
+    Zdistcheck,
+    Zdistconvex,
+    Zdistgood,
+    Zdistio,
+    Zdistplane,
+    Zdiststat,
+    Zdistvertex,
+    Zdistzero,
+    Zdoc1,
+    Zdoc2,
+    Zdoc3,
+    Zdoc4,
+    Zdoc5,
+    Zdoc6,
+    Zdoc7,
+    Zdoc8,
+    Zdoc9,
+    Zdoc10,
+    Zdoc11,
+    Zdoc12,
+    Zdropdegen,
+    Zdropneighbor,
+    Zdupflip,
+    Zduplicate,
+    Wduplicatemax,
+    Wduplicatetot,
+    Zdupridge,
+    Zdupsame,
+    Zflipped, 
+    Wflippedmax, 
+    Wflippedtot, 
+    Zflippedfacets,
+    Zfindbest,
+    Zfindbestmax,
+    Zfindbesttot,
+    Zfindcoplanar,
+    Zfindfail,
+    Zfindhorizon,
+    Zfindhorizonmax,
+    Zfindhorizontot,
+    Zfindjump,
+    Zfindnew,
+    Zfindnewmax,
+    Zfindnewtot,
+    Zfindnewjump,
+    Zfindnewsharp,
+    Zgauss0,
+    Zgoodfacet,
+    Zhashlookup,
+    Zhashridge,
+    Zhashridgetest,
+    Zhashtests,
+    Zinsidevisible,
+    Zintersect,
+    Zintersectfail,
+    Zintersectmax,
+    Zintersectnum,
+    Zintersecttot,
+    Zmaxneighbors,
+    Wmaxout,
+    Wmaxoutside,
+    Zmaxridges,
+    Zmaxvertex,
+    Zmaxvertices,
+    Zmaxvneighbors,
+    Zmemfacets,
+    Zmempoints,
+    Zmemridges,
+    Zmemvertices,
+    Zmergeflipdup,
+    Zmergehorizon,
+    Zmergeinittot,
+    Zmergeinitmax,
+    Zmergeinittot2,
+    Zmergeintohorizon,
+    Zmergenew,
+    Zmergesettot,
+    Zmergesetmax,
+    Zmergesettot2,
+    Zmergesimplex,
+    Zmergevertex,
+    Wmindenom,
+    Wminvertex,
+    Zminnorm,
+    Zmultiridge,
+    Znearlysingular,
+    Zneighbor,
+    Wnewbalance,
+    Wnewbalance2,
+    Znewfacettot,
+    Znewfacetmax,
+    Znewvertex,
+    Wnewvertex,
+    Wnewvertexmax,
+    Znoarea,
+    Znonsimplicial,
+    Znowsimplicial,
+    Znotgood,
+    Znotgoodnew,
+    Znotmax,
+    Znumfacets,
+    Znummergemax,
+    Znummergetot,
+    Znumneighbors,
+    Znumridges,
+    Znumvertices,
+    Znumvisibility,
+    Znumvneighbors,
+    Zonehorizon,
+    Zpartangle,
+    Zpartcoplanar,
+    Zpartflip,
+    Zparthorizon,
+    Zpartinside,
+    Zpartition, 
+    Zpartitionall,
+    Zpartnear,
+    Zpbalance,
+    Wpbalance,
+    Wpbalance2, 
+    Zpostfacets, 
+    Zpremergetot,
+    Zprocessed,
+    Zremvertex,
+    Zremvertexdel,
+    Zrenameall,
+    Zrenamepinch,
+    Zrenameshare,
+    Zretry,
+    Wretrymax,
+    Zridge,
+    Wridge,
+    Wridgemax,
+    Zridge0,
+    Wridge0,
+    Wridge0max,
+    Zridgemid,
+    Wridgemid,
+    Wridgemidmax,
+    Zridgeok,
+    Wridgeok,
+    Wridgeokmax,
+    Zsearchpoints,
+    Zsetplane,
+    Ztestvneighbor,
+    Ztotcheck,
+    Ztothorizon,
+    Ztotmerge,
+    Ztotpartcoplanar,
+    Ztotpartition,
+    Ztotridges,
+    Ztotvertices,
+    Ztotvisible,
+    Ztricoplanar,
+    Ztricoplanarmax,
+    Ztricoplanartot,
+    Ztridegen,
+    Ztrimirror,
+    Ztrinull,
+    Wvertexmax,
+    Wvertexmin,
+    Zvertexridge,
+    Zvertexridgetot,
+    Zvertexridgemax,
+    Zvertices,
+    Zvisfacettot,
+    Zvisfacetmax,
+    Zvisvertextot,
+    Zvisvertexmax,
+    Zwidefacet,
+    Zwidevertices,
+    ZEND};
+
+/*---------------------------------
+
+  Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
+
+  notes:
+    be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
+*/
+#else
+enum statistics {     /* for zzdef etc. macros */
+  Zback0,
+  Zbestdist,
+  Zcentrumtests,
+  Zcheckpart,
+  Zconcaveridges,
+  Zcoplanarhorizon,
+  Zcoplanarpart,
+  Zcoplanarridges,
+  Zcyclefacettot,
+  Zcyclehorizon,
+  Zdelvertextot,
+  Zdistcheck,
+  Zdistconvex,
+  Zdistzero,
+  Zdoc1,
+  Zdoc2,
+  Zdoc3,
+  Zdoc11,
+  Zflippedfacets,
+  Zgauss0,
+  Zminnorm,
+  Zmultiridge,
+  Znearlysingular,
+  Wnewvertexmax,
+  Znumvisibility,
+  Zpartcoplanar,
+  Zpartition,
+  Zpartitionall,
+  Zprocessed,
+  Zretry,
+  Zridge,
+  Wridge,
+  Wridgemax,
+  Zridge0,
+  Wridge0,
+  Wridge0max,
+  Zridgemid,
+  Wridgemid,
+  Wridgemidmax,
+  Zridgeok,
+  Wridgeok,
+  Wridgeokmax,
+  Zsetplane,
+  Ztotmerge,
+    ZEND};
+#endif
+
+/*---------------------------------
+  
+  ztype
+    the type of a statistic sets its initial value.  
+
+  notes:
+    The type should be the same as the macro for collecting the statistic
+*/
+enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
+
+/*========== macros and constants =============*/
+
+/*----------------------------------
+  
+  MAYdebugx
+    define as maydebug() to be called frequently for error trapping
+*/
+#define MAYdebugx 
+
+/*----------------------------------
+  
+  zzdef_, zdef_( type, name, doc, -1)
+    define a statistic (assumes 'qhstat.next= 0;')
+
+  zdef_( type, name, doc, count)
+    define an averaged statistic
+    printed as name/count
+*/
+#define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#if qh_KEEPstatistics
+#define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#else
+#define zdef_(type,name,doc,count)
+#endif
+
+/*----------------------------------
+  
+  zzinc_( name ), zinc_( name)
+    increment an integer statistic
+*/
+#define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#if qh_KEEPstatistics
+#define zinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#else
+#define zinc_(id) {}
+#endif
+
+/*----------------------------------
+  
+  zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
+    add value to an integer or real statistic
+*/
+#define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wwadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#if qh_KEEPstatistics
+#define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#else
+#define zadd_(id, val) {}
+#define wadd_(id, val) {}
+#endif
+
+/*----------------------------------
+
+  zzval_( name ), zval_( name ), wwval_( name )
+    set or return value of a statistic
+*/
+#define zzval_(id) ((qhstat stats[id]).i)
+#define wwval_(id) ((qhstat stats[id]).r)
+#if qh_KEEPstatistics
+#define zval_(id) ((qhstat stats[id]).i)
+#define wval_(id) ((qhstat stats[id]).r)
+#else
+#define zval_(id) qhstat tempi
+#define wval_(id) qhstat tempr
+#endif
+
+/*----------------------------------
+
+  zmax_( id, val ), wmax_( id, value )
+    maximize id with val
+*/
+#define wwmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#if qh_KEEPstatistics
+#define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));}
+#define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#else
+#define zmax_(id, val) {}
+#define wmax_(id, val) {}
+#endif
+
+/*----------------------------------
+
+  zmin_( id, val ), wmin_( id, value )
+    minimize id with val
+*/
+#if qh_KEEPstatistics
+#define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));}
+#define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));}
+#else
+#define zmin_(id, val) {}
+#define wmin_(id, val) {}
+#endif
+
+/*================== stat.h types ==============*/
+
+
+/*----------------------------------
+ 
+  intrealT
+    union of integer and real, used for statistics
+*/
+typedef union intrealT intrealT;    /* union of int and realT */
+union intrealT {
+    int i;
+    realT r;
+};
+
+/*----------------------------------
+  
+  qhstat
+    global data structure for statistics
+  
+  notes:
+   access to qh_qhstat is via the "qhstat" macro.  There are two choices
+   qh_QHpointer = 1     access globals via a pointer
+                        enables qh_saveqhull() and qh_restoreqhull()
+		= 0     qh_qhstat is a static data structure
+		        only one instance of qhull() can be active at a time
+			default value
+   qh_QHpointer is defined in qhull.h
+
+   allocated in stat.c
+*/
+typedef struct qhstatT qhstatT; 
+#if qh_QHpointer
+#define qhstat qh_qhstat->
+extern qhstatT *qh_qhstat;
+#else
+#define qhstat qh_qhstat.
+extern qhstatT qh_qhstat; 
+#endif
+struct qhstatT {  
+  intrealT   stats[ZEND];     /* integer and real statistics */
+  unsigned   char id[ZEND+10]; /* id's in print order */
+  char      *doc[ZEND];       /* array of documentation strings */
+  short int  count[ZEND];     /* -1 if none, else index of count to use */
+  char       type[ZEND];      /* type, see ztypes above */
+  char       printed[ZEND];   /* true, if statistic has been printed */
+  intrealT   init[ZTYPEend];  /* initial values by types, set initstatistics */
+
+  int        next;            /* next index for zdef_ */
+  int        precision;       /* index for precision problems */
+  int        vridges;         /* index for Voronoi ridges */
+  int        tempi;
+  realT      tempr;
+};
+
+/*========== function prototypes ===========*/
+
+void    qh_allstatA(void);
+void    qh_allstatB(void);
+void    qh_allstatC(void);
+void    qh_allstatD(void);
+void    qh_allstatE(void);
+void    qh_allstatE2(void);
+void    qh_allstatF(void);
+void    qh_allstatG(void);
+void    qh_allstatH(void);
+void    qh_allstatI(void);
+void    qh_allstatistics (void);
+void    qh_collectstatistics (void);
+void	qh_freestatistics (void);
+void    qh_initstatistics (void);
+boolT 	qh_newstats (int index, int *nextindex);
+boolT 	qh_nostatistic (int i);
+void    qh_printallstatistics (FILE *fp, char *string);
+void    qh_printstatistics (FILE *fp, char *string);
+void  	qh_printstatlevel (FILE *fp, int id, int start);
+void  	qh_printstats (FILE *fp, int index, int *nextindex);
+realT   qh_stddev (int num, realT tot, realT tot2, realT *ave);
+
+#endif   /* qhDEFstat */

Added: trunk/scipy/spatial/qhull/src/unix.c
===================================================================
--- trunk/scipy/spatial/qhull/src/unix.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/unix.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,377 @@
+/*
  ---------------------------------
+
+   unix.c
+     command line interface to qhull
+	 includes SIOUX interface for Macintoshes
+
+   see qh-qhull.htm
+
+   copyright (c) 1993-2003, The Geometry Center
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "qhull.h"
+#include "mem.h"
+#include "qset.h"
+
+#if __MWERKS__ && __POWERPC__
+#include 
+#include 
+#include 
+#include 
+
+#elif __cplusplus
+extern "C" {
+  int isatty (int);
+}
+
+#elif _MSC_VER
+#include 
+#define isatty _isatty
+
+#else
+int isatty (int);  /* returns 1 if stdin is a tty
+		   if "Undefined symbol" this can be deleted along with call in main() */
+#endif
+
+/*---------------------------------
+
+  qh_prompt 
+    long prompt for qhull
+    
+  see:
+    concise prompt below
+*/  
+char qh_prompta[]= "\n\
+qhull- compute convex hulls and related structures.\n\
+    http://www.qhull.org  %s\n\
+\n\
+input (stdin):\n\
+    first lines: dimension and number of points (or vice-versa).\n\
+    other lines: point coordinates, best if one point per line\n\
+    comments:    start with a non-numeric character\n\
+    halfspaces:  use dim plus one and put offset after coefficients.\n\
+                 May be preceeded by a single interior point ('H').\n\
+\n\
+options:\n\
+    d    - Delaunay triangulation by lifting points to a paraboloid\n\
+    d Qu - furthest-site Delaunay triangulation (upper convex hull)\n\
+    v    - Voronoi diagram (dual of the Delaunay triangulation)\n\
+    v Qu - furthest-site Voronoi diagram\n\
+    Hn,n,... - halfspace intersection about point [n,n,0,...]\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+    Qc   - keep coplanar points with nearest facet\n\
+    Qi   - keep interior points with nearest facet\n\
+\n\
+Qhull control options:\n\
+    Qbk:n   - scale coord k so that low bound is n\n\
+      QBk:n - scale coord k so that upper bound is n (QBk is %2.2g)\n\
+    QbB  - scale input to unit cube centered at the origin\n\
+    Qbb  - scale last coordinate to [0,m] for Delaunay triangulations\n\
+    Qbk:0Bk:0 - remove k-th coordinate from input\n\
+    QJn  - randomly joggle input in range [-n,n]\n\
+    QRn  - random rotation (n=seed, n=0 time, n=-1 time/no rotate)\n\
+%s%s%s%s";  /* split up qh_prompt for Visual C++ */
+char qh_promptb[]= "\
+    Qf   - partition point to furthest outside facet\n\
+    Qg   - only build good facets (needs 'QGn', 'QVn', or 'PdD')\n\
+    Qm   - only process points that would increase max_outside\n\
+    Qr   - process random outside points instead of furthest ones\n\
+    Qs   - search all points for the initial simplex\n\
+    Qu   - for 'd' or 'v', compute upper hull without point at-infinity\n\
+              returns furthest-site Delaunay triangulation\n\
+    Qv   - test vertex neighbors for convexity\n\
+    Qx   - exact pre-merges (skips coplanar and angle-coplanar facets)\n\
+    Qz   - add point-at-infinity to Delaunay triangulation\n\
+    QGn  - good facet if visible from point n, -n for not visible\n\
+    QVn  - good facet if it includes point n, -n if not\n\
+    Q0   - turn off default premerge with 'C-0'/'Qx'\n\
+    Q1	   - sort merges by type instead of angle\n\
+    Q2   - merge all non-convex at once instead of independent sets\n\
+    Q3   - do not merge redundant vertices\n\
+    Q4   - avoid old->new merges\n\
+    Q5   - do not correct outer planes at end of qhull\n\
+    Q6   - do not pre-merge concave or coplanar facets\n\
+    Q7   - depth-first processing instead of breadth-first\n\
+    Q8   - do not process near-inside points\n\
+    Q9   - process furthest of furthest points\n\
+    Q10  - no special processing for narrow distributions\n\
+    Q11  - copy normals and recompute centrums for tricoplanar facets\n\
+\n\
+";
+char qh_promptc[]= "\
+Topts- Trace options:\n\
+    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
+    Tc   - check frequently during execution\n\
+    Ts   - print statistics\n\
+    Tv   - verify result: structure, convexity, and point inclusion\n\
+    Tz   - send all output to stdout\n\
+    TFn  - report summary when n or more facets created\n\
+    TI file - input data from file, no spaces or single quotes\n\
+    TO file - output results to file, may be enclosed in single quotes\n\
+    TPn  - turn on tracing when point n added to hull\n\
+     TMn - turn on tracing at merge n\n\
+     TWn - trace merge facets when width > n\n\
+    TRn  - rerun qhull n times.  Use with 'QJn'\n\
+    TVn  - stop qhull after adding point n, -n for before (see TCn)\n\
+     TCn - stop qhull after building cone for point n (see TVn)\n\
+\n\
+Precision options:\n\
+    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
+     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
+           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
+    En   - max roundoff error for distance computation\n\
+    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
+    Vn   - min distance above plane for a visible facet (default 3C-n or En)\n\
+    Un   - max distance below plane for a new, coplanar point (default Vn)\n\
+    Wn   - min facet width for outside point (before roundoff, default 2Vn)\n\
+\n\
+Output formats (may be combined; if none, produces a summary to stdout):\n\
+    f    - facet dump\n\
+    G    - Geomview output (see below)\n\
+    i    - vertices incident to each facet\n\
+    m    - Mathematica output (2-d and 3-d)\n\
+    o    - OFF format (dim, points and facets; Voronoi regions)\n\
+    n    - normals with offsets\n\
+    p    - vertex coordinates or Voronoi vertices (coplanar points if 'Qc')\n\
+    s    - summary (stderr)\n\
+\n\
+";
+char qh_promptd[]= "\
+More formats:\n\
+    Fa   - area for each facet\n\
+    FA   - compute total area and volume for option 's'\n\
+    Fc   - count plus coplanar points for each facet\n\
+           use 'Qc' (default) for coplanar and 'Qi' for interior\n\
+    FC   - centrum or Voronoi center for each facet\n\
+    Fd   - use cdd format for input (homogeneous with offset first)\n\
+    FD   - use cdd format for numeric output (offset first)\n\
+    FF   - facet dump without ridges\n\
+    Fi   - inner plane for each facet\n\
+           for 'v', separating hyperplanes for bounded Voronoi regions\n\
+    FI   - ID of each facet\n\
+    Fm   - merge count for each facet (511 max)\n\
+    FM   - Maple output (2-d and 3-d)\n\
+    Fn   - count plus neighboring facets for each facet\n\
+    FN   - count plus neighboring facets for each point\n\
+    Fo   - outer plane (or max_outside) for each facet\n\
+           for 'v', separating hyperplanes for unbounded Voronoi regions\n\
+    FO   - options and precision constants\n\
+    Fp   - dim, count, and intersection coordinates (halfspace only)\n\
+    FP   - nearest vertex and distance for each coplanar point\n\
+    FQ   - command used for qhull\n\
+    Fs   - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
+                      output: #vertices, #facets, #coplanars, #nonsimplicial\n\
+                    #real (2), max outer plane, min vertex\n\
+    FS   - sizes:   #int (0)\n\
+                    #real(2) tot area, tot volume\n\
+    Ft   - triangulation with centrums for non-simplicial facets (OFF format)\n\
+    Fv   - count plus vertices for each facet\n\
+           for 'v', Voronoi diagram as Voronoi vertices for pairs of sites\n\
+    FV   - average of vertices (a feasible point for 'H')\n\
+    Fx   - extreme points (in order for 2-d)\n\
+\n\
+";
+char qh_prompte[]= "\
+Geomview options (2-d, 3-d, and 4-d; 2-d Voronoi)\n\
+    Ga   - all points as dots\n\
+     Gp  -  coplanar points and vertices as radii\n\
+     Gv  -  vertices as spheres\n\
+    Gi   - inner planes only\n\
+     Gn  -  no planes\n\
+     Go  -  outer planes only\n\
+    Gc   - centrums\n\
+    Gh   - hyperplane intersections\n\
+    Gr   - ridges\n\
+    GDn  - drop dimension n in 3-d and 4-d output\n\
+    Gt   - for 3-d 'd', transparent outer ridges\n\
+\n\
+Print options:\n\
+    PAn  - keep n largest facets by area\n\
+    Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
+    PDk:n - drop facet if normal[k] >= n\n\
+    Pg   - print good facets (needs 'QGn' or 'QVn')\n\
+    PFn  - keep facets whose area is at least n\n\
+    PG   - print neighbors of good facets\n\
+    PMn  - keep n facets with most merges\n\
+    Po   - force output.  If error, output neighborhood of facet\n\
+    Pp   - do not report precision problems\n\
+\n\
+    .    - list of all options\n\
+    -    - one line descriptions of all options\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt2
+    synopsis for qhull
+*/
+char qh_prompt2[]= "\n\
+qhull- compute convex hulls and related structures.  Qhull %s\n\
+    input (stdin): dimension, n, point coordinates\n\
+    comments start with a non-numeric character\n\
+    halfspace: use dim+1 and put offsets after coefficients\n\
+\n\
+options (qh-quick.htm):\n\
+    d    - Delaunay triangulation by lifting points to a paraboloid\n\
+    d Qu - furthest-site Delaunay triangulation (upper convex hull)\n\
+    v    - Voronoi diagram as the dual of the Delaunay triangulation\n\
+    v Qu - furthest-site Voronoi diagram\n\
+    H1,1 - Halfspace intersection about [1,1,0,...] via polar duality\n\
+    Qt   - triangulated output\n\
+    QJ   - joggled input instead of merged facets\n\
+    Tv   - verify result: structure, convexity, and point inclusion\n\
+    .    - concise list of all options\n\
+    -    - one-line description of all options\n\
+\n\
+Output options (subset):\n\
+    s    - summary of results (default)\n\
+    i    - vertices incident to each facet\n\
+    n    - normals with offsets\n\
+    p    - vertex coordinates (if 'Qc', includes coplanar points)\n\
+           if 'v', Voronoi vertices\n\
+    Fp   - halfspace intersections\n\
+    Fx   - extreme points (convex hull vertices)\n\
+    FA   - compute total area and volume\n\
+    o    - OFF format (if 'v', outputs Voronoi regions)\n\
+    G    - Geomview output (2-d, 3-d and 4-d)\n\
+    m    - Mathematica output (2-d and 3-d)\n\
+    QVn  - print facets that include point n, -n if not\n\
+    TO file- output results to file, may be enclosed in single quotes\n\
+\n\
+examples:\n\
+    rbox c d D2 | qhull Qc s f Fx | more      rbox 1000 s | qhull Tv s FA\n\
+    rbox 10 D2 | qhull d QJ s i TO result     rbox 10 D2 | qhull v Qbb Qt p\n\
+    rbox 10 D2 | qhull d Qu QJ m              rbox 10 D2 | qhull v Qu QJ o\n\
+    rbox c | qhull n                          rbox c | qhull FV n | qhull H Fp\n\
+    rbox d D12 | qhull QR0 FA                 rbox c D7 | qhull FA TF1000\n\
+    rbox y 1000 W0 | qhull                    rbox 10 | qhull v QJ o Fv\n\
+\n\
+";
+/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
+
+/*---------------------------------
+
+  qh_prompt3
+    concise prompt for qhull
+*/
+char qh_prompt3[]= "\n\
+Qhull %s.\n\
+Except for 'F.' and 'PG', upper-case options take an argument.\n\
+\n\
+ delaunay       voronoi	       Geomview       Halfspace      facet_dump\n\
+ incidences     mathematica    normals        OFF_format     points\n\
+ summary\n\
+\n\
+ Farea          FArea-total    Fcoplanars     FCentrums      Fd-cdd-in\n\
+ FD-cdd-out     FF-dump-xridge Finner         FIDs           Fmerges\n\
+ Fneighbors     FNeigh-vertex  Fouter         FOptions       Fpoint-intersect\n\
+ FPoint_near    FQhull         Fsummary       FSize          Ftriangles\n\
+ Fvertices      Fvoronoi       FVertex-ave    Fxtremes       FMaple\n\
+\n\
+ Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
+ Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
+ Gtransparent\n\
+\n\
+ PArea-keep     Pdrop d0:0D0   Pgood          PFacet_area_keep\n\
+ PGood_neighbors PMerge-keep   Poutput_forced Pprecision_not\n\
+\n\
+ QbBound 0:0.5  Qbk:0Bk:0_drop QbB-scale-box  Qbb-scale-last Qcoplanar\n\
+ Qfurthest      Qgood_only     QGood_point    Qinterior      Qmax_out\n\
+ QJoggle        Qrandom        QRotate        Qsearch_1st    Qtriangulate\n\
+ QupperDelaunay QVertex_good   Qvneighbors    Qxact_merge    Qzinfinite\n\
+\n\
+ Q0_no_premerge Q1_no_angle    Q2_no_independ Q3_no_redundant Q4_no_old\n\
+ Q5_no_check_out Q6_no_concave Q7_depth_first Q8_no_near_in  Q9_pick_furthest\n\
+ Q10_no_narrow  Q11_trinormals\n\
+\n\
+ T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
+ TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
+ TRerun         TWide_trace    TVertex_stop   TCone_stop\n\
+\n\
+ Angle_max      Centrum_size   Error_round    Random_dist    Visible_min\n\
+ Ucoplanar_max  Wide_outside\n\
+";
+
+/*---------------------------------
+
+  main( argc, argv )
+    processes the command line, calls qhull() to do the work, and exits
+
+  design:
+    initializes data structures
+    reads points
+    finishes initialization
+    computes convex hull and other structures
+    checks the result
+    writes the output
+    frees memory
+*/
+int main(int argc, char *argv[]) {
+  int curlong, totlong; /* used !qh_NOmem */
+  int exitcode, numpoints, dim;
+  coordT *points;
+  boolT ismalloc;
+
+#if __MWERKS__ && __POWERPC__
+  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
+  SIOUXSettings.showstatusline= false;
+  SIOUXSettings.tabspaces= 1;
+  SIOUXSettings.rows= 40;
+  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
+  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
+  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0))
+    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
+  argc= ccommand(&argv);
+#endif
+
+  if ((argc == 1) && isatty( 0 /*stdin*/)) {
+    fprintf(stdout, qh_prompt2, qh_version);
+    exit(qh_ERRnone);
+  }
+  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompta, qh_version, qh_DEFAULTbox,
+		qh_promptb, qh_promptc, qh_promptd, qh_prompte);
+    exit(qh_ERRnone);
+  }
+  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
+    fprintf(stdout, qh_prompt3, qh_version);
+    exit(qh_ERRnone);
+  }
+  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
+  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
+  if (!exitcode) {
+    qh_initflags (qh qhull_command);
+    points= qh_readpoints (&numpoints, &dim, &ismalloc);
+    qh_init_B (points, numpoints, dim, ismalloc);
+    qh_qhull();
+    qh_check_output();
+    qh_produce_output();
+    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points();
+    exitcode= qh_ERRnone;
+  }
+  qh NOerrexit= True;  /* no more setjmp */
+#ifdef qh_NOmem
+  qh_freeqhull( True);
+#else
+  qh_freeqhull( False);
+  qh_memfreeshort (&curlong, &totlong);
+  if (curlong || totlong)
+    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+       totlong, curlong);
+#endif
+  return exitcode;
+} /* main */
+

Added: trunk/scipy/spatial/qhull/src/user.c
===================================================================
--- trunk/scipy/spatial/qhull/src/user.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/user.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,324 @@
+/*
  ---------------------------------
+
+   user.c 
+   user redefinable functions
+
+   see README.txt  see COPYING.txt for copyright information.
+
+   see qhull.h for data structures, macros, and user-callable functions.
+
+   see user_eg.c, unix.c, and qhull_interface.cpp for examples.
+
+   see user.h for user-definable constants
+
+      use qh_NOmem in mem.h to turn off memory management
+      use qh_NOmerge in user.h to turn off facet merging
+      set qh_KEEPstatistics in user.h to 0 to turn off statistics
+
+   This is unsupported software.  You're welcome to make changes,
+   but you're on your own if something goes wrong.  Use 'Tc' to
+   check frequently.  Usually qhull will report an error if 
+   a data structure becomes inconsistent.  If so, it also reports
+   the last point added to the hull, e.g., 102.  You can then trace
+   the execution of qhull with "T4P102".  
+
+   Please report any errors that you fix to qhull at qhull.org
+
+   call_qhull is a template for calling qhull from within your application
+
+   if you recompile and load this module, then user.o will not be loaded
+   from qhull.a
+
+   you can add additional quick allocation sizes in qh_user_memsizes
+
+   if the other functions here are redefined to not use qh_print...,
+   then io.o will not be loaded from qhull.a.  See user_eg.c for an
+   example.  We recommend keeping io.o for the extra debugging 
+   information it supplies.
+*/
+
+#include "qhull_a.h" 
+
+/*---------------------------------
+
+  qh_call_qhull( void )
+    template for calling qhull from inside your program
+    remove #if 0, #endif to compile
+
+  returns: 
+    exit code (see qh_ERR... in qhull.h)
+    all memory freed
+
+  notes:
+    This can be called any number of times.  
+
+  see:
+    qh_call_qhull_once()
+    
+*/
+#if 0
+{
+  int dim;	            /* dimension of points */
+  int numpoints;            /* number of points */
+  coordT *points;           /* array of coordinates for each point */
+  boolT ismalloc;           /* True if qhull should free points in qh_freeqhull() or reallocation */
+  char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
+  FILE *outfile= stdout;    /* output from qh_produce_output()
+			       use NULL to skip qh_produce_output() */
+  FILE *errfile= stderr;    /* error messages from qhull code */
+  int exitcode;             /* 0 if no error from qhull */
+  facetT *facet;	    /* set by FORALLfacets */
+  int curlong, totlong;	    /* memory remaining after qh_memfreeshort */
+
+  /* initialize dim, numpoints, points[], ismalloc here */
+  exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+                      flags, outfile, errfile); 
+  if (!exitcode) {                  /* if no error */
+    /* 'qh facet_list' contains the convex hull */
+    FORALLfacets {
+       /* ... your code ... */
+    }
+  }
+  qh_freeqhull(!qh_ALL);
+  qh_memfreeshort (&curlong, &totlong);
+  if (curlong || totlong) 
+    fprintf (errfile, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
+}
+#endif
+
+/*---------------------------------
+
+  qh_new_qhull( dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
+    build new qhull data structure and return exitcode (0 if no errors)
+
+  notes:
+    do not modify points until finished with results.
+      The qhull data structure contains pointers into the points array.
+    do not call qhull functions before qh_new_qhull().
+      The qhull data structure is not initialized until qh_new_qhull().
+
+    outfile may be null
+    qhull_cmd must start with "qhull "
+    projects points to a new point array for Delaunay triangulations ('d' and 'v')
+    transforms points into a new point array for halfspace intersection ('H')
+       
+
+  To allow multiple, concurrent calls to qhull() 
+    - set qh_QHpointer in user.h
+    - use qh_save_qhull and qh_restore_qhull to swap the global data structure between calls.
+    - use qh_freeqhull(qh_ALL) to free intermediate convex hulls
+
+  see:
+    user_eg.c for an example
+*/
+int qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc, 
+		char *qhull_cmd, FILE *outfile, FILE *errfile) {
+  int exitcode, hulldim;
+  boolT new_ismalloc;
+  static boolT firstcall = True;
+  coordT *new_points;
+
+  if (firstcall) {
+    qh_meminit (errfile);
+    firstcall= False;
+  }
+  if (strncmp (qhull_cmd,"qhull ", 6)) {
+    fprintf (errfile, "qh_new_qhull: start qhull_cmd argument with \"qhull \"\n");
+    exit(1);
+  }
+  qh_initqhull_start (NULL, outfile, errfile);
+  trace1(( qh ferr, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
+  exitcode = setjmp (qh errexit);
+  if (!exitcode)
+  {
+    qh NOerrexit = False;
+    qh_initflags (qhull_cmd);
+    if (qh DELAUNAY)
+      qh PROJECTdelaunay= True;
+    if (qh HALFspace) {
+      /* points is an array of halfspaces, 
+         the last coordinate of each halfspace is its offset */
+      hulldim= dim-1;
+      qh_setfeasible (hulldim); 
+      new_points= qh_sethalfspace_all (dim, numpoints, points, qh feasible_point);
+      new_ismalloc= True;
+      if (ismalloc)
+	free (points);
+    }else {
+      hulldim= dim;
+      new_points= points;
+      new_ismalloc= ismalloc;
+    }
+    qh_init_B (new_points, numpoints, hulldim, new_ismalloc);
+    qh_qhull();
+    qh_check_output();
+    if (outfile)
+      qh_produce_output(); 
+    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points();
+  }
+  qh NOerrexit = True;
+  return exitcode;
+} /* new_qhull */
+
+/*---------------------------------
+  
+  qh_errexit( exitcode, facet, ridge )
+    report and exit from an error
+    report facet and ridge if non-NULL
+    reports useful information such as last point processed
+    set qh.FORCEoutput to print neighborhood of facet
+
+  see: 
+    qh_errexit2() in qhull.c for printing 2 facets
+
+  design:
+    check for error within error processing
+    compute qh.hulltime
+    print facet and ridge (if any)
+    report commandString, options, qh.furthest_id
+    print summary and statistics (including precision statistics)
+    if qh_ERRsingular
+      print help text for singular data set
+    exit program via long jump (if defined) or exit()      
+*/
+void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
+
+  if (qh ERREXITcalled) {
+    fprintf (qh ferr, "\nqhull error while processing previous error.  Exit program\n");
+    exit(1);
+  }
+  qh ERREXITcalled= True;
+  if (!qh QHULLfinished)
+    qh hulltime= qh_CPUclock - qh hulltime;
+  qh_errprint("ERRONEOUS", facet, NULL, ridge, NULL);
+  fprintf (qh ferr, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
+  fprintf(qh ferr, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
+  if (qh furthest_id >= 0) {
+    fprintf(qh ferr, "Last point added to hull was p%d.", qh furthest_id);
+    if (zzval_(Ztotmerge))
+      fprintf(qh ferr, "  Last merge was #%d.", zzval_(Ztotmerge));
+    if (qh QHULLfinished)
+      fprintf(qh ferr, "\nQhull has finished constructing the hull.");
+    else if (qh POSTmerging)
+      fprintf(qh ferr, "\nQhull has started post-merging.");
+    fprintf (qh ferr, "\n");
+  }
+  if (qh FORCEoutput && (qh QHULLfinished || (!facet && !ridge)))
+    qh_produce_output();
+  else {
+    if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh hull_dim+1) {
+      fprintf (qh ferr, "\nAt error exit:\n");
+      qh_printsummary (qh ferr);
+      if (qh PRINTstatistics) {
+	qh_collectstatistics();
+	qh_printstatistics(qh ferr, "at error exit");
+	qh_memstatistics (qh ferr);
+      }
+    }
+    if (qh PRINTprecision)
+      qh_printstats (qh ferr, qhstat precision, NULL);
+  }
+  if (!exitcode)
+    exitcode= qh_ERRqhull;
+  else if (exitcode == qh_ERRsingular)
+    qh_printhelp_singular(qh ferr);
+  else if (exitcode == qh_ERRprec && !qh PREmerge)
+    qh_printhelp_degenerate (qh ferr);
+  if (qh NOerrexit) {
+    fprintf (qh ferr, "qhull error while ending program.  Exit program\n");
+    exit(1);
+  }
+  qh NOerrexit= True;
+  longjmp(qh errexit, exitcode);
+} /* errexit */
+
+
+/*---------------------------------
+  
+  qh_errprint( fp, string, atfacet, otherfacet, atridge, atvertex )
+    prints out the information of facets and ridges to fp
+    also prints neighbors and geomview output
+    
+  notes:
+    except for string, any parameter may be NULL
+*/
+void qh_errprint(char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
+  int i;
+
+  if (atfacet) {
+    fprintf(qh ferr, "%s FACET:\n", string);
+    qh_printfacet(qh ferr, atfacet);
+  }
+  if (otherfacet) {
+    fprintf(qh ferr, "%s OTHER FACET:\n", string);
+    qh_printfacet(qh ferr, otherfacet);
+  }
+  if (atridge) {
+    fprintf(qh ferr, "%s RIDGE:\n", string);
+    qh_printridge(qh ferr, atridge);
+    if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
+      qh_printfacet(qh ferr, atridge->top);
+    if (atridge->bottom
+	&& atridge->bottom != atfacet && atridge->bottom != otherfacet)
+      qh_printfacet(qh ferr, atridge->bottom);
+    if (!atfacet)
+      atfacet= atridge->top;
+    if (!otherfacet)
+      otherfacet= otherfacet_(atridge, atfacet);
+  }
+  if (atvertex) {
+    fprintf(qh ferr, "%s VERTEX:\n", string);
+    qh_printvertex (qh ferr, atvertex);
+  }
+  if (qh fout && qh FORCEoutput && atfacet && !qh QHULLfinished && !qh IStracing) {
+    fprintf(qh ferr, "ERRONEOUS and NEIGHBORING FACETS to output\n");
+    for (i= 0; i < qh_PRINTEND; i++)  /* use fout for geomview output */
+      qh_printneighborhood (qh fout, qh PRINTout[i], atfacet, otherfacet,
+			    !qh_ALL);
+  }
+} /* errprint */
+
+
+/*---------------------------------
+  
+  qh_printfacetlist( fp, facetlist, facets, printall )
+    print all fields for a facet list and/or set of facets to fp
+    if !printall, 
+      only prints good facets
+
+  notes:
+    also prints all vertices
+*/
+void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
+  facetT *facet, **facetp;
+
+  qh_printbegin (qh ferr, qh_PRINTfacets, facetlist, facets, printall);
+  FORALLfacet_(facetlist)
+    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
+  FOREACHfacet_(facets)
+    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
+  qh_printend (qh ferr, qh_PRINTfacets, facetlist, facets, printall);
+} /* printfacetlist */
+
+
+/*---------------------------------
+  
+  qh_user_memsizes()
+    allocate up to 10 additional, quick allocation sizes
+
+  notes:
+    increase maximum number of allocations in qh_initqhull_mem()
+*/
+void qh_user_memsizes (void) {
+
+  /* qh_memsize (size); */
+} /* user_memsizes */
+

Added: trunk/scipy/spatial/qhull/src/user.h
===================================================================
--- trunk/scipy/spatial/qhull/src/user.h	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/user.h	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,762 @@
+/*
  ---------------------------------
+
+   user.h
+   user redefinable constants
+
+   see qh-user.htm.  see COPYING for copyright information.
+
+   before reading any code, review qhull.h for data structure definitions and 
+   the "qh" macro.
+*/
+
+#ifndef qhDEFuser
+#define qhDEFuser 1
+
+/*============= data types and configuration macros ==========*/
+
+/*----------------------------------
+  
+  realT
+    set the size of floating point numbers
+  
+  qh_REALdigits 
+    maximimum number of significant digits
+  
+  qh_REAL_1, qh_REAL_2n, qh_REAL_3n
+    format strings for printf
+  
+  qh_REALmax, qh_REALmin
+    maximum and minimum (near zero) values  
+  
+  qh_REALepsilon
+    machine roundoff.  Maximum roundoff error for addition and multiplication.
+    
+  notes:
+   Select whether to store floating point numbers in single precision (float)
+   or double precision (double).
+   
+   Use 'float' to save about 8% in time and 25% in space.  This is particularly
+   help if high-d where convex hulls are space limited.  Using 'float' also
+   reduces the printed size of Qhull's output since numbers have 8 digits of 
+   precision.
+   
+   Use 'double' when greater arithmetic precision is needed.  This is needed
+   for Delaunay triangulations and Voronoi diagrams when you are not merging 
+   facets.
+
+   If 'double' gives insufficient precision, your data probably includes
+   degeneracies.  If so you should use facet merging (done by default)
+   or exact arithmetic (see imprecision section of manual, qh-impre.htm).  
+   You may also use option 'Po' to force output despite precision errors.
+
+   You may use 'long double', but many format statements need to be changed
+   and you may need a 'long double' square root routine.  S. Grundmann
+   (sg at eeiwzb.et.tu-dresden.de) has done this.  He reports that the code runs 
+   much slower with little gain in precision.    
+
+   WARNING: on some machines,    int f(){realT a= REALmax;return (a == REALmax);}
+      returns False.  Use (a > REALmax/2) instead of (a == REALmax).
+
+   REALfloat =   1      all numbers are 'float' type
+             =   0      all numbers are 'double' type
+*/
+#define REALfloat 0
+
+#if (REALfloat == 1)
+#define realT float
+#define REALmax FLT_MAX
+#define REALmin FLT_MIN
+#define REALepsilon FLT_EPSILON
+#define qh_REALdigits 8   /* maximum number of significant digits */
+#define qh_REAL_1 "%6.8g "
+#define qh_REAL_2n "%6.8g %6.8g\n"
+#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
+
+#elif (REALfloat == 0)
+#define realT double
+#define REALmax DBL_MAX
+#define REALmin DBL_MIN
+#define REALepsilon DBL_EPSILON
+#define qh_REALdigits 16    /* maximum number of significant digits */
+#define qh_REAL_1 "%6.16g "
+#define qh_REAL_2n "%6.16g %6.16g\n"
+#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
+
+#else
+#error unknown float option
+#endif
+
+/*----------------------------------
+  
+  qh_CPUclock
+    define the clock() function for reporting the total time spent by Qhull
+    returns CPU ticks as a 'long int'
+    qh_CPUclock is only used for reporting the total time spent by Qhull
+
+  qh_SECticks 
+    the number of clock ticks per second
+
+  notes:
+    looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
+    to define a custom clock, set qh_CLOCKtype to 0
+
+    if your system does not use clock() to return CPU ticks, replace
+    qh_CPUclock with the corresponding function.  It is converted
+    to unsigned long to prevent wrap-around during long runs.
+   
+
+   Set qh_CLOCKtype to
+   
+     1	   	for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
+                Note:  may fail if more than 1 hour elapsed time
+
+     2	   	use qh_clock() with POSIX times() (see global.c)
+*/
+#define qh_CLOCKtype 1  /* change to the desired number */
+
+#if (qh_CLOCKtype == 1)
+
+#if defined (CLOCKS_PER_SECOND)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SECOND
+
+#elif defined (CLOCKS_PER_SEC)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SEC
+
+#elif defined (CLK_TCK)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks CLK_TCK
+
+#else
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks 1E6
+#endif
+
+#elif (qh_CLOCKtype == 2)
+#define qh_CPUclock    qh_clock()  /* return CPU clock */
+#define qh_SECticks 100
+
+#else /* qh_CLOCKtype == ? */
+#error unknown clock option
+#endif
+
+/*----------------------------------
+  
+  qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
+    define random number generator
+
+    qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.  
+    qh_RANDOMseed sets the random number seed for qh_RANDOMint
+
+  Set qh_RANDOMtype (default 5) to:
+    1       for random() with 31 bits (UCB)
+    2       for rand() with RAND_MAX or 15 bits (system 5)
+    3       for rand() with 31 bits (Sun)
+    4       for lrand48() with 31 bits (Solaris)
+    5       for qh_rand() with 31 bits (included with Qhull)
+  
+  notes:
+    Random numbers are used by rbox to generate point sets.  Random
+    numbers are used by Qhull to rotate the input ('QRn' option),
+    simulate a randomized algorithm ('Qr' option), and to simulate
+    roundoff errors ('Rn' option).
+
+    Random number generators differ between systems.  Most systems provide
+    rand() but the period varies.  The period of rand() is not critical
+    since qhull does not normally use random numbers.  
+
+    The default generator is Park & Miller's minimal standard random
+    number generator [CACM 31:1195 '88].  It is included with Qhull.
+
+    If qh_RANDOMmax is wrong, qhull will report a warning and Geomview 
+    output will likely be invisible.
+*/
+#define qh_RANDOMtype 5   /* *** change to the desired number *** */
+
+#if (qh_RANDOMtype == 1)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, random()/MAX */
+#define qh_RANDOMint random()
+#define qh_RANDOMseed_(seed) srandom(seed);
+
+#elif (qh_RANDOMtype == 2)
+#ifdef RAND_MAX
+#define qh_RANDOMmax ((realT)RAND_MAX)
+#else
+#define qh_RANDOMmax ((realT)32767)   /* 15 bits (System 5) */
+#endif
+#define qh_RANDOMint  rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+  
+#elif (qh_RANDOMtype == 3)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, Sun */
+#define qh_RANDOMint  rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+
+#elif (qh_RANDOMtype == 4)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, lrand38()/MAX */
+#define qh_RANDOMint lrand48()
+#define qh_RANDOMseed_(seed) srand48(seed);
+
+#elif (qh_RANDOMtype == 5)
+#define qh_RANDOMmax ((realT)2147483646UL)  /* 31 bits, qh_rand/MAX */
+#define qh_RANDOMint qh_rand()
+#define qh_RANDOMseed_(seed) qh_srand(seed);
+/* unlike rand(), never returns 0 */
+
+#else
+#error: unknown random option
+#endif
+
+/*----------------------------------
+  
+  qh_ORIENTclock
+    0 for inward pointing normals by Geomview convention
+*/
+#define qh_ORIENTclock 0 
+
+
+/*========= performance related constants =========*/
+
+/*----------------------------------
+  
+  qh_HASHfactor
+    total hash slots / used hash slots.  Must be at least 1.1.
+      
+  notes:
+    =2 for at worst 50% occupancy for qh hash_table and normally 25% occupancy
+*/
+#define qh_HASHfactor 2
+
+/*----------------------------------
+  
+  qh_VERIFYdirect
+    with 'Tv' verify all points against all facets if op count is smaller
+
+  notes:
+    if greater, calls qh_check_bestdist() instead
+*/
+#define qh_VERIFYdirect 1000000 
+
+/*----------------------------------
+  
+  qh_INITIALsearch
+     if qh_INITIALmax, search points up to this dimension
+*/
+#define qh_INITIALsearch 6
+
+/*----------------------------------
+  
+  qh_INITIALmax
+    if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
+      
+  notes:
+    from points with non-zero determinants
+    use option 'Qs' to override (much slower)
+*/
+#define qh_INITIALmax 8
+
+/*----------------------------------
+  
+  qh_JOGGLEdefault
+    default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
+
+  notes:
+    rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
+    rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
+    rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
+    rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
+    rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
+    rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
+    rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
+    rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
+    rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
+    the later have about 20 points per facet, each of which may interfere
+
+    pick a value large enough to avoid retries on most inputs
+*/
+#define qh_JOGGLEdefault 30000.0
+
+/*----------------------------------
+  
+  qh_JOGGLEincrease
+    factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
+*/
+#define qh_JOGGLEincrease 10.0
+
+/*----------------------------------
+  
+  qh_JOGGLEretry
+    if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
+
+  notes:
+    try twice at the original value in case of bad luck the first time
+*/
+#define qh_JOGGLEretry 2
+
+/*----------------------------------
+  
+  qh_JOGGLEagain
+    every following qh_JOGGLEagain, increase qh.JOGGLEmax
+
+  notes:
+    1 is OK since it's already failed qh_JOGGLEretry times
+*/
+#define qh_JOGGLEagain 1
+
+/*----------------------------------
+  
+  qh_JOGGLEmaxincrease
+    maximum qh.JOGGLEmax due to qh_JOGGLEincrease
+    relative to qh.MAXwidth
+
+  notes:
+    qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
+*/
+#define qh_JOGGLEmaxincrease 1e-2
+
+/*----------------------------------
+  
+  qh_JOGGLEmaxretry
+    stop after qh_JOGGLEmaxretry attempts
+*/
+#define qh_JOGGLEmaxretry 100
+
+/*========= memory constants =========*/
+
+/*----------------------------------
+  
+  qh_MEMalign
+    memory alignment for qh_meminitbuffers() in global.c
+    
+  notes:
+    to avoid bus errors, memory allocation must consider alignment requirements.
+    malloc() automatically takes care of alignment.   Since mem.c manages
+    its own memory, we need to explicitly specify alignment in
+    qh_meminitbuffers().
+
+    A safe choice is sizeof(double).  sizeof(float) may be used if doubles 
+    do not occur in data structures and pointers are the same size.  Be careful
+    of machines (e.g., DEC Alpha) with large pointers. 
+
+    If using gcc, best alignment is
+              #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
+*/
+#define qh_MEMalign fmax_(sizeof(realT), sizeof(void *))
+
+/*----------------------------------
+  
+  qh_MEMbufsize
+    size of additional memory buffers
+    
+  notes:
+    used for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMbufsize 0x10000       /* allocate 64K memory buffers */
+
+/*----------------------------------
+  
+  qh_MEMinitbuf
+    size of initial memory buffer
+    
+  notes:
+    use for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMinitbuf 0x20000      /* initially allocate 128K buffer */
+
+/*----------------------------------
+  
+  qh_INFINITE
+    on output, indicates Voronoi center at infinity
+*/
+#define qh_INFINITE  -10.101
+
+/*----------------------------------
+  
+  qh_DEFAULTbox
+    default box size (Geomview expects 0.5)
+*/
+#define qh_DEFAULTbox 0.5 
+
+/*======= conditional compilation ============================*/
+
+/*----------------------------------
+
+  __cplusplus
+    defined by C++ compilers
+
+  __MSC_VER
+    defined by Microsoft Visual C++
+  
+  __MWERKS__ && __POWERPC__
+    defined by Metrowerks when compiling for the Power Macintosh
+
+  __STDC__
+    defined for strict ANSI C 
+*/
+
+/*----------------------------------
+ 
+  qh_COMPUTEfurthest 
+    compute furthest distance to an outside point instead of storing it with the facet
+    =1 to compute furthest
+  
+  notes:
+    computing furthest saves memory but costs time
+      about 40% more distance tests for partitioning
+      removes facet->furthestdist 
+*/
+#define qh_COMPUTEfurthest 0
+                         
+/*----------------------------------
+ 
+  qh_KEEPstatistics   
+    =0 removes most of statistic gathering and reporting
+
+  notes:
+    if 0, code size is reduced by about 4%.
+*/
+#define qh_KEEPstatistics 1
+                       
+/*----------------------------------
+ 
+  qh_MAXoutside 
+    record outer plane for each facet
+    =1 to record facet->maxoutside
+  
+  notes:
+    this takes a realT per facet and slightly slows down qhull
+    it produces better outer planes for geomview output 
+*/
+#define qh_MAXoutside 1
+
+/*----------------------------------
+ 
+  qh_NOmerge
+    disables facet merging if defined
+    
+  notes:
+    This saves about 10% space.
+    
+    Unless 'Q0'
+      qh_NOmerge sets 'QJ' to avoid precision errors
+
+    #define qh_NOmerge    
+
+  see:
+    qh_NOmem in mem.c
+    
+    see user.c/user_eg.c for removing io.o
+*/  
+    
+/*----------------------------------
+ 
+  qh_NOtrace
+    no tracing if defined 
+  
+  notes:
+    This saves about 5% space.
+
+    #define qh_NOtrace
+*/    
+
+/*----------------------------------
+  
+  qh_QHpointer
+    access global data with pointer or static structure
+
+  qh_QHpointer  = 1     access globals via a pointer to allocated memory
+                        enables qh_saveqhull() and qh_restoreqhull()
+			costs about 8% in time and 2% in space
+
+		= 0     qh_qh and qh_qhstat are static data structures
+		        only one instance of qhull() can be active at a time
+			default value
+
+  notes:
+    all global variables for qhull are in qh, qhmem, and qhstat
+    qh is defined in qhull.h
+    qhmem is defined in mem.h
+    qhstat is defined in stat.h
+
+  see:
+    user_eg.c for an example
+*/
+#define qh_QHpointer 0
+#if 0  /* sample code */
+    qhT *oldqhA, *oldqhB;
+
+    exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+                      flags, outfile, errfile); 
+    /* use results from first call to qh_new_qhull */
+    oldqhA= qh_save_qhull();
+    exitcode= qh_new_qhull (dimB, numpointsB, pointsB, ismalloc,
+                      flags, outfile, errfile); 
+    /* use results from second call to qh_new_qhull */
+    oldqhB= qh_save_qhull();
+    qh_restore_qhull (&oldqhA);
+    /* use results from first call to qh_new_qhull */
+    qh_freeqhull (qh_ALL);  /* frees all memory used by first call */
+    qh_restore_qhull (&oldqhB);
+    /* use results from second call to qh_new_qhull */
+    qh_freeqhull (!qh_ALL); /* frees long memory used by second call */
+    qh_memfreeshort (&curlong, &totlong);  /* frees short memory and memory allocator */
+#endif
+
+/*----------------------------------
+ 
+  qh_QUICKhelp        
+    =1 to use abbreviated help messages, e.g., for degenerate inputs
+*/
+#define qh_QUICKhelp    0  
+
+/* ============ -merge constants- ====================
+
+   These constants effect facet merging.  You probably will not need
+   to modify these.  They effect the performance of facet merging.
+*/
+
+/*----------------------------------
+  
+  qh_DIMmergeVertex
+    max dimension for vertex merging (it is not effective in high-d)
+*/
+#define qh_DIMmergeVertex 6
+
+/*----------------------------------
+  
+  qh_DIMreduceBuild
+     max dimension for vertex reduction during build (slow in high-d)
+*/
+#define qh_DIMreduceBuild 5
+
+/*----------------------------------
+     
+  qh_BESTcentrum
+     if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
+     else, qh_findbestneighbor() tests all vertices (much better merges)
+
+  qh_BESTcentrum2
+     if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
+*/
+#define qh_BESTcentrum 20
+#define qh_BESTcentrum2 2
+
+/*----------------------------------
+  
+  qh_BESTnonconvex
+    if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
+    
+  notes:
+    It is needed because qh_findbestneighbor is slow for large facets
+*/
+#define qh_BESTnonconvex 15 
+
+/*----------------------------------
+  
+  qh_MAXnewmerges
+    if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
+     
+  notes:
+    It is needed because postmerge can merge many facets at once
+*/
+#define qh_MAXnewmerges 2
+
+/*----------------------------------
+  
+  qh_MAXnewcentrum
+    if <= dim+n vertices (n approximates the number of merges),
+      reset the centrum in qh_updatetested() and qh_mergecycle_facets()
+    
+  notes:
+    needed to reduce cost and because centrums may move too much if 
+    many vertices in high-d
+*/
+#define qh_MAXnewcentrum 5
+
+/*----------------------------------
+  
+  qh_COPLANARratio
+    for 3-d+ merging, qh.MINvisible is n*premerge_centrum
+
+  notes:
+    for non-merging, it's DISTround
+*/
+#define qh_COPLANARratio 3
+
+/*----------------------------------
+  
+  qh_DISToutside
+    When is a point clearly outside of a facet?  
+    Stops search in qh_findbestnew or qh_partitionall
+    qh_findbest uses qh.MINoutside since since it is only called if no merges.
+     
+  notes:
+    'Qf' always searches for best facet
+    if !qh.MERGING, same as qh.MINoutside. 
+    if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
+      [Note: Zdelvertextot occurs normally with interior points]
+            RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
+    When there is a sharp edge, need to move points to a
+    clearly good facet; otherwise may be lost in another partitioning.
+    if too big then O(n^2) behavior for partitioning in cone
+    if very small then important points not processed
+    Needed in qh_partitionall for
+      RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
+    Needed in qh_findbestnew for many instances of
+      RBOX 1000 s Z1 G1e-13 t | QHULL Tv
+
+  See:  
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
+     fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
+
+/*----------------------------------
+  
+  qh_RATIOnearinside
+    ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
+    qh_check_maxout().  
+  
+  notes:
+    This is overkill since do not know the correct value.
+    It effects whether 'Qc' reports all coplanar points
+    Not used for 'd' since non-extreme points are coplanar
+*/
+#define qh_RATIOnearinside 5
+
+/*----------------------------------
+  
+  qh_SEARCHdist
+    When is a facet coplanar with the best facet?  
+    qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
+
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
+      (qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
+
+/*----------------------------------
+  
+  qh_USEfindbestnew
+     Always use qh_findbestnew for qh_partitionpoint, otherwise use
+     qh_findbestnew if merged new facet or sharpnewfacets.
+  
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
+
+/*----------------------------------
+  
+  qh_WIDEcoplanar
+    n*MAXcoplanar or n*MINvisible for a WIDEfacet 
+    
+    if vertex is further than qh.WIDEfacet from the hyperplane
+    then its ridges are not counted in computing the area, and
+    the facet's centrum is frozen. 
+    
+  notes:
+   qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
+      qh_WIDEcoplanar * qh.MINvisible);
+*/
+#define qh_WIDEcoplanar 6
+
+/*----------------------------------
+  
+  qh_MAXnarrow
+    max. cosine in initial hull that sets qh.NARROWhull
+       
+  notes:
+    If qh.NARROWhull, the initial partition does not make 
+    coplanar points.  If narrow, a coplanar point can be 
+    coplanar to two facets of opposite orientations and
+    distant from the exact convex hull.
+
+    Conservative estimate.  Don't actually see problems until it is -1.0
+*/
+#define qh_MAXnarrow -0.99999999
+
+/*----------------------------------
+  
+  qh_WARNnarrow
+    max. cosine in initial hull to warn about qh.NARROWhull
+      
+  notes:
+    this is a conservative estimate.  
+    Don't actually see problems until it is -1.0.  See qh-impre.htm
+*/
+#define qh_WARNnarrow -0.999999999999999
+
+/*----------------------------------
+  
+  qh_ZEROdelaunay
+    a zero Delaunay facet occurs for input sites coplanar with their convex hull
+    the last normal coefficient of a zero Delaunay facet is within
+        qh_ZEROdelaunay * qh.ANGLEround of 0
+      
+  notes:
+    qh_ZEROdelaunay does not allow for joggled input ('QJ').
+
+    You can avoid zero Delaunay facets by surrounding the input with a box.
+
+    Use option 'PDk:-n' to explicitly define zero Delaunay facets
+      k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
+      n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
+*/
+#define qh_ZEROdelaunay 2
+
+#endif /* qh_DEFuser */
+
+
+

Added: trunk/scipy/spatial/qhull/src/user_eg.c
===================================================================
--- trunk/scipy/spatial/qhull/src/user_eg.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/user_eg.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,317 @@
+/*
  ---------------------------------
+
+  user_eg.c
+  sample code for calling qhull() from an application
+  
+  call with:
+
+     user_eg "cube/diamond options" "delaunay options" "halfspace options"
+
+  for example:
+
+     user_eg                             # return summaries
+
+     user_eg "n" "o" "Fp"                # return normals, OFF, points
+
+     user_eg "n Qt" "o" "Fp"             # triangulated cube
+
+     user_eg "QR0 p" "QR0 v p" "QR0 Fp"  # rotate input and return points
+                                         # 'v' returns Voronoi
+					 # transform is rotated for halfspaces
+
+   main() makes three runs of qhull.
+
+     1) compute the convex hull of a cube
+
+     2a) compute the Delaunay triangulation of random points
+
+     2b) find the Delaunay triangle closest to a point.
+
+     3) compute the halfspace intersection of a diamond
+
+ notes:
+ 
+   For another example, see main() in unix.c and user_eg2.c.
+   These examples, call qh_qhull() directly.  They allow
+   tighter control on the code loaded with Qhull.
+
+   For a simple C++ example, see qhull_interface.cpp
+
+   Summaries are sent to stderr if other output formats are used
+
+   compiled by 'make user_eg'
+
+   see qhull.h for data structures, macros, and user-callable functions.
+*/
+
+#include "qhull_a.h"
+
+/*-------------------------------------------------
+-internal function prototypes
+*/
+void print_summary (void);
+void makecube (coordT *points, int numpoints, int dim);
+void makeDelaunay (coordT *points, int numpoints, int dim, int seed);
+void findDelaunay (int dim);
+void makehalf (coordT *points, int numpoints, int dim);
+
+/*-------------------------------------------------
+-print_summary()
+*/
+void print_summary (void) {
+  facetT *facet;
+  int k;
+
+  printf ("\n%d vertices and %d facets with normals:\n", 
+                 qh num_vertices, qh num_facets);
+  FORALLfacets {
+    for (k=0; k < qh hull_dim; k++) 
+      printf ("%6.2g ", facet->normal[k]);
+    printf ("\n");
+  }
+}
+
+/*--------------------------------------------------
+-makecube- set points to vertices of cube
+  points is numpoints X dim
+*/
+void makecube (coordT *points, int numpoints, int dim) {
+  int j,k;
+  coordT *point;
+
+  for (j=0; jlocate a facet with qh_findbestfacet()
+*/
+void findDelaunay (int dim) {
+  int k;
+  coordT point[ 100];
+  boolT isoutside;
+  realT bestdist;
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+
+  for (k= 0; k < dim; k++) 
+    point[k]= 0.5;
+  qh_setdelaunay (dim+1, 1, point);
+  facet= qh_findbestfacet (point, qh_ALL, &bestdist, &isoutside);
+  if (facet->tricoplanar) {
+    fprintf(stderr, "findDelaunay: not implemented for triangulated, non-simplicial Delaunay regions (tricoplanar facet, f%d).\n",
+       facet->id);
+    qh_errexit (qh_ERRqhull, facet, NULL);
+  }
+  FOREACHvertex_(facet->vertices) {
+    for (k=0; k < dim; k++)
+      printf ("%5.2f ", vertex->point[k]);
+    printf ("\n");
+  }
+} /*.findDelaunay.*/
+
+/*--------------------------------------------------
+-makehalf- set points to halfspaces for a (dim)-dimensional diamond
+  points is numpoints X dim+1
+
+  each halfspace consists of dim coefficients followed by an offset
+*/
+void makehalf (coordT *points, int numpoints, int dim) {
+  int j,k;
+  coordT *point;
+
+  for (j=0; j= 2 ? argv[1] : "");
+  numpoints= SIZEcube;
+  makecube (points, numpoints, DIM);
+  for (i=numpoints; i--; )
+    rows[i]= points+dim*i;
+  qh_printmatrix (outfile, "input", rows, numpoints, dim);
+  exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+                      flags, outfile, errfile); 
+  if (!exitcode) {                  /* if no error */
+    /* 'qh facet_list' contains the convex hull */
+    print_summary();
+    FORALLfacets {
+       /* ... your code ... */
+    }
+  }
+  qh_freeqhull(!qh_ALL);                   /* free long memory  */
+  qh_memfreeshort (&curlong, &totlong);    /* free short memory and memory allocator */
+  if (curlong || totlong) 
+    fprintf (errfile, "qhull internal warning (user_eg, #1): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
+
+  /*
+    Run 2: Delaunay triangulation
+  */
+
+  printf( "\ncompute %d-d Delaunay triangulation\n", dim);
+  sprintf (flags, "qhull s d Tcv %s", argc >= 3 ? argv[2] : "");
+  numpoints= SIZEcube;
+  makeDelaunay (points, numpoints, dim, time(NULL));
+  for (i=numpoints; i--; )
+    rows[i]= points+dim*i;
+  qh_printmatrix (outfile, "input", rows, numpoints, dim);
+  exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
+                      flags, outfile, errfile); 
+  if (!exitcode) {                  /* if no error */
+    /* 'qh facet_list' contains the convex hull */
+    /* If you want a Voronoi diagram ('v') and do not request output (i.e., outfile=NULL), 
+       call qh_setvoronoi_all() after qh_new_qhull(). */
+    print_summary();
+    FORALLfacets {
+       /* ... your code ... */
+    }
+    printf( "\nfind %d-d Delaunay triangle closest to [0.5, 0.5, ...]\n", dim);
+    exitcode= setjmp (qh errexit);  
+    if (!exitcode) {
+      /* Trap Qhull errors in findDelaunay().  Without the setjmp(), Qhull
+         will exit() after reporting an error */
+      qh NOerrexit= False;
+      findDelaunay (DIM);
+    }
+    qh NOerrexit= True;
+  }
+#if qh_QHpointer  /* see user.h */
+  {
+    qhT *oldqhA, *oldqhB;
+    coordT pointsB[DIM*TOTpoints]; /* array of coordinates for each point */
+
+
+    printf( "\nsave first triangulation and compute a new triangulation\n");
+    oldqhA= qh_save_qhull();
+    sprintf (flags, "qhull s d Tcv %s", argc >= 3 ? argv[2] : "");
+    numpoints= SIZEcube;
+    makeDelaunay (pointsB, numpoints, dim, time(NULL)+1);
+    for (i=numpoints; i--; )
+      rows[i]= pointsB+dim*i;
+    qh_printmatrix (outfile, "input", rows, numpoints, dim);
+    exitcode= qh_new_qhull (dim, numpoints, pointsB, ismalloc,
+                      flags, outfile, errfile); 
+    if (!exitcode)
+      print_summary();
+    printf( "\nsave second triangulation and restore first one\n");
+    oldqhB= qh_save_qhull();
+    qh_restore_qhull (&oldqhA);
+    print_summary();
+    printf( "\nfree first triangulation and restore second one.\n");
+    qh_freeqhull (qh_ALL);               /* free short and long memory used by first call */
+			                 /* do not use qh_memfreeshort */
+    qh_restore_qhull (&oldqhB);
+    print_summary();
+  }
+#endif
+  qh_freeqhull(!qh_ALL);                 /* free long memory */
+  qh_memfreeshort (&curlong, &totlong);  /* free short memory and memory allocator */
+  if (curlong || totlong) 
+    fprintf (errfile, "qhull internal warning (user_eg, #2): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
+
+  /*
+    Run 3: halfspace intersection about the origin
+  */
+  printf( "\ncompute halfspace intersection about the origin for a diamond\n");
+  sprintf (flags, "qhull H0 s Tcv %s", argc >= 4 ? argv[3] : "Fp");
+  numpoints= SIZEcube;
+  makehalf (points, numpoints, dim);
+  for (i=numpoints; i--; )
+    rows[i]= points+(dim+1)*i;
+  qh_printmatrix (outfile, "input as halfspace coefficients + offsets", rows, numpoints, dim+1);
+  /* use qh_sethalfspace_all to transform the halfspaces yourself.  
+     If so, set 'qh feasible_point and do not use option 'Hn,...' [it would retransform the halfspaces]
+  */
+  exitcode= qh_new_qhull (dim+1, numpoints, points, ismalloc,
+                      flags, outfile, errfile); 
+  if (!exitcode) 
+    print_summary();
+  qh_freeqhull (!qh_ALL);
+  qh_memfreeshort (&curlong, &totlong);
+  if (curlong || totlong)  /* could also check previous runs */
+    fprintf (stderr, "qhull internal warning (user_eg, #3): did not free %d bytes of long memory (%d pieces)\n",
+       totlong, curlong);
+  return exitcode;
+} /* main */
+

Added: trunk/scipy/spatial/qhull/src/user_eg2.c
===================================================================
--- trunk/scipy/spatial/qhull/src/user_eg2.c	                        (rev 0)
+++ trunk/scipy/spatial/qhull/src/user_eg2.c	2010-08-31 21:54:55 UTC (rev 6652)
@@ -0,0 +1,542 @@
+/*
  ---------------------------------
+
+  user_eg2.c
+
+  sample code for calling qhull() from an application.
+
+  See user_eg.c for a simpler method using qh_new_qhull().
+  The method used here and in unix.c gives you additional
+  control over Qhull. 
+  
+  call with:
+
+     user_eg2 "triangulated cube/diamond options" "delaunay options" "halfspace options"
+
+  for example:
+
+     user_eg2                             # return summaries
+
+     user_eg2 "n" "o" "Fp"                # return normals, OFF, points
+
+     user_eg2 "QR0 p" "QR0 v p" "QR0 Fp"  # rotate input and return points
+                                         # 'v' returns Voronoi
+					 # transform is rotated for halfspaces
+
+   main() makes three runs of qhull.
+
+     1) compute the convex hull of a cube, and incrementally add a diamond
+
+     2a) compute the Delaunay triangulation of random points, and add points.
+
+     2b) find the Delaunay triangle closest to a point.
+
+     3) compute the halfspace intersection of a diamond, and add a cube
+
+ notes:
+ 
+   summaries are sent to stderr if other output formats are used
+
+   derived from unix.c and compiled by 'make user_eg2'
+
+   see qhull.h for data structures, macros, and user-callable functions.
+   
+   If you want to control all output to stdio and input to stdin,
+   set the #if below to "1" and delete all lines that contain "io.c".  
+   This prevents the loading of io.o.  Qhull will
+   still write to 'qh ferr' (stderr) for error reporting and tracing.
+
+   Defining #if 1, also prevents user.o from being loaded.
+*/
+
+#include "qhull_a.h"
+
+/*-------------------------------------------------
+-internal function prototypes
+*/
+void print_summary (void);
+void makecube (coordT *points, int numpoints, int dim);
+void adddiamond (coordT *points, int numpoints, int numnew, int dim);
+void makeDelaunay (coordT *points, int numpoints, int dim);
+void addDelaunay (coordT *points, int numpoints, int numnew, int dim);
+void findDelaunay (int dim);
+void makehalf (coordT *points, int numpoints, int dim);
+void addhalf (coordT *points, int numpoints, int numnew, int dim, coordT *feasible);
+
+/*-------------------------------------------------
+-print_summary()
+*/
+void print_summary (void) {
+  facetT *facet;
+  int k;
+
+  printf ("\n%d vertices and %d facets with normals:\n", 
+                 qh num_vertices, qh num_facets);
+  FORALLfacets {
+    for (k=0; k < qh hull_dim; k++) 
+      printf ("%6.2g ", facet->normal[k]);
+    printf ("\n");
+  }
+}
+
+/*--------------------------------------------------
+-makecube- set points to vertices of cube
+  points is numpoints X dim
+*/
+void makecube (coordT *points, int numpoints, int dim) {
+  int j,k;
+  coordT *point;
+
+  for (j=0; jlocate a facet with qh_findbestfacet()
+*/
+void findDelaunay (int dim) {
+  int k;
+  coordT point[ 100];
+  boolT isoutside;
+  realT bestdist;
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+
+  for (k= 0; k < dim-1; k++) 
+    point[k]= 0.5;
+  qh_setdelaunay (dim, 1, point);
+  facet= qh_findbestfacet (point, qh_ALL, &bestdist, &isoutside);
+  if (facet->tricoplanar) {
+    fprintf(stderr, "findDelaunay: not implemented for triangulated, non-simplicial Delaunay regions (tricoplanar facet, f%d).\n",
+       facet->id);
+    qh_errexit (qh_ERRqhull, facet, NULL);
+  }
+  FOREACHvertex_(facet->vertices) {
+    for (k=0; k < dim-1; k++)
+      printf ("%5.2f ", vertex->point[k]);
+    printf ("\n");
+  }
+} /*.findDelaunay.*/
+
+/*--------------------------------------------------
+-makehalf- set points to halfspaces for a (dim)-d diamond
+  points is numpoints X dim+1
+
+  each halfspace consists of dim coefficients followed by an offset
+*/
+void makehalf (coordT *points, int numpoints, int dim) {
+  int j,k;
+  coordT *point;
+
+  for (j=0; j= 2 ? argv[1] : "");
+    qh_initflags (options);
+    printf( "\ncompute triangulated convex hull of cube after rotating input\n");
+    makecube (array[0], SIZEcube, DIM);
+    qh_init_B (array[0], SIZEcube, DIM, ismalloc);
+    qh_qhull();
+    qh_check_output();
+    qh_triangulate();  /* requires option 'Q11' if want to add points */ 
+    print_summary ();
+    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points ();
+    printf( "\nadd points in a diamond\n");
+    adddiamond (array[0], SIZEcube, SIZEdiamond, DIM);
+    qh_check_output();
+    print_summary (); 
+    qh_produce_output();  /* delete this line to help avoid io.c */
+    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points ();
+  }
+  qh NOerrexit= True;
+  qh_freeqhull (!qh_ALL);
+  qh_memfreeshort (&curlong, &totlong);
+  /*
+    Run 2: Delaunay triangulation
+  */
+  qh_init_A (stdin, stdout, stderr, 0, NULL);
+  exitcode= setjmp (qh errexit);
+  if (!exitcode) {
+    coordT array[TOTpoints][DIM];
+
+    strcat (qh rbox_command, "user_eg Delaunay");
+    sprintf (options, "qhull s d Tcv %s", argc >= 3 ? argv[2] : "");
+    qh_initflags (options);
+    printf( "\ncompute %d-d Delaunay triangulation\n", DIM-1);
+    makeDelaunay (array[0], SIZEcube, DIM);
+    /* Instead of makeDelaunay with qh_setdelaunay, you may
+       produce a 2-d array of points, set DIM to 2, and set 
+       qh PROJECTdelaunay to True.  qh_init_B will call 
+       qh_projectinput to project the points to the paraboloid
+       and add a point "at-infinity".
+    */
+    qh_init_B (array[0], SIZEcube, DIM, ismalloc);
+    qh_qhull();
+    /* If you want Voronoi ('v') without qh_produce_output(), call
+       qh_setvoronoi_all() after qh_qhull() */
+    qh_check_output();
+    print_summary ();
+    qh_produce_output();  /* delete this line to help avoid io.c */
+    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points ();
+    printf( "\nadd points to triangulation\n");
+    addDelaunay (array[0], SIZEcube, SIZEdiamond, DIM); 
+    qh_check_output();
+    qh_produce_output();  /* delete this line to help avoid io.c */
+    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points ();
+    printf( "\nfind Delaunay triangle closest to [0.5, 0.5, ...]\n");
+    findDelaunay (DIM);
+  }
+  qh NOerrexit= True;
+  qh_freeqhull (!qh_ALL);
+  qh_memfreeshort (&curlong, &totlong);
+  /*
+    Run 3: halfspace intersection
+  */
+  qh_init_A (stdin, stdout, stderr, 0, NULL);
+  exitcode= setjmp (qh errexit);
+  if (!exitcode) {
+    coordT array[TOTpoints][DIM+1];  /* +1 for halfspace offset */
+    pointT *points;
+
+    strcat (qh rbox_command, "user_eg halfspaces");
+    sprintf (options, "qhull H0 s Tcv %s", argc >= 4 ? argv[3] : "");
+    qh_initflags (options);
+    printf( "\ncompute halfspace intersection about the origin for a diamond\n");
+    makehalf (array[0], SIZEcube, DIM);
+    qh_setfeasible (DIM); /* from io.c, sets qh feasible_point from 'Hn,n' */
+    /* you may malloc and set qh feasible_point directly.  It is only used for
+       option 'Fp' */
+    points= qh_sethalfspace_all ( DIM+1, SIZEcube, array[0], qh feasible_point); 
+    qh_init_B (points, SIZEcube, DIM, True); /* qh_freeqhull frees points */
+    qh_qhull();
+    qh_check_output();
+    qh_produce_output();  /* delete this line to help avoid io.c */
+    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points ();
+    printf( "\nadd halfspaces for cube to intersection\n");
+    addhalf (array[0], SIZEcube, SIZEdiamond, DIM, qh feasible_point); 
+    qh_check_output();
+    qh_produce_output();  /* delete this line to help avoid io.c */
+    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points ();
+  }
+  qh NOerrexit= True;
+  qh NOerrexit= True;
+  qh_freeqhull (!qh_ALL);
+  qh_memfreeshort (&curlong, &totlong);
+  if (curlong || totlong)  /* could also check previous runs */
+    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
+       totlong, curlong);
+  return exitcode;
+} /* main */
+
+#if 1    /* use 1 to prevent loading of io.o and user.o */
+/*-------------------------------------------
+-errexit- return exitcode to system after an error
+  assumes exitcode non-zero
+  prints useful information
+  see qh_errexit2() in qhull.c for 2 facets
+*/
+void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
+
+  if (qh ERREXITcalled) {
+    fprintf (qh ferr, "qhull error while processing previous error.  Exit program\n");
+    exit(1);
+  }
+  qh ERREXITcalled= True;
+  if (!qh QHULLfinished)
+    qh hulltime= (unsigned)clock() - qh hulltime;
+  fprintf (qh ferr, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
+  fprintf(qh ferr, "Options selected:\n%s\n", qh qhull_options);
+  if (qh furthest_id >= 0) {
+    fprintf(qh ferr, "\nLast point added to hull was p%d", qh furthest_id);
+    if (zzval_(Ztotmerge))
+      fprintf(qh ferr, "  Last merge was #%d.", zzval_(Ztotmerge));
+    if (qh QHULLfinished)
+      fprintf(qh ferr, "\nQhull has finished constructing the hull.");
+    else if (qh POSTmerging)
+      fprintf(qh ferr, "\nQhull has started post-merging");
+    fprintf(qh ferr, "\n\n");
+  }
+  if (qh NOerrexit) {
+    fprintf (qh ferr, "qhull error while ending program.  Exit program\n");
+    exit(1);
+  }
+  if (!exitcode)
+    exitcode= qh_ERRqhull;
+  qh NOerrexit= True;
+  longjmp(qh errexit, exitcode);
+} /* errexit */
+
+
+/*-------------------------------------------
+-errprint- prints out the information of the erroneous object
+    any parameter may be NULL, also prints neighbors and geomview output
+*/
+void qh_errprint(char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
+
+  fprintf (qh ferr, "%s facets f%d f%d ridge r%d vertex v%d\n",
+	   string, getid_(atfacet), getid_(otherfacet), getid_(atridge),
+	   getid_(atvertex));
+} /* errprint */
+
+
+void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
+  facetT *facet, **facetp;
+
+  /* remove these calls to help avoid io.c */
+  qh_printbegin (qh ferr, qh_PRINTfacets, facetlist, facets, printall);/*io.c*/
+  FORALLfacet_(facetlist)                                              /*io.c*/
+    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);          /*io.c*/
+  FOREACHfacet_(facets)                                                /*io.c*/
+    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);          /*io.c*/
+  qh_printend (qh ferr, qh_PRINTfacets, facetlist, facets, printall);  /*io.c*/
+
+  FORALLfacet_(facetlist)
+    fprintf( qh ferr, "facet f%d\n", facet->id);
+} /* printfacetlist */
+
+
+
+/*-----------------------------------------
+-user_memsizes- allocate up to 10 additional, quick allocation sizes
+*/
+void qh_user_memsizes (void) {
+
+  /* qh_memsize (size); */
+} /* user_memsizes */
+
+#endif