/ src / gmpy2_vector.c
gmpy2_vector.c
  1  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2   * gmpy2_vector.c                                                          *
  3   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  4   * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision   *
  5   * libraries.                                                              *
  6   *                                                                         *
  7   * Copyright 2000 - 2009 Alex Martelli                                     *
  8   *                                                                         *
  9   * Copyright 2008 - 2021 Case Van Horsen                                   *
 10   *                                                                         *
 11   * This file is part of GMPY2.                                             *
 12   *                                                                         *
 13   * GMPY2 is free software: you can redistribute it and/or modify it under  *
 14   * the terms of the GNU Lesser General Public License as published by the  *
 15   * Free Software Foundation, either version 3 of the License, or (at your  *
 16   * option) any later version.                                              *
 17   *                                                                         *
 18   * GMPY2 is distributed in the hope that it will be useful, but WITHOUT    *
 19   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   *
 20   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public    *
 21   * License for more details.                                               *
 22   *                                                                         *
 23   * You should have received a copy of the GNU Lesser General Public        *
 24   * License along with GMPY2; if not, see <http://www.gnu.org/licenses/>    *
 25   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 26  
 27  /* The following code was a test case for creating a gmpy2 function that would
 28   * apply an MPFR function to all the elements of a list. It was slightly faster
 29   * than map(gmpy2.list, <<list>>) but not enough to justify the effort. The
 30   * code is left for possible future use.
 31   */
 32  
 33  PyDoc_STRVAR(GMPy_doc_function_vector,
 34  "vector(iterable) -> list\n\n"
 35  "Template for applying a function to an iterable.");
 36  
 37  PyDoc_STRVAR(GMPy_doc_context_vector,
 38  "vector(iterable) -> list\n\n"
 39  "Template for applying a function to an iterable.");
 40  
 41  static PyObject *
 42  GMPy_Context_Vector(PyObject *self, PyObject *other)
 43  {
 44      PyObject *result, *tempres;
 45      Py_ssize_t i, seq_length;
 46  
 47      CTXT_Object *context = NULL;
 48  
 49      if (self && CTXT_Check(self)) {
 50          context = (CTXT_Object*)self;
 51      }
 52      else {
 53          CHECK_CONTEXT(context);
 54      }
 55  
 56      if (!(other = PySequence_List(other))) {
 57          TYPE_ERROR("argument must be an iterable");
 58          return NULL;
 59      }
 60  
 61      /* other contains a new list containing all the values from the
 62       * iterable. Create a list to store the results.
 63       */
 64  
 65      seq_length = PyList_GET_SIZE(other);
 66      if (!(result = PyList_New(seq_length))) {
 67          Py_DECREF(other);
 68          return NULL;
 69      }
 70  
 71      /* Iterate through the list. */
 72  
 73      for (i=0; i < seq_length; i++) {
 74          if (!(tempres = GMPy_Number_Sin(PyList_GET_ITEM(other, i), context))) {
 75              Py_DECREF(other);
 76              Py_DECREF(result);
 77              TYPE_ERROR("all items in iterable must be numbers");
 78              return NULL;
 79          }
 80  
 81          if (PyList_SetItem(result, i, tempres) < 0) {
 82              Py_DECREF(other);
 83              Py_DECREF(result);
 84              return NULL;
 85          }
 86      }
 87  
 88      Py_DECREF(other);
 89  
 90      return (PyObject*)result;
 91  }
 92  
 93  PyDoc_STRVAR(GMPy_doc_function_vector2,
 94  "vector2(iterable, iterable) -> list\n\n"
 95  "Template for applying a function to a pair of iterables.");
 96  
 97  PyDoc_STRVAR(GMPy_doc_context_vector2,
 98  "vector2(iterable) -> list\n\n"
 99  "Template for applying a function to a pair of iterables.");
100  
101  static PyObject *
102  GMPy_Context_Vector2(PyObject *self, PyObject *args)
103  {
104      PyObject *arg1, *arg2, *result;
105      MPFR_Object *tempres;
106  
107      Py_ssize_t i, seq_length;
108  
109      CTXT_Object *context = NULL;
110  
111      if (self && CTXT_Check(self)) {
112          context = (CTXT_Object*)self;
113      }
114      else {
115          CHECK_CONTEXT(context);
116      }
117  
118      if (PyTuple_GET_SIZE(args) != 2) {
119          TYPE_ERROR("vector2() requires 2 arguments");
120          return NULL;
121      }
122  
123      if (!(arg1 = PySequence_List(PyTuple_GET_ITEM(args, 0)))) {
124          TYPE_ERROR("argument must be an iterable");
125          return NULL;
126      }
127  
128      if (!(arg2 = PySequence_List(PyTuple_GET_ITEM(args, 1)))) {
129          Py_DECREF(arg1);
130          TYPE_ERROR("argument must be an iterable");
131          return NULL;
132      }
133  
134  
135      /* other contains a new list containing all the values from the
136       * iterable. Create a list to store the results.
137       */
138  
139      if (PyList_GET_SIZE(arg1) != PyList_GET_SIZE(arg2)) {
140          Py_DECREF(arg1);
141          Py_DECREF(arg2);
142          TYPE_ERROR("arguments must be the same length");
143          return NULL;
144      }
145  
146      seq_length = PyList_GET_SIZE(arg1);
147      if (!(result = PyList_New(seq_length))) {
148          Py_DECREF(arg1);
149          Py_DECREF(arg2);
150          return NULL;
151      }
152  
153      /* Iterate through the list. */
154  
155      for (i=0; i < seq_length; i++) {
156          //~ if (!(tempres = GMPy_Number_Mul(PyList_GET_ITEM(arg1, i),
157                                          //~ PyList_GET_ITEM(arg2, i),
158                                          //~ context))) {
159              //~ Py_DECREF(arg1);
160              //~ Py_DECREF(arg2);
161              //~ Py_DECREF(result);
162              //~ TYPE_ERROR("all items in iterable must be numbers");
163              //~ return NULL;
164          //~ }
165  
166          tempres = GMPy_MPFR_New(0, context);
167          tempres->rc = mpfr_mul(tempres->f,
168                                 MPFR(PyList_GET_ITEM(arg1, i)),
169                                 MPFR(PyList_GET_ITEM(arg2, i)),
170                                 GET_MPFR_ROUND(context));
171  
172          if (PyList_SetItem(result, i, (PyObject*)tempres) < 0) {
173              Py_DECREF(arg1);
174              Py_DECREF(arg2);
175              Py_DECREF(result);
176              return NULL;
177          }
178      }
179  
180      Py_DECREF(arg1);
181      Py_DECREF(arg2);
182  
183      return (PyObject*)result;
184  }