diff options
author | wfspotz@sandia.gov <wfspotz@sandia.gov@localhost> | 2007-04-01 02:31:40 +0000 |
---|---|---|
committer | wfspotz@sandia.gov <wfspotz@sandia.gov@localhost> | 2007-04-01 02:31:40 +0000 |
commit | 020c1ddab8f82c2692efceec9c11877cd5863c96 (patch) | |
tree | 7956396462d812d0820f245fc5a8c4b7338446fb /numpy/doc/swig | |
parent | fd85bb29c7f18dbae1fbfe439b692fce7d4e7618 (diff) | |
download | numpy-020c1ddab8f82c2692efceec9c11877cd5863c96.tar.gz |
Added (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) and (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) typemaps, and tests, and documentation
Diffstat (limited to 'numpy/doc/swig')
-rw-r--r-- | numpy/doc/swig/Series.i | 2 | ||||
-rw-r--r-- | numpy/doc/swig/numpy.i | 94 | ||||
-rw-r--r-- | numpy/doc/swig/numpy_swig.html | 23 | ||||
-rw-r--r-- | numpy/doc/swig/numpy_swig.pdf | bin | 125477 -> 126706 bytes | |||
-rw-r--r-- | numpy/doc/swig/numpy_swig.txt | 23 | ||||
-rw-r--r-- | numpy/doc/swig/series.cxx | 8 | ||||
-rw-r--r-- | numpy/doc/swig/series.h | 4 | ||||
-rwxr-xr-x | numpy/doc/swig/testSeries.py | 120 |
8 files changed, 249 insertions, 25 deletions
diff --git a/numpy/doc/swig/Series.i b/numpy/doc/swig/Series.i index 08041ad09..11cb1c3da 100644 --- a/numpy/doc/swig/Series.i +++ b/numpy/doc/swig/Series.i @@ -25,6 +25,8 @@ %apply (TYPE ARGOUT_ARRAY1[ANY]) {(TYPE even[3])}; %apply (TYPE ARGOUT_ARRAY1[ANY]) {(TYPE odd[ 3])}; +%apply (TYPE* ARGOUT_ARRAY1, int DIM1) {(TYPE* twoVec, int size)}; +%apply (int DIM1, TYPE* ARGOUT_ARRAY1) {(int size, TYPE* threeVec)}; %apply (TYPE IN_ARRAY2[ANY][ANY]) {(TYPE matrix[ANY][ANY])}; %apply (TYPE* IN_ARRAY2, int DIM1, int DIM2) {(TYPE* matrix, int rows, int cols)}; diff --git a/numpy/doc/swig/numpy.i b/numpy/doc/swig/numpy.i index 656ed98f3..8996ac44f 100644 --- a/numpy/doc/swig/numpy.i +++ b/numpy/doc/swig/numpy.i @@ -315,21 +315,25 @@ int require_size(PyArrayObject* ary, npy_intp* size, int n) { * (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) * (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) * - * (DATA_TYPE IN_ARRAY2[ANY][ANY]) + * (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) * (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) * (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) * * (DATA_TYPE ARGOUT_ARRAY1[ANY]) + * (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + * (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) * * (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) * - * where "DATA_TYPE" is any type supported by the NumPy module. In python, - * the dimensions will not need to be specified. 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 numpy arrays of the appropriate type. - + * where "DATA_TYPE" is any type supported by the NumPy module, and + * "DIM_TYPE" is any int-like type suitable for specifying dimensions. + * 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 numpy + * arrays of the appropriate type. + * * These typemaps can be applied to existing functions using the * %apply directive: * @@ -369,11 +373,21 @@ int require_size(PyArrayObject* ary, npy_intp* size, int n) { * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) {(int rows, int cols, double* matrix)}; * void ceil(int rows, int cols, double* matrix); * - * %apply (double ARGOUT_ARRAY1[ANY] {(double series[int length])}; - * void negate(double* series, int length); + * %apply (double IN_ARRAY1[ANY] ) {(double vector[ANY])}; + * %apply (double ARGOUT_ARRAY1[ANY]) {(double even[ 3])}; + * %apply (double ARGOUT_ARRAY1[ANY]) {(double odd[ 3])}; + * void eoSplit(double vector[3], double even[3], double odd[3]); + * + * %apply (double* ARGOUT_ARRAY1, int DIM1) {(double* twoVec, int size)}; + * void twos(double* twoVec, int size); * - * %apply (double ARGOUT_ARRAY2[ANY][ANY]) {(double matrix[int rows][int cols])}; - * void normalize(double* matrix, int rows, int cols); + * %apply (int DIM1, double* ARGOUT_ARRAY1) {(int size, double* threeVec)}; + * void threes(int size, double* threeVec); + * + * %apply (double IN_ARRAY2[ANY][ANY]) {(double matrix[2][2])}; + * %apply (double ARGOUT_ARRAY2[ANY][ANY]) {(double upper[ 3][3])}; + * %apply (double ARGOUT_ARRAY2[ANY][ANY]) {(double lower[ 3][3])}; + * void luSplit(double matrix[3][3], double upper[3][3], double lower[3][3]); * * or directly with * @@ -393,9 +407,13 @@ int require_size(PyArrayObject* ary, npy_intp* size, int n) { * void floor(double* INPLACE_ARRAY2, int DIM1, int DIM2, double floor); * void ceil( int DIM1, int DIM2, double* INPLACE_ARRAY2, double ceil ); * - * void negate(double ARGOUT_ARRAY1[ANY]); + * void eoSplit(double IN_ARRAY1[ANY], double ARGOUT_ARRAY1[ANY], + * double ARGOUT_ARRAY1[ANY]); + * void twos(double* ARGOUT_ARRAY1, int DIM1) + * void threes(int DIM1, double* ARGOUT_ARRAY1) * - * void normalize(double ARGOUT_ARRAY2[ANY][ANY]); + * void luSplit(double IN_ARRAY2[ANY][ANY], double ARGOUT_ARRAY2[ANY][ANY], + * double ARGOUT_ARRAY2[ANY][ANY]); */ %define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) @@ -630,6 +648,54 @@ int require_size(PyArrayObject* ary, npy_intp* size, int n) { $result = SWIG_Python_AppendOutput($result,array$argnum); } +/* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + */ +%typemap(in,numinputs=1) + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + (PyObject * array = NULL) +{ + if (!PyInt_Check($input)) { + char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $2 = (DIM_TYPE) PyInt_AsLong($input); + npy_intp dims[1] = { (npy_intp) $2 }; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + $1 = (DATA_TYPE*)((PyArrayObject*)array)->data; +} +%typemap(argout) + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) +{ + $result = SWIG_Python_AppendOutput($result,array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + */ +%typemap(in,numinputs=1) + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + (PyObject * array = NULL) +{ + if (!PyInt_Check($input)) { + char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $1 = (DIM_TYPE) PyInt_AsLong($input); + npy_intp dims[1] = { (npy_intp) $1 }; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + $2 = (DATA_TYPE*)((PyArrayObject*)array)->data; +} +%typemap(argout) + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) +{ + $result = SWIG_Python_AppendOutput($result,array$argnum); +} + /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) */ %typemap(in,numinputs=0) diff --git a/numpy/doc/swig/numpy_swig.html b/numpy/doc/swig/numpy_swig.html index 2f581393f..12dbe8f59 100644 --- a/numpy/doc/swig/numpy_swig.html +++ b/numpy/doc/swig/numpy_swig.html @@ -528,17 +528,28 @@ signatures are</p> are in fact output arrays. This pattern occurs often when there is more than one output variable and the single return argument is therefore not sufficient. In <a class="reference" href="http://www.python.org">python</a>, the convential way to return -multiple arguments is to pack them into a tuple and return the tuple. -This is what the argout typemaps do. If a wrapped function that uses -these argout typemaps has more than one return argument, they are so -packed. The <a class="reference" href="http://www.python.org">python</a> user does not pass these arrays in, they simply -get returned. The argout signatures are</p> +multiple arguments is to pack them into a sequence (tuple, list, etc.) +and return the sequence. This is what the argout typemaps do. If a +wrapped function that uses these argout typemaps has more than one +return argument, they are packed into a tuple or list, depending on +the version of <a class="reference" href="http://www.python.org">python</a>. The <a class="reference" href="http://www.python.org">python</a> user does not pass these +arrays in, they simply get returned. The argout signatures are</p> <blockquote> <ul class="simple"> <li><tt class="docutils literal"><span class="pre">(DATA_TYPE</span> <span class="pre">ARGOUT_ARRAY1[ANY])</span></tt></li> +<li><tt class="docutils literal"><span class="pre">(DATA_TYPE*</span> <span class="pre">ARGOUT_ARRAY1,</span> <span class="pre">int</span> <span class="pre">DIM1)</span></tt></li> +<li><tt class="docutils literal"><span class="pre">(int</span> <span class="pre">DIM1,</span> <span class="pre">DATA_TYPE*</span> <span class="pre">ARGOUT_ARRAY1)</span></tt></li> <li><tt class="docutils literal"><span class="pre">(DATA_TYPE</span> <span class="pre">ARGOUT_ARRAY2[ANY][ANY])</span></tt></li> </ul> </blockquote> +<p>These are typically used in situations where in C/C++, you would +allocate a(n) array(s) on the heap, and call the function to fill the +array(s) values. In python, the arrays are allocated for you and +returned as new array objects.</p> +<p>Note that we support <tt class="docutils literal"><span class="pre">DATA_TYPE*</span></tt> argout typemaps in 1D, but not +2D. This because of a quirk with the <a class="reference" href="http://www.swig.org">SWIG</a> typemap syntax and +cannot be avoided. Note that for these types of 1D typemaps, the +python function will take a single argument representing <tt class="docutils literal"><span class="pre">DIM1</span></tt>.</p> </div> <div class="section"> <h2><a class="toc-backref" href="#id7" id="output-arrays" name="output-arrays">Output Arrays</a></h2> @@ -803,7 +814,7 @@ Their work has made this end result possible.</p> </div> <div class="footer"> <hr class="footer" /> -Generated on: 2007-03-29 20:45 UTC. +Generated on: 2007-04-01 02:30 UTC. Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source. </div> diff --git a/numpy/doc/swig/numpy_swig.pdf b/numpy/doc/swig/numpy_swig.pdf Binary files differindex 5f8678e5e..00b7aad77 100644 --- a/numpy/doc/swig/numpy_swig.pdf +++ b/numpy/doc/swig/numpy_swig.pdf diff --git a/numpy/doc/swig/numpy_swig.txt b/numpy/doc/swig/numpy_swig.txt index c3b5db6c6..ee1bf1f99 100644 --- a/numpy/doc/swig/numpy_swig.txt +++ b/numpy/doc/swig/numpy_swig.txt @@ -209,15 +209,28 @@ Argout arrays are arrays that appear in the input arguments in C, but are in fact output arrays. This pattern occurs often when there is more than one output variable and the single return argument is therefore not sufficient. In `python`_, the convential way to return -multiple arguments is to pack them into a tuple and return the tuple. -This is what the argout typemaps do. If a wrapped function that uses -these argout typemaps has more than one return argument, they are so -packed. The `python`_ user does not pass these arrays in, they simply -get returned. The argout signatures are +multiple arguments is to pack them into a sequence (tuple, list, etc.) +and return the sequence. This is what the argout typemaps do. If a +wrapped function that uses these argout typemaps has more than one +return argument, they are packed into a tuple or list, depending on +the version of `python`_. The `python`_ user does not pass these +arrays in, they simply get returned. The argout signatures are * ``(DATA_TYPE ARGOUT_ARRAY1[ANY])`` + * ``(DATA_TYPE* ARGOUT_ARRAY1, int DIM1)`` + * ``(int DIM1, DATA_TYPE* ARGOUT_ARRAY1)`` * ``(DATA_TYPE ARGOUT_ARRAY2[ANY][ANY])`` +These are typically used in situations where in C/C++, you would +allocate a(n) array(s) on the heap, and call the function to fill the +array(s) values. In python, the arrays are allocated for you and +returned as new array objects. + +Note that we support ``DATA_TYPE*`` argout typemaps in 1D, but not +2D. This because of a quirk with the `SWIG`_ typemap syntax and +cannot be avoided. Note that for these types of 1D typemaps, the +python function will take a single argument representing ``DIM1``. + Output Arrays ------------- diff --git a/numpy/doc/swig/series.cxx b/numpy/doc/swig/series.cxx index 6d51c0ae6..7f691c405 100644 --- a/numpy/doc/swig/series.cxx +++ b/numpy/doc/swig/series.cxx @@ -87,6 +87,14 @@ void SNAME ## EOSplit(TYPE vector[3], TYPE even[3], TYPE odd[3]) { \ } \ } \ \ +void SNAME ## Twos(TYPE* twoVec, int size) { \ + for (int i=0; i<size; ++i) twoVec[i] = 2; \ +} \ +\ +void SNAME ## Threes(int size, TYPE* threeVec) { \ + for (int i=0; i<size; ++i) threeVec[i] = 3; \ +} \ +\ TYPE SNAME ## Det(TYPE matrix[2][2]) { \ return matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]; \ } \ diff --git a/numpy/doc/swig/series.h b/numpy/doc/swig/series.h index 60e8515aa..29c6ea951 100644 --- a/numpy/doc/swig/series.h +++ b/numpy/doc/swig/series.h @@ -32,6 +32,8 @@ // * 1D in-place arrays // * 1D in-place arrays, data last // * 1D argout arrays, hard-coded length +// * 1D argout arrays +// * 1D argout arrays, data last // * 2D input arrays, hard-coded lengths // * 2D input arrays // * 2D input arrays, data last @@ -49,6 +51,8 @@ void SNAME ## Reverse( TYPE array[3]); \ void SNAME ## Ones( TYPE * array, int size); \ void SNAME ## Zeros( int size, TYPE * array); \ void SNAME ## EOSplit( TYPE vector[3], TYPE even[3], TYPE odd[3]); \ +void SNAME ## Twos( TYPE * twoVec, int size); \ +void SNAME ## Threes( int size, TYPE * threeVec); \ TYPE SNAME ## Det( TYPE matrix[2][2]); \ TYPE SNAME ## Max( TYPE * matrix, int rows, int cols); \ TYPE SNAME ## Min( int rows, int cols, TYPE * matrix); \ diff --git a/numpy/doc/swig/testSeries.py b/numpy/doc/swig/testSeries.py index c756f8700..e5631f98b 100755 --- a/numpy/doc/swig/testSeries.py +++ b/numpy/doc/swig/testSeries.py @@ -68,6 +68,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testScharTwos(self): + "Test scharTwos function" + twos = Series.scharTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testScharThrees(self): + "Test scharThrees function" + threes = Series.scharThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testScharDet(self): "Test scharDet function" matrix = [[6,7],[8,9]] @@ -161,6 +171,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testUcharTwos(self): + "Test ucharTwos function" + twos = Series.ucharTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testUcharThrees(self): + "Test ucharThrees function" + threes = Series.ucharThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testUcharDet(self): "Test ucharDet function" matrix = [[7,6],[9,8]] @@ -254,6 +274,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testShortTwos(self): + "Test shortTwos function" + twos = Series.shortTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testShortThrees(self): + "Test shortThrees function" + threes = Series.shortThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testShortDet(self): "Test shortDet function" matrix = [[6,7],[8,9]] @@ -347,6 +377,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testUshortTwos(self): + "Test ushortTwos function" + twos = Series.ushortTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testUshortThrees(self): + "Test ushortThrees function" + threes = Series.ushortThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testUshortDet(self): "Test ushortDet function" matrix = [[7,6],[9,8]] @@ -440,6 +480,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testIntTwos(self): + "Test intTwos function" + twos = Series.intTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testIntThrees(self): + "Test intThrees function" + threes = Series.intThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testIntDet(self): "Test intDet function" matrix = [[6,7],[8,9]] @@ -534,6 +584,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testUintTwos(self): + "Test uintTwos function" + twos = Series.uintTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testUintThrees(self): + "Test uintThrees function" + threes = Series.uintThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testUintDet(self): "Test uintDet function" matrix = [[7,6],[9,8]] @@ -627,6 +687,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testLongTwos(self): + "Test longTwos function" + twos = Series.longTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testLongThrees(self): + "Test longThrees function" + threes = Series.longThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testLongDet(self): "Test longDet function" matrix = [[6,7],[8,9]] @@ -720,6 +790,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testUlongTwos(self): + "Test ulongTwos function" + twos = Series.ulongTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testUlongThrees(self): + "Test ulongThrees function" + threes = Series.ulongThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testUlongDet(self): "Test ulongDet function" matrix = [[7,6],[9,8]] @@ -813,6 +893,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testLongLongTwos(self): + "Test longLongTwos function" + twos = Series.longLongTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testLongLongThrees(self): + "Test longLongThrees function" + threes = Series.longLongThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testLongLongDet(self): "Test longLongDet function" matrix = [[6,7],[8,9]] @@ -906,6 +996,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testUlongLongTwos(self): + "Test ulongLongTwos function" + twos = Series.ulongLongTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testUlongLongThrees(self): + "Test ulongLongThrees function" + threes = Series.ulongLongThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testUlongLongDet(self): "Test ulongLongDet function" matrix = [[7,6],[9,8]] @@ -1008,6 +1108,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testFloatTwos(self): + "Test floatTwos function" + twos = Series.floatTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testFloatThrees(self): + "Test floatThrees function" + threes = Series.floatThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testFloatMax(self): "Test floatMax function" matrix = [[-6,5,-4],[3.14,-2.718,1]] @@ -1100,6 +1210,16 @@ class SeriesTestCase(unittest.TestCase): self.assertEquals((even == [1,0,3]).all(), True) self.assertEquals((odd == [0,2,0]).all(), True) + def testDoubleTwos(self): + "Test doubleTwos function" + twos = Series.doubleTwos(5) + self.assertEquals((twos == [2,2,2,2,2]).all(), True) + + def testDoubleThrees(self): + "Test doubleThrees function" + threes = Series.doubleThrees(6) + self.assertEquals((threes == [3,3,3,3,3,3]).all(), True) + def testDoubleDet(self): "Test doubleDet function" matrix = [[6,7],[8,9]] |