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