1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * gmpy2_square.c                                                             *
3  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4  * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision   *
5  * libraries.                                                              *
6  *                                                                         *
7  * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,               *
8  *           2008, 2009 Alex Martelli                                      *
9  *                                                                         *
10  * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014,                     *
11  *           2015, 2016, 2017, 2018, 2019, 2020 Case Van Horsen            *
12  *                                                                         *
13  * This file is part of GMPY2.                                             *
14  *                                                                         *
15  * GMPY2 is free software: you can redistribute it and/or modify it under  *
16  * the terms of the GNU Lesser General Public License as published by the  *
17  * Free Software Foundation, either version 3 of the License, or (at your  *
18  * option) any later version.                                              *
19  *                                                                         *
20  * GMPY2 is distributed in the hope that it will be useful, but WITHOUT    *
21  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   *
22  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public    *
23  * License for more details.                                               *
24  *                                                                         *
25  * You should have received a copy of the GNU Lesser General Public        *
26  * License along with GMPY2; if not, see <http://www.gnu.org/licenses/>    *
27  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
28 
29 /* Public API
30  * ==========
31  * The following function is available as part of GMPY2's C API. A NULL value
32  * for context implies the function should use the currently active context.
33  *
34  *   GMPy_Number_Square(Number, Number, context|NULL)
35  *
36  * Private API
37  * ===========
38  *   GMPy_Integer_Square(Integer, Integer, context|NULL)
39  *   GMPy_Rational_Square(Rational, Rational, context|NULL)
40  *   GMPy_Real_Square(Real, Real, context|NULL)
41  *   GMPy_Complex_Square(Complex, Complex, context|NULL)
42  *
43  *   GMPy_Context_Square(context, args)
44  *
45  */
46 
47 static PyObject *
_GMPy_MPZ_Square(PyObject * x,CTXT_Object * context)48 _GMPy_MPZ_Square(PyObject *x, CTXT_Object *context)
49 {
50     MPZ_Object *result = NULL;
51 
52     if (!(result = GMPy_MPZ_New(context))) {
53         return NULL;
54     }
55 
56     mpz_mul(result->z, MPZ(x), MPZ(x));
57     return (PyObject*)result;
58 }
59 
60 static PyObject *
GMPy_Integer_Square(PyObject * x,CTXT_Object * context)61 GMPy_Integer_Square(PyObject *x, CTXT_Object *context)
62 {
63     PyObject *result, *tempx;
64 
65     if (!(tempx = (PyObject*)GMPy_MPZ_From_Integer(x, context))) {
66         return NULL;
67     }
68 
69     result = _GMPy_MPZ_Square(tempx, context);
70     Py_DECREF(tempx);
71     return result;
72 }
73 
74 static PyObject *
_GMPy_MPQ_Square(PyObject * x,CTXT_Object * context)75 _GMPy_MPQ_Square(PyObject *x, CTXT_Object *context)
76 {
77     MPQ_Object *result;
78 
79     if (!(result = GMPy_MPQ_New(context))) {
80         return NULL;
81     }
82 
83     mpq_mul(result->q, MPQ(x), MPQ(x));
84     return (PyObject*)result;
85 }
86 
87 static PyObject *
GMPy_Rational_Square(PyObject * x,CTXT_Object * context)88 GMPy_Rational_Square(PyObject *x, CTXT_Object *context)
89 {
90     PyObject *result, *tempx;
91 
92     if (!(tempx = (PyObject*)GMPy_MPQ_From_Rational(x, context))) {
93         return NULL;
94     }
95 
96     result = _GMPy_MPQ_Square(tempx, context);
97     Py_DECREF(tempx);
98     return result;
99 }
100 
101 static PyObject *
_GMPy_MPFR_Square(PyObject * x,CTXT_Object * context)102 _GMPy_MPFR_Square(PyObject *x, CTXT_Object *context)
103 {
104     MPFR_Object *result;
105 
106     CHECK_CONTEXT(context);
107 
108     if (!(result = GMPy_MPFR_New(0, context))) {
109         return NULL;
110     }
111 
112     mpfr_clear_flags();
113 
114     mpfr_sqr(result->f, MPFR(x), GET_MPFR_ROUND(context));
115     _GMPy_MPFR_Cleanup(&result, context);
116     return (PyObject*)result;
117 }
118 
119 static PyObject *
GMPy_Real_Square(PyObject * x,CTXT_Object * context)120 GMPy_Real_Square(PyObject *x, CTXT_Object *context)
121 {
122     PyObject *result, *tempx;
123 
124     CHECK_CONTEXT(context);
125 
126     if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
127         return NULL;
128     }
129 
130     result = _GMPy_MPFR_Square(tempx, context);
131     Py_DECREF(tempx);
132     return result;
133 }
134 
135 static PyObject *
_GMPy_MPC_Square(PyObject * x,CTXT_Object * context)136 _GMPy_MPC_Square(PyObject *x, CTXT_Object *context)
137 {
138     MPC_Object *result;
139 
140     CHECK_CONTEXT(context);
141 
142     if (!(result = GMPy_MPC_New(0, 0, context))) {
143         return NULL;
144     }
145 
146     mpc_sqr(result->c, MPC(x), GET_MPC_ROUND(context));
147     _GMPy_MPC_Cleanup(&result, context);
148     return (PyObject*)result;
149 }
150 static PyObject *
GMPy_Complex_Square(PyObject * x,CTXT_Object * context)151 GMPy_Complex_Square(PyObject *x, CTXT_Object *context)
152 {
153     PyObject *result, *tempx;
154 
155     CHECK_CONTEXT(context);
156 
157     if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
158         return NULL;
159     }
160 
161     result = _GMPy_MPC_Square(tempx, context);
162     Py_DECREF(tempx);
163     return result;
164 }
165 
166 PyDoc_STRVAR(GMPy_doc_function_square,
167 "square(x) -> number\n\n"
168 "Return x * x. If x is an integer, then the result is an 'mpz'.\n"
169 "If x is a rational, then the result is an 'mpq'. If x is a float,\n"
170 "then the result is an 'mpfr'. If x is a complex number, then the\n"
171 "result is an 'mpc'.");
172 
173 PyDoc_STRVAR(GMPy_doc_context_square,
174 "context.square(x) -> number\n\n"
175 "Return x * x. If x is an integer, then the result is an 'mpz'.\n"
176 "If x is a rational, then the result is an 'mpq'. If x is a float,\n"
177 "then the result is an 'mpfr'. If x is a complex number, then the\n"
178 "result is an 'mpc'.");
179 
180 static PyObject *
GMPy_Number_Square(PyObject * x,CTXT_Object * context)181 GMPy_Number_Square(PyObject *x, CTXT_Object *context)
182 {
183     if (MPZ_Check(x))
184         return _GMPy_MPZ_Square(x, context);
185 
186     if (MPQ_Check(x))
187         return _GMPy_MPQ_Square(x, context);
188 
189     if (MPFR_Check(x))
190         return _GMPy_MPFR_Square(x, context);
191 
192     if (MPC_Check(x))
193         return _GMPy_MPC_Square(x, context);
194 
195     if (IS_INTEGER(x))
196         return GMPy_Integer_Square(x, context);
197 
198     if (IS_RATIONAL(x))
199         return GMPy_Rational_Square(x, context);
200 
201     if (IS_REAL(x))
202         return GMPy_Real_Square(x, context);
203 
204     if (IS_COMPLEX(x))
205         return GMPy_Complex_Square(x, context);
206 
207     TYPE_ERROR("square() argument type not supported");
208     return NULL;
209 }
210 
211 static PyObject *
GMPy_Context_Square(PyObject * self,PyObject * other)212 GMPy_Context_Square(PyObject *self, PyObject *other)
213 {
214     CTXT_Object *context = NULL;
215 
216     if (self && CTXT_Check(self)) {
217         context = (CTXT_Object*)self;
218     }
219     else {
220         CHECK_CONTEXT(context);
221     }
222 
223     return GMPy_Number_Square(other, context);
224 }
225 
226