/ src / gmpy2_sign.c
gmpy2_sign.c
  1  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2   * gmpy2_sign.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  static PyObject *
 28  GMPy_Integer_Sign(PyObject *x, CTXT_Object *context)
 29  {
 30      long res;
 31      MPZ_Object *tempx;
 32  
 33      if (!(tempx = GMPy_MPZ_From_Integer(x, context))) {
 34          return NULL;
 35      }
 36      else {
 37          res = mpz_sgn(tempx->z);
 38          Py_DECREF((PyObject*)tempx);
 39          return PyIntOrLong_FromLong(res);
 40      }
 41  }
 42  
 43  static PyObject *
 44  GMPy_Rational_Sign(PyObject *x, CTXT_Object *context)
 45  {
 46      long res;
 47      MPQ_Object *tempx;
 48  
 49      if (!(tempx = GMPy_MPQ_From_Rational(x, context))) {
 50          return NULL;
 51      }
 52      else {
 53          res = mpq_sgn(tempx->q);
 54          Py_DECREF((PyObject*)tempx);
 55          return PyIntOrLong_FromLong(res);
 56      }
 57  }
 58  
 59  static PyObject *
 60  GMPy_Real_Sign(PyObject *x, CTXT_Object *context)
 61  {
 62      long sign;
 63      MPFR_Object *tempx;
 64      PyObject *result;
 65  
 66      CHECK_CONTEXT(context);
 67  
 68      if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
 69          return NULL;
 70      }
 71      else {
 72          mpfr_clear_flags();
 73          sign = mpfr_sgn(tempx->f);
 74          Py_DECREF((PyObject*)tempx);
 75          result = PyIntOrLong_FromLong(sign);
 76          GMPY_CHECK_ERANGE(result, context, "sign() of invalid value (NaN)");
 77          return result;
 78      }
 79  }
 80  
 81  static PyObject *
 82  GMPy_Number_Sign(PyObject *x, CTXT_Object *context)
 83  {
 84      if (IS_INTEGER(x))
 85          return GMPy_Integer_Sign(x, context);
 86      else if (IS_RATIONAL_ONLY(x))
 87          return GMPy_Rational_Sign(x, context);
 88      else if (IS_REAL_ONLY(x))
 89          return GMPy_Real_Sign(x, context);
 90  
 91      TYPE_ERROR("sign() argument type not supported");
 92      return NULL;
 93  }
 94  
 95  PyDoc_STRVAR(GMPy_doc_function_sign,
 96  "sign(x) -> number\n\n"
 97  "Return -1 if x < 0, 0 if x == 0, or +1 if x >0.");
 98  
 99  static PyObject *
100  GMPy_Context_Sign(PyObject *self, PyObject *other)
101  {
102      CTXT_Object *context = NULL;
103  
104      if (self && CTXT_Check(self)) {
105          context = (CTXT_Object*)self;
106      }
107      else {
108          CHECK_CONTEXT(context);
109      }
110  
111      return GMPy_Number_Sign(other, context);
112  }