From 04da0ca3c042f6a94ee3888617ebc8dc3b65cb59 Mon Sep 17 00:00:00 2001 From: Hans Stephensen <arngorf@gmail.com> Date: Sun, 19 Dec 2021 15:00:14 +0100 Subject: [PATCH] added c++ code and swig interface for python --- .../NeighbourhoodTetMeshIntegrator.i | 36 + .../NeighbourhoodTetMeshIntegrator.py | 104 + .../TetMeshIntegrator.py | 16 + .../_NeighbourhoodTetMeshIntegrator.so | Bin 0 -> 132064 bytes .../__init__.py | 1 + .../c_NeighbourhoodTetMeshIntegrator.cpp | 469 +++ .../c_NeighbourhoodTetMeshIntegrator.h | 15 + cpp/NeighbourhoodTetMeshIntegrator/numpy.i | 3183 +++++++++++++++++ cpp/NeighbourhoodTetMeshIntegrator/swig_it | 4 + .../NeighbourhoodTriMeshIntegrator.i | 48 + .../NeighbourhoodTriMeshIntegrator.py | 68 + .../TriMeshIntegrator.py | 16 + .../_NeighbourhoodTriMeshIntegrator.so | Bin 0 -> 134832 bytes .../__init__.py | 1 + .../c_NeighbourhoodTriMeshIntegrator.cpp | 327 ++ .../c_NeighbourhoodTriMeshIntegrator.h | 15 + cpp/NeighbourhoodTriMeshIntegrator/numpy.i | 3183 +++++++++++++++++ cpp/NeighbourhoodTriMeshIntegrator/swig_it | 4 + examples.py | 2 +- 19 files changed, 7491 insertions(+), 1 deletion(-) create mode 100644 cpp/NeighbourhoodTetMeshIntegrator/NeighbourhoodTetMeshIntegrator.i create mode 100644 cpp/NeighbourhoodTetMeshIntegrator/NeighbourhoodTetMeshIntegrator.py create mode 100644 cpp/NeighbourhoodTetMeshIntegrator/TetMeshIntegrator.py create mode 100755 cpp/NeighbourhoodTetMeshIntegrator/_NeighbourhoodTetMeshIntegrator.so create mode 100644 cpp/NeighbourhoodTetMeshIntegrator/__init__.py create mode 100644 cpp/NeighbourhoodTetMeshIntegrator/c_NeighbourhoodTetMeshIntegrator.cpp create mode 100644 cpp/NeighbourhoodTetMeshIntegrator/c_NeighbourhoodTetMeshIntegrator.h create mode 100644 cpp/NeighbourhoodTetMeshIntegrator/numpy.i create mode 100644 cpp/NeighbourhoodTetMeshIntegrator/swig_it create mode 100644 cpp/NeighbourhoodTriMeshIntegrator/NeighbourhoodTriMeshIntegrator.i create mode 100644 cpp/NeighbourhoodTriMeshIntegrator/NeighbourhoodTriMeshIntegrator.py create mode 100644 cpp/NeighbourhoodTriMeshIntegrator/TriMeshIntegrator.py create mode 100755 cpp/NeighbourhoodTriMeshIntegrator/_NeighbourhoodTriMeshIntegrator.so create mode 100644 cpp/NeighbourhoodTriMeshIntegrator/__init__.py create mode 100644 cpp/NeighbourhoodTriMeshIntegrator/c_NeighbourhoodTriMeshIntegrator.cpp create mode 100644 cpp/NeighbourhoodTriMeshIntegrator/c_NeighbourhoodTriMeshIntegrator.h create mode 100644 cpp/NeighbourhoodTriMeshIntegrator/numpy.i create mode 100644 cpp/NeighbourhoodTriMeshIntegrator/swig_it diff --git a/cpp/NeighbourhoodTetMeshIntegrator/NeighbourhoodTetMeshIntegrator.i b/cpp/NeighbourhoodTetMeshIntegrator/NeighbourhoodTetMeshIntegrator.i new file mode 100644 index 0000000..d62c696 --- /dev/null +++ b/cpp/NeighbourhoodTetMeshIntegrator/NeighbourhoodTetMeshIntegrator.i @@ -0,0 +1,36 @@ +%module NeighbourhoodTetMeshIntegrator + +%{ +#define SWIG_FILE_WITH_INIT +#include "c_NeighbourhoodTetMeshIntegrator.h" +%} + +%include "numpy.i" + +%init %{ +import_array(); +%} + +%apply (double* INPLACE_ARRAY2, int DIM1, int DIM2) { + (double * verts, int num_verts, int d1) +}; + +%apply (long* INPLACE_ARRAY2, int DIM1, int DIM2) { + (const long * const elements, int num_elements, int d2) +}; + +%apply (double* INPLACE_ARRAY1, int DIM1) { + (double * dists, int num_dists), + (const double * const x, int num_x), + (double * y_volume, int num_y1), + (double * y_area, int num_y2) +}; + +void NeighbourhoodTetMeshIntegrator( + double * verts, int num_verts, int d1, + const long * const elements, int num_elements, int d2, + double * dists, int num_dists, + const double * const x, int num_x, + double * y_volume, int num_y1, + double * y_area, int num_y2 + ); \ No newline at end of file diff --git a/cpp/NeighbourhoodTetMeshIntegrator/NeighbourhoodTetMeshIntegrator.py b/cpp/NeighbourhoodTetMeshIntegrator/NeighbourhoodTetMeshIntegrator.py new file mode 100644 index 0000000..9a06a83 --- /dev/null +++ b/cpp/NeighbourhoodTetMeshIntegrator/NeighbourhoodTetMeshIntegrator.py @@ -0,0 +1,104 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 3.0.12 +# +# Do not make changes to this file unless you know what you are doing--modify +# the SWIG interface file instead. + +from sys import version_info as _swig_python_version_info +if _swig_python_version_info >= (2, 7, 0): + def swig_import_helper(): + import importlib + pkg = __name__.rpartition('.')[0] + mname = '.'.join((pkg, '_NeighbourhoodTetMeshIntegrator')).lstrip('.') + try: + return importlib.import_module(mname) + except ImportError: + return importlib.import_module('_NeighbourhoodTetMeshIntegrator') + _NeighbourhoodTetMeshIntegrator = swig_import_helper() + del swig_import_helper +elif _swig_python_version_info >= (2, 6, 0): + def swig_import_helper(): + from os.path import dirname + import imp + fp = None + try: + fp, pathname, description = imp.find_module('_NeighbourhoodTetMeshIntegrator', [dirname(__file__)]) + except ImportError: + import _NeighbourhoodTetMeshIntegrator + return _NeighbourhoodTetMeshIntegrator + try: + _mod = imp.load_module('_NeighbourhoodTetMeshIntegrator', fp, pathname, description) + finally: + if fp is not None: + fp.close() + return _mod + _NeighbourhoodTetMeshIntegrator = swig_import_helper() + del swig_import_helper +else: + import _NeighbourhoodTetMeshIntegrator +del _swig_python_version_info + +try: + _swig_property = property +except NameError: + pass # Python < 2.2 doesn't have 'property'. + +try: + import builtins as __builtin__ +except ImportError: + import __builtin__ + +def _swig_setattr_nondynamic(self, class_type, name, value, static=1): + if (name == "thisown"): + return self.this.own(value) + if (name == "this"): + if type(value).__name__ == 'SwigPyObject': + self.__dict__[name] = value + return + method = class_type.__swig_setmethods__.get(name, None) + if method: + return method(self, value) + if (not static): + if _newclass: + object.__setattr__(self, name, value) + else: + self.__dict__[name] = value + else: + raise AttributeError("You cannot add attributes to %s" % self) + + +def _swig_setattr(self, class_type, name, value): + return _swig_setattr_nondynamic(self, class_type, name, value, 0) + + +def _swig_getattr(self, class_type, name): + if (name == "thisown"): + return self.this.own() + method = class_type.__swig_getmethods__.get(name, None) + if method: + return method(self) + raise AttributeError("'%s' object has no attribute '%s'" % (class_type.__name__, name)) + + +def _swig_repr(self): + try: + strthis = "proxy of " + self.this.__repr__() + except __builtin__.Exception: + strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + +try: + _object = object + _newclass = 1 +except __builtin__.Exception: + class _object: + pass + _newclass = 0 + + +def NeighbourhoodTetMeshIntegrator(verts, elements, dists, x, y_volume, y_area): + return _NeighbourhoodTetMeshIntegrator.NeighbourhoodTetMeshIntegrator(verts, elements, dists, x, y_volume, y_area) +NeighbourhoodTetMeshIntegrator = _NeighbourhoodTetMeshIntegrator.NeighbourhoodTetMeshIntegrator +# This file is compatible with both classic and new-style classes. + + diff --git a/cpp/NeighbourhoodTetMeshIntegrator/TetMeshIntegrator.py b/cpp/NeighbourhoodTetMeshIntegrator/TetMeshIntegrator.py new file mode 100644 index 0000000..a7700c0 --- /dev/null +++ b/cpp/NeighbourhoodTetMeshIntegrator/TetMeshIntegrator.py @@ -0,0 +1,16 @@ +import numpy as np + +from .NeighbourhoodTetMeshIntegrator import NeighbourhoodTetMeshIntegrator + +def TetMeshIntegrator(verts, elements, dists, x): + verts = verts.astype(np.float64) + elements = elements.astype(np.int64) + dists = dists.astype(np.float64) + x = x.astype(np.float64) + + y_volume = np.empty(x.shape, dtype=np.float64) + y_area = np.empty(x.shape, dtype=np.float64) + + NeighbourhoodTetMeshIntegrator(verts, elements, dists, x, y_volume, y_area) + + return y_volume, y_area \ No newline at end of file diff --git a/cpp/NeighbourhoodTetMeshIntegrator/_NeighbourhoodTetMeshIntegrator.so b/cpp/NeighbourhoodTetMeshIntegrator/_NeighbourhoodTetMeshIntegrator.so new file mode 100755 index 0000000000000000000000000000000000000000..5acff1cf18fa7944f16a5d60eb86e266cc9e84ae GIT binary patch literal 132064 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 T44Z!6-w+oHKq$B-G%f=GBsu^` literal 0 HcmV?d00001 diff --git a/cpp/NeighbourhoodTetMeshIntegrator/__init__.py b/cpp/NeighbourhoodTetMeshIntegrator/__init__.py new file mode 100644 index 0000000..8612953 --- /dev/null +++ b/cpp/NeighbourhoodTetMeshIntegrator/__init__.py @@ -0,0 +1 @@ +from .TetMeshIntegrator import TetMeshIntegrator \ No newline at end of file diff --git a/cpp/NeighbourhoodTetMeshIntegrator/c_NeighbourhoodTetMeshIntegrator.cpp b/cpp/NeighbourhoodTetMeshIntegrator/c_NeighbourhoodTetMeshIntegrator.cpp new file mode 100644 index 0000000..0b1e710 --- /dev/null +++ b/cpp/NeighbourhoodTetMeshIntegrator/c_NeighbourhoodTetMeshIntegrator.cpp @@ -0,0 +1,469 @@ +#include "c_NeighbourhoodTetMeshIntegrator.h" +#include <cmath> +#include <algorithm> +#include <iostream> +#include <boost/numeric/ublas/matrix.hpp> +#include <boost/numeric/ublas/vector.hpp> +#include <boost/numeric/ublas/lu.hpp> +#include <boost/numeric/ublas/io.hpp> + +#define TOL 1e-10 + +void copy_verts(const double * const verts, const long * const v_indices, double * t_verts, const int * const ordering) +{ + for (int j = 0; j < 4; ++j) + { + long vn = v_indices[ordering[j]]; + for (int i = 0; i < 3; ++i) + { + t_verts[3*j + i] = verts[3*vn + i]; + } + } +} + +void get_sorted_indices(double * dists, int * ordering) +{ + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3-i; ++j) // not sure about this, verify with web for bubblesort + { + if (dists[j] > dists[j+1]) { + std::swap(dists[j], dists[j+1]); + std::swap(ordering[j], ordering[j+1]); + } + } +} + +void rotx(double & vy, double & vz, const double t) +{ + const double ct = std::cos(t); + const double st = std::sin(t); + + const double tmp_vz = vy * st + vz * ct; + + vy = vy * ct - vz * st; + vz = tmp_vz; +} + +void roty(double & vx, double & vz, const double t) +{ + const double ct = std::cos(t); + const double st = std::sin(t); + + const double tmp_vz = ct * vz - st * vx; + + vx = vx * ct + st * vz; + vz = tmp_vz; +} + +void rotz(double & vx, double & vy, const double t) +{ + const double ct = std::cos(t); + const double st = std::sin(t); + + const double tmp_vy = vx * st + vy * ct; + + vx = vx * ct - vy * st; + vy = tmp_vy; +} + +void get_linear_params(const double * const verts, const double * const dists, double &a, double &b, double &c) +{ + using namespace boost::numeric::ublas; + + matrix<double> A(4,4); + vector<double> v(4); + + for (unsigned i = 0; i < 4; ++i) { + v(i) = dists[i]; + for (unsigned j = 0; j < 4; ++j) { + if (j < 3) A(i, j) = verts[i*3 + j]; + else A(i, j) = 1.0; + } + } + + permutation_matrix<size_t> pm(4); + + int singular = lu_factorize(A, pm); + + if (singular) { + a=0; b=0; c=0; // This is not my favorite solution, but it is caught later down the line + return; + } + + lu_substitute(A, pm, v); + + a = v(0); + b = v(1); + c = v(2); +} + +double full_tri_area(const double * const verts) +{ + // cross product and multiply by last vector + double a[3] = {verts[3] - verts[0], verts[4] - verts[1], verts[5] - verts[2]}; + double b[3] = {verts[6] - verts[0], verts[7] - verts[1], verts[8] - verts[2]}; + double cx = a[1] * b[2] - b[1] * a[2]; + double cy = b[0] * a[2] - a[0] * b[2]; + double cz = a[0] * b[1] - b[0] * a[1]; + + return std::sqrt(cx*cx + cy*cy + cz*cz) / 2.0; +} + +double full_tet_volume(const double * const verts) +{ + // cross product and multiply by last vector + double a[3] = {verts[3] - verts[0], verts[4] - verts[1], verts[5] - verts[2]}; + double b[3] = {verts[6] - verts[0], verts[7] - verts[1], verts[8] - verts[2]}; + double c[3] = {verts[9] - verts[0], verts[10] - verts[1], verts[11] - verts[2]}; + double cm_x = (b[1] * c[2] - c[1] * b[2]) * a[0]; + double cm_y = (c[0] * b[2] - b[0] * c[2]) * a[1]; + double cm_z = (b[0] * c[1] - c[0] * b[1]) * a[2]; + + return std::abs(cm_x + cm_y + cm_z) / 6.0; +} + +void transform_tet(double * verts, double * dists, double & scale) // 9, 3 +{ + // Normalize so first vertice is at the origin + for (int j = 1; j < 4; ++j) + for (int i = 0; i < 3; ++i) + verts[j*3 + i] -= verts[i]; + + for (int i = 0; i < 3; ++i) + verts[i] = 0; + + double a, b, c; + get_linear_params(verts, dists, a, b, c); + + double gradient_norm = std::sqrt(a*a + b*b + c*c); + scale = gradient_norm; + + double t; + + t = -std::atan2(c, b); + + for (int i = 1; i < 4; ++i) + { + // rotx (x is unchanged, rot y and z) + rotx(verts[i*3+1], verts[i*3+2], t); + } + rotx(b, c, t); + + t = -std::atan2(b, a); + + for (int i = 1; i < 4; ++i) + { + // rotz (z is unchanged, rot x and y) + rotz(verts[i*3], verts[i*3+1], t); + } + + // Scale to h scale + for (int i = 0; i < 4; ++i) + { + verts[i*3] = verts[i*3] * gradient_norm + dists[0]; + } +} + +void h_midpoint(const double * const p0, const double * const p1, const double h, double * p01) +{ + double K[3] = {p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]}; + + double h0 = p0[0]; + double h1 = p1[0]; + double a = h0; + double b = 1.0/(h1 - h0); + + for (int i = 0; i < 3; ++i) + { + p01[i] = p0[i] + K[i]*(h - a)*b; + } +} + +double volume_fast(const double * const v0, const double * const v1, + const double * const v2, const double * const v3, + const double h) +{ + double p01[3]; + h_midpoint(v0, v1, h, p01); + double p02[3]; + h_midpoint(v0, v2, h, p02); + double p03[3]; + h_midpoint(v0, v3, h, p03); + double p12[3]; + h_midpoint(v1, v2, h, p12); + double p13[3]; + h_midpoint(v1, v3, h, p13); + + double P_tet1[12] = { v0[0], v0[1], v0[2], + p01[0], p01[1], p01[2], + p02[0], p02[1], p02[2], + p03[0], p03[1], p03[2]}; + + double P_tet2[12] = { v1[0], v1[1], v1[2], + p01[0], p01[1], p01[2], + p12[0], p12[1], p12[2], + p13[0], p13[1], p13[2]}; + + double volume_1 = full_tet_volume(P_tet1); + double volume_2 = full_tet_volume(P_tet2); + + return volume_1 - volume_2; +} + +double volume_safe(const double * const v0, const double * const v1, + const double * const v2, const double * const v3, + const double h) +{ + double p02[3]; + h_midpoint(v0, v2, h, p02); + double p03[3]; + h_midpoint(v0, v3, h, p03); + double p12[3]; + h_midpoint(v1, v2, h, p12); + double p13[3]; + h_midpoint(v1, v3, h, p13); + + double P_tet1[12] = { v0[0], v0[1], v0[2], + p02[0], p02[1], p02[2], + p03[0], p03[1], p03[2], + p12[0], p12[1], p12[2]}; + + double P_tet2[12] = { v0[0], v0[1], v0[2], + p03[0], p03[1], p03[2], + p12[0], p12[1], p12[2], + p13[0], p13[1], p13[2]}; + + double P_tet3[12] = { v0[0], v0[1], v0[2], + v1[0], v1[1], v1[2], + p12[0], p12[1], p12[2], + p13[0], p13[1], p13[2]}; + + double volume_1 = full_tet_volume(P_tet1); + double volume_2 = full_tet_volume(P_tet2); + double volume_3 = full_tet_volume(P_tet3); + + return volume_1 + volume_2 + volume_3; +} + +double sliced_tet_volume(const double * const verts, const double full_volume, const int i, double h) +{ + double v0[3] = {verts[i*12 + 0], verts[i*12 + 1], verts[i*12 + 2]}; + double v1[3] = {verts[i*12 + 3], verts[i*12 + 4], verts[i*12 + 5]}; + double v2[3] = {verts[i*12 + 6], verts[i*12 + 7], verts[i*12 + 8]}; + double v3[3] = {verts[i*12 + 9], verts[i*12 + 10], verts[i*12 + 11]}; + + if (h <= v0[0]) { + // VOL 0 + return 0.0; + } else if (h <= v1[0]) { + // VOL 1 + + double p01[3]; + double p02[3]; + double p03[3]; + + h_midpoint(v0, v1, h, p01); + h_midpoint(v0, v2, h, p02); + h_midpoint(v0, v3, h, p03); + + double P[12] = { v0[0], v0[1], v0[2], + p01[0], p01[1], p01[2], + p02[0], p02[1], p02[2], + p03[0], p03[1], p03[2]}; + + double volume = full_tet_volume(P); + + if (std::isnan(volume)) + { + std::cout << "NAN in volume (case 1) on " << P << " " << h << std::endl; + } + + return volume; + + } else if (h <= v2[0]) { + // VOL 2 + if (std::abs(v0[0] - v1[0]) < TOL) { + // Degenerate case + double volume = volume_safe(v0, v1, v2, v3, h); + if (std::isnan(volume)) + { + std::cout << "NAN in volume_safe on " << v0 << " " << v1 << " " << v2 << " " << v3 << " " << h << std::endl; + } + return volume; + } else { + // Non-degenerate case + double volume = volume_fast(v0, v1, v2, v3, h); + if (std::isnan(volume)) + { + std::cout << "NAN in volume_fast on " << v0 << " " << v1 << " " << v2 << " " << v3 << " " << h << std::endl; + } + return volume; + } + } else if (h <= v3[0]) { + // VOL 3 + double p03[3]; + double p13[3]; + double p23[3]; + + h_midpoint(v0, v3, h, p03); + h_midpoint(v1, v3, h, p13); + h_midpoint(v2, v3, h, p23); + + double P_remaining[12] = { v3[0], v3[1], v3[2], + p03[0], p03[1], p03[2], + p13[0], p13[1], p13[2], + p23[0], p23[1], p23[2]}; + + double volume_remaining = full_tet_volume(P_remaining); + if (std::isnan(volume_remaining)) + { + std::cout << "NAN in volume_remaining on " << P_remaining << " " << h << std::endl; + } + if (std::isnan(full_volume)) + { + std::cout << "NAN in full_volume on " << v0 << " " << v1 << " " << v2 << " " << v3 << " " << h << std::endl; + } + return full_volume - volume_remaining; + } else { + // VOL 4 + return full_volume; + } +} + +double sliced_tet_area(const double * const verts, const int i, double h) +{ + double v0[3] = {verts[i*12 + 0], verts[i*12 + 1], verts[i*12 + 2]}; + double v1[3] = {verts[i*12 + 3], verts[i*12 + 4], verts[i*12 + 5]}; + double v2[3] = {verts[i*12 + 6], verts[i*12 + 7], verts[i*12 + 8]}; + double v3[3] = {verts[i*12 + 9], verts[i*12 + 10], verts[i*12 + 11]}; + + if (h <= v0[0]) { + // AREA 0 + return 0.0; + } else if (h <= v1[0]) { + // AREA 1 + double p01[3]; + double p02[3]; + double p03[3]; + + h_midpoint(v0, v1, h, p01); + h_midpoint(v0, v2, h, p02); + h_midpoint(v0, v3, h, p03); + + double P[9] = {p01[0], p01[1], p01[2], + p02[0], p02[1], p02[2], + p03[0], p03[1], p03[2]}; + + return full_tri_area(P); + + } else if (h <= v2[0]) { + // AREA 2 + double p02[3]; + double p03[3]; + double p12[3]; + double p13[3]; + + h_midpoint(v0, v2, h, p02); + h_midpoint(v0, v3, h, p03); + h_midpoint(v1, v2, h, p12); + h_midpoint(v1, v3, h, p13); + + double P_1[9] = {p02[0], p02[1], p02[2], + p03[0], p03[1], p03[2], + p12[0], p12[1], p12[2]}; + double P_2[9] = {p03[0], p03[1], p03[2], + p12[0], p12[1], p12[2], + p13[0], p13[1], p13[2]}; + + return full_tri_area(P_1) + full_tri_area(P_2); + + } else if (h <= v3[0]) { + // AREA 3 + double p03[3]; + double p13[3]; + double p23[3]; + + h_midpoint(v0, v3, h, p03); + h_midpoint(v1, v3, h, p13); + h_midpoint(v2, v3, h, p23); + + double P[9] = {p03[0], p03[1], p03[2], + p13[0], p13[1], p13[2], + p23[0], p23[1], p23[2]}; + + return full_tri_area(P); + } else { + // AREA 4 + return 0.0; + } +} + +void NeighbourhoodTetMeshIntegrator( + double * verts, int num_verts, int d1, + const long * const elements, int num_elements, int d2, + double * dists, int num_dists, + const double * const x, int num_x, + double * y_volume, int num_y1, + double * y_area, int num_y2 + ) +{ + double * t_verts = (double *) malloc(num_elements * 12 * sizeof(double)); // Every triangle, x0 y0 x1 y1 x2 y2 + double * t_scales = (double *) malloc(num_elements * sizeof(double)); + double * full_volumes = (double *) malloc(num_elements * sizeof(double)); + + #pragma omp parallel for + for (int i = 0; i < num_elements; ++i) + { + + double * t_verts_tmp = (double *) malloc(12*sizeof(double)); + + int ordering[4]; + long v_indices[4]; + double t_dists_tmp[4]; + + for (int j = 0; j < 4; ++j) + { + ordering[j] = j; + v_indices[j] = elements[i*4+j]; + t_dists_tmp[j] = dists[v_indices[j]]; + } + + get_sorted_indices(t_dists_tmp, ordering); + + copy_verts(verts, v_indices, t_verts_tmp, ordering); + + double t_scale; + + transform_tet(t_verts_tmp, t_dists_tmp, t_scale); + + t_scales[i] = t_scale; + full_volumes[i] = full_tet_volume(t_verts_tmp); + + for (int j = 0; j < 12; ++j) + { + t_verts[i*12 + j] = t_verts_tmp[j]; + } + + free(t_verts_tmp); + } + + #pragma omp parallel for + for (int j = 0; j < num_x; ++j) + { + y_volume[j] = 0.0; + y_area[j] = 0.0; + + for (int i = 0; i < num_elements; ++i) + { + if (t_scales[i] != 0) + { + y_volume[j] += sliced_tet_volume(t_verts, full_volumes[i], i, x[j]) / t_scales[i]; + y_area[j] += sliced_tet_area(t_verts, i, x[j]); + } + } + } + + free(t_verts); + free(t_scales); + free(full_volumes); +} \ No newline at end of file diff --git a/cpp/NeighbourhoodTetMeshIntegrator/c_NeighbourhoodTetMeshIntegrator.h b/cpp/NeighbourhoodTetMeshIntegrator/c_NeighbourhoodTetMeshIntegrator.h new file mode 100644 index 0000000..5df1db2 --- /dev/null +++ b/cpp/NeighbourhoodTetMeshIntegrator/c_NeighbourhoodTetMeshIntegrator.h @@ -0,0 +1,15 @@ +#ifndef C_NEIGHBOURHOODTETMESHINTEGRATOR_HPP +#define C_NEIGHBOURHOODTETMESHINTEGRATOR_HPP + +#define PI 3.141592653589793238462643383279 + +void NeighbourhoodTetMeshIntegrator( + double * verts, int num_verts, int d1, + const long * const elements, int num_elements, int d2, + double * dists, int num_dists, + const double * const x, int num_x, + double * y_volume, int num_y1, + double * y_area, int num_y2 + ); + +#endif // C_NEIGHBOURHOODTETMESHINTEGRATOR_HPP \ No newline at end of file diff --git a/cpp/NeighbourhoodTetMeshIntegrator/numpy.i b/cpp/NeighbourhoodTetMeshIntegrator/numpy.i new file mode 100644 index 0000000..72d5824 --- /dev/null +++ b/cpp/NeighbourhoodTetMeshIntegrator/numpy.i @@ -0,0 +1,3183 @@ +/* -*- C -*- (not really, but good for syntax highlighting) */ + +/* + * Copyright (c) 2005-2015, NumPy Developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of the NumPy Developers nor the names of any + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef SWIGPYTHON + +%{ +#ifndef SWIG_FILE_WITH_INIT +#define NO_IMPORT_ARRAY +#endif +#include "stdio.h" +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include <numpy/arrayobject.h> +%} + +/**********************************************************************/ + +%fragment("NumPy_Backward_Compatibility", "header") +{ +%#if NPY_API_VERSION < 0x00000007 +%#define NPY_ARRAY_DEFAULT NPY_DEFAULT +%#define NPY_ARRAY_FARRAY NPY_FARRAY +%#define NPY_FORTRANORDER NPY_FORTRAN +%#endif +} + +/**********************************************************************/ + +/* The following code originally appeared in + * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was + * translated from C++ to C by John Hunter. Bill Spotz has modified + * it to fix some minor bugs, upgrade from Numeric to numpy (all + * versions), add some comments and functionality, and convert from + * direct code insertion to SWIG fragments. + */ + +%fragment("NumPy_Macros", "header") +{ +/* Macros to extract array attributes. + */ +%#if NPY_API_VERSION < 0x00000007 +%#define is_array(a) ((a) && PyArray_Check((PyArrayObject*)a)) +%#define array_type(a) (int)(PyArray_TYPE((PyArrayObject*)a)) +%#define array_numdims(a) (((PyArrayObject*)a)->nd) +%#define array_dimensions(a) (((PyArrayObject*)a)->dimensions) +%#define array_size(a,i) (((PyArrayObject*)a)->dimensions[i]) +%#define array_strides(a) (((PyArrayObject*)a)->strides) +%#define array_stride(a,i) (((PyArrayObject*)a)->strides[i]) +%#define array_data(a) (((PyArrayObject*)a)->data) +%#define array_descr(a) (((PyArrayObject*)a)->descr) +%#define array_flags(a) (((PyArrayObject*)a)->flags) +%#define array_clearflags(a,f) (((PyArrayObject*)a)->flags) &= ~f +%#define array_enableflags(a,f) (((PyArrayObject*)a)->flags) = f +%#define array_is_fortran(a) (PyArray_ISFORTRAN((PyArrayObject*)a)) +%#else +%#define is_array(a) ((a) && PyArray_Check(a)) +%#define array_type(a) PyArray_TYPE((PyArrayObject*)a) +%#define array_numdims(a) PyArray_NDIM((PyArrayObject*)a) +%#define array_dimensions(a) PyArray_DIMS((PyArrayObject*)a) +%#define array_strides(a) PyArray_STRIDES((PyArrayObject*)a) +%#define array_stride(a,i) PyArray_STRIDE((PyArrayObject*)a,i) +%#define array_size(a,i) PyArray_DIM((PyArrayObject*)a,i) +%#define array_data(a) PyArray_DATA((PyArrayObject*)a) +%#define array_descr(a) PyArray_DESCR((PyArrayObject*)a) +%#define array_flags(a) PyArray_FLAGS((PyArrayObject*)a) +%#define array_enableflags(a,f) PyArray_ENABLEFLAGS((PyArrayObject*)a,f) +%#define array_clearflags(a,f) PyArray_CLEARFLAGS((PyArrayObject*)a,f) +%#define array_is_fortran(a) (PyArray_IS_F_CONTIGUOUS((PyArrayObject*)a)) +%#endif +%#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS((PyArrayObject*)a)) +%#define array_is_native(a) (PyArray_ISNOTSWAPPED((PyArrayObject*)a)) +} + +/**********************************************************************/ + +%fragment("NumPy_Utilities", + "header") +{ + /* Given a PyObject, return a string describing its type. + */ + const char* pytype_string(PyObject* py_obj) + { + if (py_obj == NULL ) return "C NULL value"; + if (py_obj == Py_None ) return "Python None" ; + if (PyCallable_Check(py_obj)) return "callable" ; + if (PyString_Check( py_obj)) return "string" ; + if (PyInt_Check( py_obj)) return "int" ; + if (PyFloat_Check( py_obj)) return "float" ; + if (PyDict_Check( py_obj)) return "dict" ; + if (PyList_Check( py_obj)) return "list" ; + if (PyTuple_Check( py_obj)) return "tuple" ; +%#if PY_MAJOR_VERSION < 3 + if (PyFile_Check( py_obj)) return "file" ; + if (PyModule_Check( py_obj)) return "module" ; + if (PyInstance_Check(py_obj)) return "instance" ; +%#endif + + return "unknown type"; + } + + /* Given a NumPy typecode, return a string describing the type. + */ + const char* typecode_string(int typecode) + { + static const char* type_names[25] = {"bool", + "byte", + "unsigned byte", + "short", + "unsigned short", + "int", + "unsigned int", + "long", + "unsigned long", + "long long", + "unsigned long long", + "float", + "double", + "long double", + "complex float", + "complex double", + "complex long double", + "object", + "string", + "unicode", + "void", + "ntypes", + "notype", + "char", + "unknown"}; + return typecode < 24 ? type_names[typecode] : type_names[24]; + } + + /* Make sure input has correct numpy type. This now just calls + PyArray_EquivTypenums(). + */ + int type_match(int actual_type, + int desired_type) + { + return PyArray_EquivTypenums(actual_type, desired_type); + } + +%#ifdef SWIGPY_USE_CAPSULE + void free_cap(PyObject * cap) + { + void* array = (void*) PyCapsule_GetPointer(cap,SWIGPY_CAPSULE_NAME); + if (array != NULL) free(array); + } +%#endif + + +} + +/**********************************************************************/ + +%fragment("NumPy_Object_to_Array", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities") +{ + /* Given a PyObject pointer, cast it to a PyArrayObject pointer if + * legal. If not, set the python error string appropriately and + * return NULL. + */ + PyArrayObject* obj_to_array_no_conversion(PyObject* input, + int typecode) + { + PyArrayObject* ary = NULL; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input), typecode))) + { + ary = (PyArrayObject*) input; + } + else if is_array(input) + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = typecode_string(array_type(input)); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. Array of type '%s' given", + desired_type, actual_type); + ary = NULL; + } + else + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = pytype_string(input); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. A '%s' was given", + desired_type, + actual_type); + ary = NULL; + } + return ary; + } + + /* Convert the given PyObject to a NumPy array with the given + * typecode. On success, return a valid PyArrayObject* with the + * correct type. On failure, the python error string will be set and + * the routine returns NULL. + */ + PyArrayObject* obj_to_array_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + PyArrayObject* ary = NULL; + PyObject* py_obj; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input),typecode))) + { + ary = (PyArrayObject*) input; + *is_new_object = 0; + } + else + { + py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_ARRAY_DEFAULT); + /* If NULL, PyArray_FromObject will have set python error value.*/ + ary = (PyArrayObject*) py_obj; + *is_new_object = 1; + } + return ary; + } + + /* Given a PyArrayObject, check to see if it is contiguous. If so, + * return the input pointer and flag it as not a new object. If it is + * not contiguous, create a new PyArrayObject using the original data, + * flag it as a new object and return the pointer. + */ + PyArrayObject* make_contiguous(PyArrayObject* ary, + int* is_new_object, + int min_dims, + int max_dims) + { + PyArrayObject* result; + if (array_is_contiguous(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, + array_type(ary), + min_dims, + max_dims); + *is_new_object = 1; + } + return result; + } + + /* Given a PyArrayObject, check to see if it is Fortran-contiguous. + * If so, return the input pointer, but do not flag it as not a new + * object. If it is not Fortran-contiguous, create a new + * PyArrayObject using the original data, flag it as a new object + * and return the pointer. + */ + PyArrayObject* make_fortran(PyArrayObject* ary, + int* is_new_object) + { + PyArrayObject* result; + if (array_is_fortran(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + Py_INCREF(array_descr(ary)); + result = (PyArrayObject*) PyArray_FromArray(ary, + array_descr(ary), +%#if NPY_API_VERSION < 0x00000007 + NPY_FORTRANORDER); +%#else + NPY_ARRAY_F_CONTIGUOUS); +%#endif + *is_new_object = 1; + } + return result; + } + + /* Convert a given PyObject to a contiguous PyArrayObject of the + * specified type. If the input object is not a contiguous + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_contiguous(ary1, &is_new2, 0, 0); + if ( is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } + + /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the + * specified type. If the input object is not a Fortran-ordered + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_fortran(ary1, &is_new2); + if (is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } +} /* end fragment */ + +/**********************************************************************/ + +%fragment("NumPy_Array_Requirements", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros") +{ + /* Test whether a python object is contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ + int require_contiguous(PyArrayObject* ary) + { + int contiguous = 1; + if (!array_is_contiguous(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must be contiguous. A non-contiguous array was given"); + contiguous = 0; + } + return contiguous; + } + + /* Test whether a python object is (C_ or F_) contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ + int require_c_or_f_contiguous(PyArrayObject* ary) + { + int contiguous = 1; + if (!(array_is_contiguous(ary) || array_is_fortran(ary))) + { + PyErr_SetString(PyExc_TypeError, + "Array must be contiguous (C_ or F_). A non-contiguous array was given"); + contiguous = 0; + } + return contiguous; + } + + /* Require that a numpy array is not byte-swapped. If the array is + * not byte-swapped, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_native(PyArrayObject* ary) + { + int native = 1; + if (!array_is_native(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must have native byteorder. " + "A byte-swapped array was given"); + native = 0; + } + return native; + } + + /* Require the given PyArrayObject to have a specified number of + * dimensions. If the array has the specified number of dimensions, + * return 1. Otherwise, set the python error string and return 0. + */ + int require_dimensions(PyArrayObject* ary, + int exact_dimensions) + { + int success = 1; + if (array_numdims(ary) != exact_dimensions) + { + PyErr_Format(PyExc_TypeError, + "Array must have %d dimensions. Given array has %d dimensions", + exact_dimensions, + array_numdims(ary)); + success = 0; + } + return success; + } + + /* Require the given PyArrayObject to have one of a list of specified + * number of dimensions. If the array has one of the specified number + * of dimensions, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_dimensions_n(PyArrayObject* ary, + int* exact_dimensions, + int n) + { + int success = 0; + int i; + char dims_str[255] = ""; + char s[255]; + for (i = 0; i < n && !success; i++) + { + if (array_numdims(ary) == exact_dimensions[i]) + { + success = 1; + } + } + if (!success) + { + for (i = 0; i < n-1; i++) + { + sprintf(s, "%d, ", exact_dimensions[i]); + strcat(dims_str,s); + } + sprintf(s, " or %d", exact_dimensions[n-1]); + strcat(dims_str,s); + PyErr_Format(PyExc_TypeError, + "Array must have %s dimensions. Given array has %d dimensions", + dims_str, + array_numdims(ary)); + } + return success; + } + + /* Require the given PyArrayObject to have a specified shape. If the + * array has the specified shape, return 1. Otherwise, set the python + * error string and return 0. + */ + int require_size(PyArrayObject* ary, + npy_intp* size, + int n) + { + int i; + int success = 1; + size_t len; + char desired_dims[255] = "["; + char s[255]; + char actual_dims[255] = "["; + for(i=0; i < n;i++) + { + if (size[i] != -1 && size[i] != array_size(ary,i)) + { + success = 0; + } + } + if (!success) + { + for (i = 0; i < n; i++) + { + if (size[i] == -1) + { + sprintf(s, "*,"); + } + else + { + sprintf(s, "%ld,", (long int)size[i]); + } + strcat(desired_dims,s); + } + len = strlen(desired_dims); + desired_dims[len-1] = ']'; + for (i = 0; i < n; i++) + { + sprintf(s, "%ld,", (long int)array_size(ary,i)); + strcat(actual_dims,s); + } + len = strlen(actual_dims); + actual_dims[len-1] = ']'; + PyErr_Format(PyExc_TypeError, + "Array must have shape of %s. Given array has shape of %s", + desired_dims, + actual_dims); + } + return success; + } + + /* Require the given PyArrayObject to to be Fortran ordered. If the + * the PyArrayObject is already Fortran ordered, do nothing. Else, + * set the Fortran ordering flag and recompute the strides. + */ + int require_fortran(PyArrayObject* ary) + { + int success = 1; + int nd = array_numdims(ary); + int i; + npy_intp * strides = array_strides(ary); + if (array_is_fortran(ary)) return success; + int n_non_one = 0; + /* Set the Fortran ordered flag */ + const npy_intp *dims = array_dimensions(ary); + for (i=0; i < nd; ++i) + n_non_one += (dims[i] != 1) ? 1 : 0; + if (n_non_one > 1) + array_clearflags(ary,NPY_ARRAY_CARRAY); + array_enableflags(ary,NPY_ARRAY_FARRAY); + /* Recompute the strides */ + strides[0] = strides[nd-1]; + for (i=1; i < nd; ++i) + strides[i] = strides[i-1] * array_size(ary,i-1); + return success; + } +} + +/* Combine all NumPy fragments into one for convenience */ +%fragment("NumPy_Fragments", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities", + fragment="NumPy_Object_to_Array", + fragment="NumPy_Array_Requirements") +{ +} + +/* End John Hunter translation (with modifications by Bill Spotz) + */ + +/* %numpy_typemaps() macro + * + * This macro defines a family of 75 typemaps that allow C arguments + * of the form + * + * 1. (DATA_TYPE IN_ARRAY1[ANY]) + * 2. (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + * 3. (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + * + * 4. (DATA_TYPE IN_ARRAY2[ANY][ANY]) + * 5. (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 6. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + * 7. (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 8. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + * + * 9. (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + * 10. (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 11. (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 12. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + * 13. (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 14. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + * + * 15. (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + * 16. (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 17. (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 18. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + * 19. (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 20. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + * + * 21. (DATA_TYPE INPLACE_ARRAY1[ANY]) + * 22. (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + * 23. (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + * + * 24. (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + * 25. (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 26. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + * 27. (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 28. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + * + * 29. (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + * 30. (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 31. (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 32. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + * 33. (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 34. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + * + * 35. (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + * 36. (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 37. (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 38. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + * 39. (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 40. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + * + * 41. (DATA_TYPE ARGOUT_ARRAY1[ANY]) + * 42. (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + * 43. (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + * + * 44. (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + * + * 45. (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + * + * 46. (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + * + * 47. (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + * 48. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + * + * 49. (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 50. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + * 51. (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 52. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + * + * 53. (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 54. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + * 55. (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 56. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) + * + * 57. (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 58. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) + * 59. (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 60. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) + * + * 61. (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + * 62. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + * + * 63. (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 64. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + * 65. (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 66. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + * + * 67. (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 68. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) + * 69. (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 70. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) + * + * 71. (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 72. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) + * 73. (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 74. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) + * + * 75. (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) + * + * where "DATA_TYPE" is any type supported by the NumPy module, and + * "DIM_TYPE" is any int-like type suitable for specifying dimensions. + * The difference between "ARRAY" typemaps and "FARRAY" typemaps is + * that the "FARRAY" typemaps expect Fortran ordering of + * multidimensional arrays. In python, the dimensions will not need + * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1" + * typemaps). The IN_ARRAYs can be a numpy array or any sequence that + * can be converted to a numpy array of the specified type. The + * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The + * ARGOUT_ARRAYs will be returned as new numpy arrays of the + * appropriate type. + * + * These typemaps can be applied to existing functions using the + * %apply directive. For example: + * + * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)}; + * double prod(double* series, int length); + * + * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) + * {(int rows, int cols, double* matrix )}; + * void floor(int rows, int cols, double* matrix, double f); + * + * %apply (double IN_ARRAY3[ANY][ANY][ANY]) + * {(double tensor[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double low[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double upp[2][2][2] )}; + * void luSplit(double tensor[2][2][2], + * double low[2][2][2], + * double upp[2][2][2] ); + * + * or directly with + * + * double prod(double* IN_ARRAY1, int DIM1); + * + * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f); + * + * void luSplit(double IN_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY]); + */ + +%define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) + +/************************/ +/* Input Array Typemaps */ +/************************/ + +/* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY1[ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY1[ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY1[ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = {-1}; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 2)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 3)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/***************************/ +/* In-Place Array Typemaps */ +/***************************/ + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY1[ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY1[ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int i=1) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = 1; + for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + (PyArrayObject* array=NULL, int i=0) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = 1; + for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i); + $2 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 2) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_size(array, size, 4) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 3) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* INPLACE_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/*************************/ +/* Argout Array Typemaps */ +/*************************/ + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY1[ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[1] = { $1_dim0 }; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY1[ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $2 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $2; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $1 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $1; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[2] = { $1_dim0, $1_dim1 }; + array = PyArray_SimpleNew(2, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = PyArray_SimpleNew(3, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[4] = { $1_dim0, $1_dim1, $1_dim2, $1_dim3 }; + array = PyArray_SimpleNew(4, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/*****************************/ +/* Argoutview Array Typemaps */ +/*****************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEW_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/*************************************/ +/* Managed Argoutview Array Typemaps */ +/*************************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEWM_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj= PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/**************************************/ +/* In-Place Array Typemap - flattened */ +/**************************************/ + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) + (PyArrayObject* array=NULL, int i=1) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_c_or_f_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = 1; + for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); +} + +%enddef /* %numpy_typemaps() macro */ +/* *************************************************************** */ + +/* Concrete instances of the %numpy_typemaps() macro: Each invocation + * below applies all of the typemaps above to the specified data type. + */ +%numpy_typemaps(signed char , NPY_BYTE , int) +%numpy_typemaps(unsigned char , NPY_UBYTE , int) +%numpy_typemaps(short , NPY_SHORT , int) +%numpy_typemaps(unsigned short , NPY_USHORT , int) +%numpy_typemaps(int , NPY_INT , int) +%numpy_typemaps(unsigned int , NPY_UINT , int) +%numpy_typemaps(long , NPY_LONG , int) +%numpy_typemaps(unsigned long , NPY_ULONG , int) +%numpy_typemaps(long long , NPY_LONGLONG , int) +%numpy_typemaps(unsigned long long, NPY_ULONGLONG, int) +%numpy_typemaps(float , NPY_FLOAT , int) +%numpy_typemaps(double , NPY_DOUBLE , int) +%numpy_typemaps(int8_t , NPY_INT8 , int) +%numpy_typemaps(int16_t , NPY_INT16 , int) +%numpy_typemaps(int32_t , NPY_INT32 , int) +%numpy_typemaps(int64_t , NPY_INT64 , int) +%numpy_typemaps(uint8_t , NPY_UINT8 , int) +%numpy_typemaps(uint16_t , NPY_UINT16 , int) +%numpy_typemaps(uint32_t , NPY_UINT32 , int) +%numpy_typemaps(uint64_t , NPY_UINT64 , int) + + +/* *************************************************************** + * The follow macro expansion does not work, because C++ bool is 4 + * bytes and NPY_BOOL is 1 byte + * + * %numpy_typemaps(bool, NPY_BOOL, int) + */ + +/* *************************************************************** + * On my Mac, I get the following warning for this macro expansion: + * 'swig/python detected a memory leak of type 'long double *', no destructor found.' + * + * %numpy_typemaps(long double, NPY_LONGDOUBLE, int) + */ + +#ifdef __cplusplus + +%include <std_complex.i> + +%numpy_typemaps(std::complex<float>, NPY_CFLOAT , int) +%numpy_typemaps(std::complex<double>, NPY_CDOUBLE, int) + +#endif + +#endif /* SWIGPYTHON */ diff --git a/cpp/NeighbourhoodTetMeshIntegrator/swig_it b/cpp/NeighbourhoodTetMeshIntegrator/swig_it new file mode 100644 index 0000000..636affe --- /dev/null +++ b/cpp/NeighbourhoodTetMeshIntegrator/swig_it @@ -0,0 +1,4 @@ +swig -Wall -python -c++ NeighbourhoodTetMeshIntegrator.i +g++ -O3 -fPIC -fopenmp -lstdc++ -c c_NeighbourhoodTetMeshIntegrator.cpp +g++ -O3 -fPIC -fopenmp -lstdc++ -c NeighbourhoodTetMeshIntegrator_wrap.cxx -I/usr/include/python3.7 -I/usr/lib/python3.7/site-packages/numpy/core/include +g++ -shared c_NeighbourhoodTetMeshIntegrator.o NeighbourhoodTetMeshIntegrator_wrap.o -fopenmp -O3 -lstdc++ -o _NeighbourhoodTetMeshIntegrator.so diff --git a/cpp/NeighbourhoodTriMeshIntegrator/NeighbourhoodTriMeshIntegrator.i b/cpp/NeighbourhoodTriMeshIntegrator/NeighbourhoodTriMeshIntegrator.i new file mode 100644 index 0000000..e66fab2 --- /dev/null +++ b/cpp/NeighbourhoodTriMeshIntegrator/NeighbourhoodTriMeshIntegrator.i @@ -0,0 +1,48 @@ +%module NeighbourhoodTriMeshIntegrator + +%{ +#define SWIG_FILE_WITH_INIT +#include "c_NeighbourhoodTriMeshIntegrator.h" +%} + +%include "numpy.i" + +%init %{ +import_array(); +%} + +%apply (double* INPLACE_ARRAY2, int DIM1, int DIM2) { + (double * verts, int num_verts, int d1) +}; + +%apply (long* INPLACE_ARRAY2, int DIM1, int DIM2) { + (long * faces, int num_faces, int d2) +}; + +%apply (double* INPLACE_ARRAY2, int DIM1, int DIM2) { + (double * tet_verts, int num_tet_verts, int d3) +}; + +%apply (long* INPLACE_ARRAY2, int DIM1, int DIM2) { + (long * tet_elems, int num_tet_verts, int d4) +}; + +%apply (long* INPLACE_ARRAY2, int DIM1, int DIM2) { + (long * tet_faces, int num_tet_verts, int d5) +}; + +%apply (double* INPLACE_ARRAY1, int DIM1) { + (double * dists, int num_dists), + (double * x, int num_x), + (double * y_area, int num_y1), + (double * y_circumference, int num_y2) +}; + +void NeighbourhoodTriMeshIntegrator( + double * verts, int num_verts, int d1, + long * faces, int num_faces, int d2, + double * dists, int num_dists, + double * x, int num_x, + double * y_area, int num_y1, + double * y_circumference, int num_y2 + ); diff --git a/cpp/NeighbourhoodTriMeshIntegrator/NeighbourhoodTriMeshIntegrator.py b/cpp/NeighbourhoodTriMeshIntegrator/NeighbourhoodTriMeshIntegrator.py new file mode 100644 index 0000000..14f2cc0 --- /dev/null +++ b/cpp/NeighbourhoodTriMeshIntegrator/NeighbourhoodTriMeshIntegrator.py @@ -0,0 +1,68 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 4.0.2 +# +# Do not make changes to this file unless you know what you are doing--modify +# the SWIG interface file instead. + +from sys import version_info as _swig_python_version_info +if _swig_python_version_info < (2, 7, 0): + raise RuntimeError("Python 2.7 or later required") + +# Import the low-level C/C++ module +if __package__ or "." in __name__: + from . import _NeighbourhoodTriMeshIntegrator +else: + import _NeighbourhoodTriMeshIntegrator + +try: + import builtins as __builtin__ +except ImportError: + import __builtin__ + +def _swig_repr(self): + try: + strthis = "proxy of " + self.this.__repr__() + except __builtin__.Exception: + strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + + +def _swig_setattr_nondynamic_instance_variable(set): + def set_instance_attr(self, name, value): + if name == "thisown": + self.this.own(value) + elif name == "this": + set(self, name, value) + elif hasattr(self, name) and isinstance(getattr(type(self), name), property): + set(self, name, value) + else: + raise AttributeError("You cannot add instance attributes to %s" % self) + return set_instance_attr + + +def _swig_setattr_nondynamic_class_variable(set): + def set_class_attr(cls, name, value): + if hasattr(cls, name) and not isinstance(getattr(cls, name), property): + set(cls, name, value) + else: + raise AttributeError("You cannot add class attributes to %s" % cls) + return set_class_attr + + +def _swig_add_metaclass(metaclass): + """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass""" + def wrapper(cls): + return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy()) + return wrapper + + +class _SwigNonDynamicMeta(type): + """Meta class to enforce nondynamic attributes (no new attributes) for a class""" + __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__) + + + +def NeighbourhoodTriMeshIntegrator(verts, faces, dists, x, y_area, y_circumference): + return _NeighbourhoodTriMeshIntegrator.NeighbourhoodTriMeshIntegrator(verts, faces, dists, x, y_area, y_circumference) + + diff --git a/cpp/NeighbourhoodTriMeshIntegrator/TriMeshIntegrator.py b/cpp/NeighbourhoodTriMeshIntegrator/TriMeshIntegrator.py new file mode 100644 index 0000000..1cb9452 --- /dev/null +++ b/cpp/NeighbourhoodTriMeshIntegrator/TriMeshIntegrator.py @@ -0,0 +1,16 @@ +import numpy as np + +from .NeighbourhoodTriMeshIntegrator import NeighbourhoodTriMeshIntegrator + +def TriMeshIntegrator(verts, faces, dists, x): + verts = verts.astype(np.float64) + faces = faces.astype(np.int64) + dists = dists.astype(np.float64) + x = x.astype(np.float64) + + y_area = np.empty(x.shape, dtype=np.float64) + y_circumference = np.empty(x.shape, dtype=np.float64) + + NeighbourhoodTriMeshIntegrator(verts, faces, dists, x, y_area, y_circumference) + + return y_area, y_circumference \ No newline at end of file diff --git a/cpp/NeighbourhoodTriMeshIntegrator/_NeighbourhoodTriMeshIntegrator.so b/cpp/NeighbourhoodTriMeshIntegrator/_NeighbourhoodTriMeshIntegrator.so new file mode 100755 index 0000000000000000000000000000000000000000..15bbfd1279f091270bef36b610067953ef107d7c GIT binary patch literal 134832 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 literal 0 HcmV?d00001 diff --git a/cpp/NeighbourhoodTriMeshIntegrator/__init__.py b/cpp/NeighbourhoodTriMeshIntegrator/__init__.py new file mode 100644 index 0000000..9f25e90 --- /dev/null +++ b/cpp/NeighbourhoodTriMeshIntegrator/__init__.py @@ -0,0 +1 @@ +from .TriMeshIntegrator import TriMeshIntegrator \ No newline at end of file diff --git a/cpp/NeighbourhoodTriMeshIntegrator/c_NeighbourhoodTriMeshIntegrator.cpp b/cpp/NeighbourhoodTriMeshIntegrator/c_NeighbourhoodTriMeshIntegrator.cpp new file mode 100644 index 0000000..682db89 --- /dev/null +++ b/cpp/NeighbourhoodTriMeshIntegrator/c_NeighbourhoodTriMeshIntegrator.cpp @@ -0,0 +1,327 @@ +#include "c_NeighbourhoodTriMeshIntegrator.h" +#include <cmath> +#include <algorithm> +#include <iostream> +#include <vector> +#include <boost/numeric/ublas/matrix.hpp> +#include <boost/numeric/ublas/vector.hpp> +#include <boost/numeric/ublas/lu.hpp> +#include <boost/numeric/ublas/io.hpp> + +const double eps = 0.000000001; + +void copy_verts(const double * const verts, const long * const v_indices, double * t_verts, const int * const ordering) +{ + for (int j = 0; j < 3; ++j) + { + long vn = v_indices[ordering[j]]; + for (int i = 0; i < 3; ++i) + { + t_verts[3*j + i] = verts[3*vn + i]; + } + } +} + +void get_sorted_indices(double * dists, int * ordering) +{ + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 2-i; ++j) + { + if (dists[j] > dists[j+1]) { + std::swap(dists[j], dists[j+1]); + std::swap(ordering[j], ordering[j+1]); + } + } +} + +void rotx(double & vy, double & vz, const double t) +{ + const double ct = std::cos(t); + const double st = std::sin(t); + + const double tmp_vz = vy * st + vz * ct; + + vy = vy * ct - vz * st; + vz = tmp_vz; +} + +void roty(double & vx, double & vz, const double t) +{ + const double ct = std::cos(t); + const double st = std::sin(t); + + const double tmp_vz = ct * vz - st * vx; + + vx = vx * ct + st * vz; + vz = tmp_vz; +} + +void rotz(double & vx, double & vy, const double t) +{ + const double ct = std::cos(t); + const double st = std::sin(t); + + const double tmp_vy = vx * st + vy * ct; + + vx = vx * ct - vy * st; + vy = tmp_vy; +} + +void get_linear_params(const double * const verts, const double * const dists, double &a, double &b) +{ + using namespace boost::numeric::ublas; + + matrix<double> A(3,3); + vector<double> v(3); + + for (unsigned i = 0; i < 3; ++i) { + v(i) = dists[i]; + for (unsigned j = 0; j < 3; ++j) { + if (j < 2) A(i, j) = verts[i*3 + j]; + else A(i, j) = 1.0; + } + } + + permutation_matrix<size_t> pm(3); + + lu_factorize(A, pm); + lu_substitute(A, pm, v); + + a = v(0); + b = v(1); +} + +void get_edge_linear_params(const double * const verts, double * linear_params, int i) +{ + const double x0 = verts[i*6]; + const double y0 = verts[i*6 + 1]; + const double x1 = verts[i*6 + 2]; + const double y1 = verts[i*6 + 3]; + const double x2 = verts[i*6 + 4]; + const double y2 = verts[i*6 + 5]; + + linear_params[i*6] = (y1 - y0) / (x1 - x0); + linear_params[i*6 + 1] = y0 - linear_params[i*6]*x0; + linear_params[i*6 + 2] = (y2 - y0) / (x2 - x0); + linear_params[i*6 + 3] = y0 - linear_params[i*6+2]*x0; + linear_params[i*6 + 4] = (y2 - y1) / (x2 - x1); + linear_params[i*6 + 5] = y1 - linear_params[i*6+4]*x1; +} + +void transform_triangle(double * verts, double * dists, double & scale, double & full_area) // 9, 3 +{ + // Normalize so first vertice is at the origin + + for (int i = 0; i < 3; ++i) + { + verts[3+i] -= verts[i]; + verts[6+i] -= verts[i]; + verts[i] = 0; + } + + // Rotate so it corresponds to a flat triangWle + + double t; + t = -std::atan2(verts[4], verts[3]); + rotz(verts[3],verts[4], t); + rotz(verts[6],verts[7], t); + + t = std::atan2(verts[5], verts[3]); + roty(verts[3],verts[5], t); + roty(verts[6],verts[8], t); + + t = -std::atan2(verts[8], verts[7]); + rotx(verts[4],verts[5], t); + rotx(verts[7],verts[8], t); + + // calculate full area of triangle + const double ax = verts[0] - verts[3]; + const double ay = verts[1] - verts[4]; + const double bx = verts[0] - verts[6]; + const double by = verts[1] - verts[7]; + + full_area = std::abs(ax*by - bx*ay) / 2.0; + + double a, b; + if (full_area < eps) { + verts[0] = dists[0]; verts[1] = dists[0]; verts[2] = dists[0]; // dont think we need this now we have the bounds elsewhere (Update: well, apparently we do...) + return; + } + + if (dists[0] == dists[2]) { + verts[0] = dists[0]; verts[1] = dists[0]; verts[2] = dists[0]; // dont think we need this now we have the bounds elsewhere (Update: well, apparently we do...) + return; + } + + get_linear_params(verts, dists, a, b); + + double gradient_norm = std::sqrt(a*a + b*b); + scale = 1.0/gradient_norm; + + // Change basis + t = -std::atan2(b, a); + rotz(verts[3],verts[4], t); + rotz(verts[6],verts[7], t); + + // Scale to h scale + verts[0] = verts[0] + dists[0]; + verts[3] = verts[3] * gradient_norm + dists[0]; + verts[6] = verts[6] * gradient_norm + dists[0]; +} + +double sliced_triangle_area(const double * const verts, const double * const edge_linear_params, const int i, double h) +{ + double x0 = verts[i*6 + 0]; + double y0 = verts[i*6 + 1]; + double x1 = verts[i*6 + 2]; + double y1 = verts[i*6 + 3]; + double x2 = verts[i*6 + 4]; + double y2 = verts[i*6 + 5]; + + auto f01 = [=](double x) { return edge_linear_params[i*6 + 0]*x + edge_linear_params[i*6 + 1]; }; + auto f02 = [=](double x) { return edge_linear_params[i*6 + 2]*x + edge_linear_params[i*6 + 3]; }; + auto f12 = [=](double x) { return edge_linear_params[i*6 + 4]*x + edge_linear_params[i*6 + 5]; }; + + if (x1 == x2 && y1 == y2) return 0.0; + + if (x0 == x1) { + if (y0 == y1) return 0.0; + if (x0 == x2) return 0.0; + + double height_full = x2 - x0; + double base_full = y1 - y0; + double full_area = std::abs(0.5*height_full*base_full); + + double right_height = x2 - h; + double right_base = f02(h) - f12(h); + double right_area = std::abs(0.5*right_height*right_base); + + double area = full_area - right_area; + + return area; + } + + if (h < x1) + { + double height = h - x0; + double base = f01(h) - f02(h); + double area = std::abs(0.5*base*height); + + return std::abs(0.5*base*height); + } + + double left_height = x1 - x0; + double base = f01(x1) - f02(x1); + double left_area = std::abs(base*left_height); + + double right_height = x2 - x1; + double mid_base = y1 - f02(x1); + double full_right_area = std::abs(right_height*mid_base); + + double remaining_right_area = std::abs((f12(h) - f02(h)) * (x2 - h)); + + double area = 0.5*(left_area + full_right_area - remaining_right_area); + + return area; +} + +double sliced_triangle_circ(const double * const verts, const double * const edge_linear_params, const int i, double h) +{ + double x0 = verts[i*6 + 0]; + double y0 = verts[i*6 + 1]; + double x1 = verts[i*6 + 2]; + double y1 = verts[i*6 + 3]; + double x2 = verts[i*6 + 4]; + double y2 = verts[i*6 + 5]; + + if (x0 == x1 && y0 == y1) return 0.0; + if (x0 == x2 && y0 == y2) return 0.0; + if (x1 == x2 && y1 == y2) return 0.0; + if (x0 == x1 && x1 == x2) return 0.0; + if (y0 == y1 && y1 == y2) return 0.0; + + auto f02 = [=](double x) { return edge_linear_params[i*6 + 2]*x + edge_linear_params[i*6 + 3]; }; + if (h < x1) + { + auto f01 = [=](double x) { return edge_linear_params[i*6 + 0]*x + edge_linear_params[i*6 + 1]; }; + return std::abs(f01(h) - f02(h)); + } + + auto f12 = [=](double x) { return edge_linear_params[i*6 + 4]*x + edge_linear_params[i*6 + 5]; }; + return std::abs(f12(h) - f02(h)); +} + +void NeighbourhoodTriMeshIntegrator( + double * verts, int num_verts, int d1, + long * faces, int num_faces, int d2, + double * dists, int num_dists, + double * x, int num_x, + double * y_area, int num_y1, + double * y_circumference, int num_y2 + ) +{ + double * t_verts = (double *) malloc(num_faces * 6 * sizeof(double)); // Every triangle, x0 y0 x1 y1 x2 y2 + double * t_scales = (double *) malloc(num_faces * sizeof(double)); + double * full_areas = (double *) malloc(num_faces * sizeof(double)); + double * triangle_h_bounds = (double *) malloc(num_faces * 2 * sizeof(double)); + double * edge_linear_params = (double *) malloc (num_faces * 6 * sizeof(double)); + + #pragma omp parallel for + for (int i = 0; i < num_faces; ++i) + { + + double * t_verts_tmp = (double *) malloc(9*sizeof(double)); + + int ordering[3] = {0, 1, 2}; + long v_indices[3] = {faces[i*3 + 0], faces[i*3 + 1], faces[i*3 + 2]}; + + double t_dists_tmp[3] = {dists[v_indices[0]], dists[v_indices[1]], dists[v_indices[2]]}; + get_sorted_indices(t_dists_tmp, ordering); + + copy_verts(verts, v_indices, t_verts_tmp, ordering); + + triangle_h_bounds[i*2] = t_dists_tmp[0]; + triangle_h_bounds[i*2+1] = t_dists_tmp[2]; + + double t_scale, full_area; + + transform_triangle(t_verts_tmp, t_dists_tmp, t_scale, full_area); + + for (int j = 0; j < 6; ++j) + { + int g_idx = (j / 2) * 3 + j%2; // This skips the z-coordinate which is now 0 + t_verts[i*6 + j] = t_verts_tmp[g_idx]; + } + + t_scales[i] = t_scale; + full_areas[i] = full_area; + + get_edge_linear_params(t_verts, edge_linear_params, i); + + free(t_verts_tmp); + } + + #pragma omp parallel for + for (int j = 0; j < num_x; ++j) + { + y_area[j] = 0.0; + y_circumference[j] = 0.0; + + for (int i = 0; i < num_faces; ++i) + { + if (x[j] <= triangle_h_bounds[i*2]) { + } else if (x[j] >= triangle_h_bounds[i*2+1]) { + y_area[j] += full_areas[i]; + } else { + y_area[j] += sliced_triangle_area(t_verts, edge_linear_params, i, x[j]) * t_scales[i]; + y_circumference[j] += sliced_triangle_circ(t_verts, edge_linear_params, i, x[j]); + } + } + } + + free(t_verts); + free(t_scales); + free(full_areas); + free(triangle_h_bounds); + free(edge_linear_params); +} diff --git a/cpp/NeighbourhoodTriMeshIntegrator/c_NeighbourhoodTriMeshIntegrator.h b/cpp/NeighbourhoodTriMeshIntegrator/c_NeighbourhoodTriMeshIntegrator.h new file mode 100644 index 0000000..f098793 --- /dev/null +++ b/cpp/NeighbourhoodTriMeshIntegrator/c_NeighbourhoodTriMeshIntegrator.h @@ -0,0 +1,15 @@ +#ifndef C_NEIGHBOURHOODTRIMESHINTEGRATOR_HPP +#define C_NEIGHBOURHOODTRIMESHINTEGRATOR_HPP + +//#define PI 3.141592653589793238462643383279 + +void NeighbourhoodTriMeshIntegrator( + double * verts, int num_verts, int d1, + long * faces, int num_faces, int d2, + double * dists, int num_dists, + double * x, int num_x, + double * y_area, int num_y1, + double * y_circumference, int num_y2 + ); + +#endif // C_NEIGHBOURHOODTRIMESHINTEGRATOR_HPP \ No newline at end of file diff --git a/cpp/NeighbourhoodTriMeshIntegrator/numpy.i b/cpp/NeighbourhoodTriMeshIntegrator/numpy.i new file mode 100644 index 0000000..72d5824 --- /dev/null +++ b/cpp/NeighbourhoodTriMeshIntegrator/numpy.i @@ -0,0 +1,3183 @@ +/* -*- C -*- (not really, but good for syntax highlighting) */ + +/* + * Copyright (c) 2005-2015, NumPy Developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of the NumPy Developers nor the names of any + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef SWIGPYTHON + +%{ +#ifndef SWIG_FILE_WITH_INIT +#define NO_IMPORT_ARRAY +#endif +#include "stdio.h" +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include <numpy/arrayobject.h> +%} + +/**********************************************************************/ + +%fragment("NumPy_Backward_Compatibility", "header") +{ +%#if NPY_API_VERSION < 0x00000007 +%#define NPY_ARRAY_DEFAULT NPY_DEFAULT +%#define NPY_ARRAY_FARRAY NPY_FARRAY +%#define NPY_FORTRANORDER NPY_FORTRAN +%#endif +} + +/**********************************************************************/ + +/* The following code originally appeared in + * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was + * translated from C++ to C by John Hunter. Bill Spotz has modified + * it to fix some minor bugs, upgrade from Numeric to numpy (all + * versions), add some comments and functionality, and convert from + * direct code insertion to SWIG fragments. + */ + +%fragment("NumPy_Macros", "header") +{ +/* Macros to extract array attributes. + */ +%#if NPY_API_VERSION < 0x00000007 +%#define is_array(a) ((a) && PyArray_Check((PyArrayObject*)a)) +%#define array_type(a) (int)(PyArray_TYPE((PyArrayObject*)a)) +%#define array_numdims(a) (((PyArrayObject*)a)->nd) +%#define array_dimensions(a) (((PyArrayObject*)a)->dimensions) +%#define array_size(a,i) (((PyArrayObject*)a)->dimensions[i]) +%#define array_strides(a) (((PyArrayObject*)a)->strides) +%#define array_stride(a,i) (((PyArrayObject*)a)->strides[i]) +%#define array_data(a) (((PyArrayObject*)a)->data) +%#define array_descr(a) (((PyArrayObject*)a)->descr) +%#define array_flags(a) (((PyArrayObject*)a)->flags) +%#define array_clearflags(a,f) (((PyArrayObject*)a)->flags) &= ~f +%#define array_enableflags(a,f) (((PyArrayObject*)a)->flags) = f +%#define array_is_fortran(a) (PyArray_ISFORTRAN((PyArrayObject*)a)) +%#else +%#define is_array(a) ((a) && PyArray_Check(a)) +%#define array_type(a) PyArray_TYPE((PyArrayObject*)a) +%#define array_numdims(a) PyArray_NDIM((PyArrayObject*)a) +%#define array_dimensions(a) PyArray_DIMS((PyArrayObject*)a) +%#define array_strides(a) PyArray_STRIDES((PyArrayObject*)a) +%#define array_stride(a,i) PyArray_STRIDE((PyArrayObject*)a,i) +%#define array_size(a,i) PyArray_DIM((PyArrayObject*)a,i) +%#define array_data(a) PyArray_DATA((PyArrayObject*)a) +%#define array_descr(a) PyArray_DESCR((PyArrayObject*)a) +%#define array_flags(a) PyArray_FLAGS((PyArrayObject*)a) +%#define array_enableflags(a,f) PyArray_ENABLEFLAGS((PyArrayObject*)a,f) +%#define array_clearflags(a,f) PyArray_CLEARFLAGS((PyArrayObject*)a,f) +%#define array_is_fortran(a) (PyArray_IS_F_CONTIGUOUS((PyArrayObject*)a)) +%#endif +%#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS((PyArrayObject*)a)) +%#define array_is_native(a) (PyArray_ISNOTSWAPPED((PyArrayObject*)a)) +} + +/**********************************************************************/ + +%fragment("NumPy_Utilities", + "header") +{ + /* Given a PyObject, return a string describing its type. + */ + const char* pytype_string(PyObject* py_obj) + { + if (py_obj == NULL ) return "C NULL value"; + if (py_obj == Py_None ) return "Python None" ; + if (PyCallable_Check(py_obj)) return "callable" ; + if (PyString_Check( py_obj)) return "string" ; + if (PyInt_Check( py_obj)) return "int" ; + if (PyFloat_Check( py_obj)) return "float" ; + if (PyDict_Check( py_obj)) return "dict" ; + if (PyList_Check( py_obj)) return "list" ; + if (PyTuple_Check( py_obj)) return "tuple" ; +%#if PY_MAJOR_VERSION < 3 + if (PyFile_Check( py_obj)) return "file" ; + if (PyModule_Check( py_obj)) return "module" ; + if (PyInstance_Check(py_obj)) return "instance" ; +%#endif + + return "unknown type"; + } + + /* Given a NumPy typecode, return a string describing the type. + */ + const char* typecode_string(int typecode) + { + static const char* type_names[25] = {"bool", + "byte", + "unsigned byte", + "short", + "unsigned short", + "int", + "unsigned int", + "long", + "unsigned long", + "long long", + "unsigned long long", + "float", + "double", + "long double", + "complex float", + "complex double", + "complex long double", + "object", + "string", + "unicode", + "void", + "ntypes", + "notype", + "char", + "unknown"}; + return typecode < 24 ? type_names[typecode] : type_names[24]; + } + + /* Make sure input has correct numpy type. This now just calls + PyArray_EquivTypenums(). + */ + int type_match(int actual_type, + int desired_type) + { + return PyArray_EquivTypenums(actual_type, desired_type); + } + +%#ifdef SWIGPY_USE_CAPSULE + void free_cap(PyObject * cap) + { + void* array = (void*) PyCapsule_GetPointer(cap,SWIGPY_CAPSULE_NAME); + if (array != NULL) free(array); + } +%#endif + + +} + +/**********************************************************************/ + +%fragment("NumPy_Object_to_Array", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities") +{ + /* Given a PyObject pointer, cast it to a PyArrayObject pointer if + * legal. If not, set the python error string appropriately and + * return NULL. + */ + PyArrayObject* obj_to_array_no_conversion(PyObject* input, + int typecode) + { + PyArrayObject* ary = NULL; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input), typecode))) + { + ary = (PyArrayObject*) input; + } + else if is_array(input) + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = typecode_string(array_type(input)); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. Array of type '%s' given", + desired_type, actual_type); + ary = NULL; + } + else + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = pytype_string(input); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. A '%s' was given", + desired_type, + actual_type); + ary = NULL; + } + return ary; + } + + /* Convert the given PyObject to a NumPy array with the given + * typecode. On success, return a valid PyArrayObject* with the + * correct type. On failure, the python error string will be set and + * the routine returns NULL. + */ + PyArrayObject* obj_to_array_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + PyArrayObject* ary = NULL; + PyObject* py_obj; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input),typecode))) + { + ary = (PyArrayObject*) input; + *is_new_object = 0; + } + else + { + py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_ARRAY_DEFAULT); + /* If NULL, PyArray_FromObject will have set python error value.*/ + ary = (PyArrayObject*) py_obj; + *is_new_object = 1; + } + return ary; + } + + /* Given a PyArrayObject, check to see if it is contiguous. If so, + * return the input pointer and flag it as not a new object. If it is + * not contiguous, create a new PyArrayObject using the original data, + * flag it as a new object and return the pointer. + */ + PyArrayObject* make_contiguous(PyArrayObject* ary, + int* is_new_object, + int min_dims, + int max_dims) + { + PyArrayObject* result; + if (array_is_contiguous(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, + array_type(ary), + min_dims, + max_dims); + *is_new_object = 1; + } + return result; + } + + /* Given a PyArrayObject, check to see if it is Fortran-contiguous. + * If so, return the input pointer, but do not flag it as not a new + * object. If it is not Fortran-contiguous, create a new + * PyArrayObject using the original data, flag it as a new object + * and return the pointer. + */ + PyArrayObject* make_fortran(PyArrayObject* ary, + int* is_new_object) + { + PyArrayObject* result; + if (array_is_fortran(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + Py_INCREF(array_descr(ary)); + result = (PyArrayObject*) PyArray_FromArray(ary, + array_descr(ary), +%#if NPY_API_VERSION < 0x00000007 + NPY_FORTRANORDER); +%#else + NPY_ARRAY_F_CONTIGUOUS); +%#endif + *is_new_object = 1; + } + return result; + } + + /* Convert a given PyObject to a contiguous PyArrayObject of the + * specified type. If the input object is not a contiguous + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_contiguous(ary1, &is_new2, 0, 0); + if ( is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } + + /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the + * specified type. If the input object is not a Fortran-ordered + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_fortran(ary1, &is_new2); + if (is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } +} /* end fragment */ + +/**********************************************************************/ + +%fragment("NumPy_Array_Requirements", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros") +{ + /* Test whether a python object is contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ + int require_contiguous(PyArrayObject* ary) + { + int contiguous = 1; + if (!array_is_contiguous(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must be contiguous. A non-contiguous array was given"); + contiguous = 0; + } + return contiguous; + } + + /* Test whether a python object is (C_ or F_) contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ + int require_c_or_f_contiguous(PyArrayObject* ary) + { + int contiguous = 1; + if (!(array_is_contiguous(ary) || array_is_fortran(ary))) + { + PyErr_SetString(PyExc_TypeError, + "Array must be contiguous (C_ or F_). A non-contiguous array was given"); + contiguous = 0; + } + return contiguous; + } + + /* Require that a numpy array is not byte-swapped. If the array is + * not byte-swapped, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_native(PyArrayObject* ary) + { + int native = 1; + if (!array_is_native(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must have native byteorder. " + "A byte-swapped array was given"); + native = 0; + } + return native; + } + + /* Require the given PyArrayObject to have a specified number of + * dimensions. If the array has the specified number of dimensions, + * return 1. Otherwise, set the python error string and return 0. + */ + int require_dimensions(PyArrayObject* ary, + int exact_dimensions) + { + int success = 1; + if (array_numdims(ary) != exact_dimensions) + { + PyErr_Format(PyExc_TypeError, + "Array must have %d dimensions. Given array has %d dimensions", + exact_dimensions, + array_numdims(ary)); + success = 0; + } + return success; + } + + /* Require the given PyArrayObject to have one of a list of specified + * number of dimensions. If the array has one of the specified number + * of dimensions, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_dimensions_n(PyArrayObject* ary, + int* exact_dimensions, + int n) + { + int success = 0; + int i; + char dims_str[255] = ""; + char s[255]; + for (i = 0; i < n && !success; i++) + { + if (array_numdims(ary) == exact_dimensions[i]) + { + success = 1; + } + } + if (!success) + { + for (i = 0; i < n-1; i++) + { + sprintf(s, "%d, ", exact_dimensions[i]); + strcat(dims_str,s); + } + sprintf(s, " or %d", exact_dimensions[n-1]); + strcat(dims_str,s); + PyErr_Format(PyExc_TypeError, + "Array must have %s dimensions. Given array has %d dimensions", + dims_str, + array_numdims(ary)); + } + return success; + } + + /* Require the given PyArrayObject to have a specified shape. If the + * array has the specified shape, return 1. Otherwise, set the python + * error string and return 0. + */ + int require_size(PyArrayObject* ary, + npy_intp* size, + int n) + { + int i; + int success = 1; + size_t len; + char desired_dims[255] = "["; + char s[255]; + char actual_dims[255] = "["; + for(i=0; i < n;i++) + { + if (size[i] != -1 && size[i] != array_size(ary,i)) + { + success = 0; + } + } + if (!success) + { + for (i = 0; i < n; i++) + { + if (size[i] == -1) + { + sprintf(s, "*,"); + } + else + { + sprintf(s, "%ld,", (long int)size[i]); + } + strcat(desired_dims,s); + } + len = strlen(desired_dims); + desired_dims[len-1] = ']'; + for (i = 0; i < n; i++) + { + sprintf(s, "%ld,", (long int)array_size(ary,i)); + strcat(actual_dims,s); + } + len = strlen(actual_dims); + actual_dims[len-1] = ']'; + PyErr_Format(PyExc_TypeError, + "Array must have shape of %s. Given array has shape of %s", + desired_dims, + actual_dims); + } + return success; + } + + /* Require the given PyArrayObject to to be Fortran ordered. If the + * the PyArrayObject is already Fortran ordered, do nothing. Else, + * set the Fortran ordering flag and recompute the strides. + */ + int require_fortran(PyArrayObject* ary) + { + int success = 1; + int nd = array_numdims(ary); + int i; + npy_intp * strides = array_strides(ary); + if (array_is_fortran(ary)) return success; + int n_non_one = 0; + /* Set the Fortran ordered flag */ + const npy_intp *dims = array_dimensions(ary); + for (i=0; i < nd; ++i) + n_non_one += (dims[i] != 1) ? 1 : 0; + if (n_non_one > 1) + array_clearflags(ary,NPY_ARRAY_CARRAY); + array_enableflags(ary,NPY_ARRAY_FARRAY); + /* Recompute the strides */ + strides[0] = strides[nd-1]; + for (i=1; i < nd; ++i) + strides[i] = strides[i-1] * array_size(ary,i-1); + return success; + } +} + +/* Combine all NumPy fragments into one for convenience */ +%fragment("NumPy_Fragments", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities", + fragment="NumPy_Object_to_Array", + fragment="NumPy_Array_Requirements") +{ +} + +/* End John Hunter translation (with modifications by Bill Spotz) + */ + +/* %numpy_typemaps() macro + * + * This macro defines a family of 75 typemaps that allow C arguments + * of the form + * + * 1. (DATA_TYPE IN_ARRAY1[ANY]) + * 2. (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + * 3. (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + * + * 4. (DATA_TYPE IN_ARRAY2[ANY][ANY]) + * 5. (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 6. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + * 7. (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 8. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + * + * 9. (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + * 10. (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 11. (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 12. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + * 13. (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 14. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + * + * 15. (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + * 16. (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 17. (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 18. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + * 19. (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 20. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + * + * 21. (DATA_TYPE INPLACE_ARRAY1[ANY]) + * 22. (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + * 23. (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + * + * 24. (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + * 25. (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 26. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + * 27. (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 28. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + * + * 29. (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + * 30. (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 31. (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 32. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + * 33. (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 34. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + * + * 35. (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + * 36. (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 37. (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 38. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + * 39. (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 40. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + * + * 41. (DATA_TYPE ARGOUT_ARRAY1[ANY]) + * 42. (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + * 43. (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + * + * 44. (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + * + * 45. (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + * + * 46. (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + * + * 47. (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + * 48. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + * + * 49. (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 50. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + * 51. (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 52. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + * + * 53. (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 54. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + * 55. (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 56. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) + * + * 57. (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 58. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) + * 59. (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 60. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) + * + * 61. (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + * 62. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + * + * 63. (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 64. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + * 65. (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 66. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + * + * 67. (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 68. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) + * 69. (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 70. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) + * + * 71. (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 72. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) + * 73. (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 74. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) + * + * 75. (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) + * + * where "DATA_TYPE" is any type supported by the NumPy module, and + * "DIM_TYPE" is any int-like type suitable for specifying dimensions. + * The difference between "ARRAY" typemaps and "FARRAY" typemaps is + * that the "FARRAY" typemaps expect Fortran ordering of + * multidimensional arrays. In python, the dimensions will not need + * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1" + * typemaps). The IN_ARRAYs can be a numpy array or any sequence that + * can be converted to a numpy array of the specified type. The + * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The + * ARGOUT_ARRAYs will be returned as new numpy arrays of the + * appropriate type. + * + * These typemaps can be applied to existing functions using the + * %apply directive. For example: + * + * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)}; + * double prod(double* series, int length); + * + * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) + * {(int rows, int cols, double* matrix )}; + * void floor(int rows, int cols, double* matrix, double f); + * + * %apply (double IN_ARRAY3[ANY][ANY][ANY]) + * {(double tensor[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double low[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double upp[2][2][2] )}; + * void luSplit(double tensor[2][2][2], + * double low[2][2][2], + * double upp[2][2][2] ); + * + * or directly with + * + * double prod(double* IN_ARRAY1, int DIM1); + * + * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f); + * + * void luSplit(double IN_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY]); + */ + +%define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) + +/************************/ +/* Input Array Typemaps */ +/************************/ + +/* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY1[ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY1[ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY1[ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = {-1}; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 2)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 3)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/***************************/ +/* In-Place Array Typemaps */ +/***************************/ + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY1[ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY1[ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int i=1) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = 1; + for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + (PyArrayObject* array=NULL, int i=0) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = 1; + for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i); + $2 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 2) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_size(array, size, 4) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 3) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* INPLACE_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/*************************/ +/* Argout Array Typemaps */ +/*************************/ + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY1[ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[1] = { $1_dim0 }; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY1[ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $2 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $2; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $1 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $1; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[2] = { $1_dim0, $1_dim1 }; + array = PyArray_SimpleNew(2, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = PyArray_SimpleNew(3, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[4] = { $1_dim0, $1_dim1, $1_dim2, $1_dim3 }; + array = PyArray_SimpleNew(4, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/*****************************/ +/* Argoutview Array Typemaps */ +/*****************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEW_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/*************************************/ +/* Managed Argoutview Array Typemaps */ +/*************************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEWM_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj= PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/**************************************/ +/* In-Place Array Typemap - flattened */ +/**************************************/ + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) + (PyArrayObject* array=NULL, int i=1) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_c_or_f_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = 1; + for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); +} + +%enddef /* %numpy_typemaps() macro */ +/* *************************************************************** */ + +/* Concrete instances of the %numpy_typemaps() macro: Each invocation + * below applies all of the typemaps above to the specified data type. + */ +%numpy_typemaps(signed char , NPY_BYTE , int) +%numpy_typemaps(unsigned char , NPY_UBYTE , int) +%numpy_typemaps(short , NPY_SHORT , int) +%numpy_typemaps(unsigned short , NPY_USHORT , int) +%numpy_typemaps(int , NPY_INT , int) +%numpy_typemaps(unsigned int , NPY_UINT , int) +%numpy_typemaps(long , NPY_LONG , int) +%numpy_typemaps(unsigned long , NPY_ULONG , int) +%numpy_typemaps(long long , NPY_LONGLONG , int) +%numpy_typemaps(unsigned long long, NPY_ULONGLONG, int) +%numpy_typemaps(float , NPY_FLOAT , int) +%numpy_typemaps(double , NPY_DOUBLE , int) +%numpy_typemaps(int8_t , NPY_INT8 , int) +%numpy_typemaps(int16_t , NPY_INT16 , int) +%numpy_typemaps(int32_t , NPY_INT32 , int) +%numpy_typemaps(int64_t , NPY_INT64 , int) +%numpy_typemaps(uint8_t , NPY_UINT8 , int) +%numpy_typemaps(uint16_t , NPY_UINT16 , int) +%numpy_typemaps(uint32_t , NPY_UINT32 , int) +%numpy_typemaps(uint64_t , NPY_UINT64 , int) + + +/* *************************************************************** + * The follow macro expansion does not work, because C++ bool is 4 + * bytes and NPY_BOOL is 1 byte + * + * %numpy_typemaps(bool, NPY_BOOL, int) + */ + +/* *************************************************************** + * On my Mac, I get the following warning for this macro expansion: + * 'swig/python detected a memory leak of type 'long double *', no destructor found.' + * + * %numpy_typemaps(long double, NPY_LONGDOUBLE, int) + */ + +#ifdef __cplusplus + +%include <std_complex.i> + +%numpy_typemaps(std::complex<float>, NPY_CFLOAT , int) +%numpy_typemaps(std::complex<double>, NPY_CDOUBLE, int) + +#endif + +#endif /* SWIGPYTHON */ diff --git a/cpp/NeighbourhoodTriMeshIntegrator/swig_it b/cpp/NeighbourhoodTriMeshIntegrator/swig_it new file mode 100644 index 0000000..99461e7 --- /dev/null +++ b/cpp/NeighbourhoodTriMeshIntegrator/swig_it @@ -0,0 +1,4 @@ +swig -Wall -python -c++ NeighbourhoodTriMeshIntegrator.i +g++ -O3 -fPIC -fopenmp -lstdc++ -c c_NeighbourhoodTriMeshIntegrator.cpp +g++ -O3 -fPIC -fopenmp -lstdc++ -c NeighbourhoodTriMeshIntegrator_wrap.cxx -I/usr/include/python3.7 -I/usr/lib/python3.7/site-packages/numpy/core/include +g++ -shared c_NeighbourhoodTriMeshIntegrator.o NeighbourhoodTriMeshIntegrator_wrap.o -fopenmp -O3 -lstdc++ -o _NeighbourhoodTriMeshIntegrator.so diff --git a/examples.py b/examples.py index d97f8cf..8386225 100644 --- a/examples.py +++ b/examples.py @@ -2,7 +2,7 @@ import numpy as np import matplotlib.pyplot as plt from RandomRotations import RandomRotationMatrix -from RPSM import measure_interior, measure_exterior +from src import measure_interior, measure_exterior def Test_Cube_Integration_Interior(do_plots): -- GitLab