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 *
GMPy_Integer_Sign(PyObject * x,CTXT_Object * context)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 *
GMPy_Rational_Sign(PyObject * x,CTXT_Object * context)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 *
GMPy_Real_Sign(PyObject * x,CTXT_Object * context)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 *
GMPy_Number_Sign(PyObject * x,CTXT_Object * context)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 *
GMPy_Context_Sign(PyObject * self,PyObject * other)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 }
113