1 /**
2  * Copyright 2015, SRI International.
3  *
4  * This file is part of LibPoly.
5  *
6  * LibPoly is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * LibPoly is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with LibPoly.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "polypyValue.h"
21 #include "utils.h"
22 #include "polypyAlgebraicNumber.h"
23 
24 #include <structmember.h>
25 #include <math.h>
26 
27 static void
28 Value_dealloc(Value* self);
29 
30 static PyObject*
31 Value_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
32 
33 static int
34 Value_init(Value* self, PyObject* args);
35 
36 static PyObject*
37 Value_to_double(PyObject* self);
38 
39 static PyObject*
40 Value_richcompare(PyObject* self, PyObject* other, int op);
41 
42 static PyObject*
43 Value_str(PyObject* self);
44 
45 static long
46 Value_hash(PyObject* self);
47 
48 static PyObject*
49 Value_get_value_between(PyObject* self, PyObject* args);
50 
51 static PyObject*
52 Value_add(PyObject* self, PyObject* args);
53 
54 static PyObject*
55 Value_neg(PyObject* self);
56 
57 static PyObject*
58 Value_sub(PyObject* self, PyObject* args);
59 
60 static PyObject*
61 Value_mul(PyObject* self, PyObject* args);
62 
63 static PyObject*
64 Value_div(PyObject* self, PyObject* args);
65 
66 static PyObject*
67 Value_pow(PyObject* self, PyObject* args);
68 
69 static PyObject*
70 Value_long(PyObject* self);
71 
72 static PyObject*
73 Value_float(PyObject* self);
74 
75 PyMethodDef Value_methods[] = {
76     {"to_double", (PyCFunction)Value_to_double, METH_NOARGS, "Returns the approximation of the value"},
77     {"get_value_between", (PyCFunction)Value_get_value_between, METH_VARARGS, "Returns a value between this and given value"},
78     {NULL}  /* Sentinel */
79 };
80 
81 PyNumberMethods Value_NumberMethods = {
82      Value_add,              // binaryfunc nb_add;
83      Value_sub,              // binaryfunc nb_subtract;
84      Value_mul,              // binaryfunc nb_multiply;
85      0,                      // binaryfunc nb_remainder;
86      0,                      // binaryfunc nb_divmod;
87      (ternaryfunc)Value_pow, // ternaryfunc nb_power;
88      Value_neg,              // unaryfunc nb_negative;
89      0,                      // unaryfunc nb_positive;
90      0,                      // unaryfunc nb_absolute;
91      0,                      // inquiry nb_bool;
92      0,                      // unaryfunc nb_invert;
93      0,                      // binaryfunc nb_lshift;
94      0,                      // binaryfunc nb_rshift;
95      0,                      // binaryfunc nb_and;
96      0,                      // binaryfunc nb_xor;
97      0,                      // binaryfunc nb_or;
98      Value_long,             // unaryfunc nb_int;
99      0,                      // void *nb_reserved;
100      Value_float,            // unaryfunc nb_float;
101      0,                      // binaryfunc nb_inplace_add;
102      0,                      // binaryfunc nb_inplace_subtract;
103      0,                      // binaryfunc nb_inplace_multiply;
104      0,                      // binaryfunc nb_inplace_remainder;
105      0,                      // ternaryfunc nb_inplace_power;
106      0,                      // binaryfunc nb_inplace_lshift;
107      0,                      // binaryfunc nb_inplace_rshift;
108      0,                      // binaryfunc nb_inplace_and;
109      0,                      // binaryfunc nb_inplace_xor;
110      0,                      // binaryfunc nb_inplace_or;
111      0,                      // binaryfunc nb_floor_divide;
112      Value_div,              // binaryfunc nb_true_divide;
113      0,                      // binaryfunc nb_inplace_floor_divide;
114      0,                      // binaryfunc nb_inplace_true_divide;
115      0,                      // unaryfunc nb_index;
116      0,                      // binaryfunc nb_matrix_multiply;
117      0,                      // binaryfunc nb_inplace_matrix_multiply;
118 };
119 
120 PyTypeObject ValueType = {
121     {PyObject_HEAD_INIT(NULL)},   // PyObject_VAR_HEAD
122     "polypy.Value",              // const char *tp_name;
123     sizeof(Value),               // Py_ssize_t tp_basicsize;
124     0,                           // Py_ssize_t tp_itemsize;
125     (destructor)Value_dealloc,   // destructor tp_dealloc;
126     0,                           // printfunc tp_print;
127     0,                           // getattrfunc tp_getattr;
128     0,                           // setattrfunc tp_setattr;
129     0,                           // PyAsyncMethods *tp_as_async;
130     Value_str,                   // reprfunc tp_repr;
131     &Value_NumberMethods,        // PyNumberMethods *tp_as_number;
132     0,                           // PySequenceMethods *tp_as_sequence;
133     0,                           // PyMappingMethods *tp_as_mapping;
134     &Value_hash,                 // hashfunc tp_hash;
135     0,                           // ternaryfunc tp_call;
136     Value_str,                   // reprfunc tp_str;
137     0,                           // getattrofunc tp_getattro;
138     0,                           // setattrofunc tp_setattro;
139     0,                           // PyBufferProcs *tp_as_buffer;
140     Py_TPFLAGS_DEFAULT,          // unsigned long tp_flags;
141     "Values of different kinds", // const char *tp_doc;
142     0,                           // traverseproc tp_traverse;
143     0,                           // inquiry tp_clear;
144     Value_richcompare,           // richcmpfunc tp_richcompare;
145     0,                           // Py_ssize_t tp_weaklistoffset;
146     0,                           // getiterfunc tp_iter;
147     0,                           // iternextfunc tp_iternext;
148     Value_methods,               // struct PyMethodDef *tp_methods;
149     0,                           // struct PyMemberDef *tp_members;
150     0,                           // struct PyGetSetDef *tp_getset;
151     0,                           // struct _typeobject *tp_base;
152     0,                           // PyObject *tp_dict;
153     0,                           // descrgetfunc tp_descr_get;
154     0,                           // descrsetfunc tp_descr_set;
155     0,                           // Py_ssize_t tp_dictoffset;
156     (initproc)Value_init,        // initproc tp_init;
157     0,                           // allocfunc tp_alloc;
158     Value_new,                   // newfunc tp_new;
159     0,                           // freefunc tp_free;
160     0,                           // inquiry tp_is_gc;
161     0,                           // PyObject *tp_bases;
162     0,                           // PyObject *tp_mro;
163     0,                           // PyObject *tp_cache;
164     0,                           // PyObject *tp_subclasses;
165     0,                           // PyObject *tp_weaklist;
166     0,                           // destructor tp_del;
167     0,                           // unsigned int tp_version_tag;
168     0,                           // destructor tp_finalize;
169 };
170 
171 static void
Value_dealloc(Value * self)172 Value_dealloc(Value* self)
173 {
174   lp_value_destruct(&self->v);
175   ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
176 }
177 
178 PyObject*
PyValue_create(const lp_value_t * v)179 PyValue_create(const lp_value_t* v) {
180   Value *self;
181   self = (Value*)ValueType.tp_alloc(&ValueType, 0);
182   if (self != NULL) {
183     if (v) {
184       lp_value_construct_copy(&self->v, v);
185     } else {
186       lp_value_construct_zero(&self->v);
187     }
188   }
189   return (PyObject *)self;
190 }
191 
192 static PyObject*
Value_new(PyTypeObject * type,PyObject * args,PyObject * kwds)193 Value_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
194   return PyValue_create(0);
195 }
196 
197 /** Construct a value from given number. */
198 static int
Value_init(Value * self,PyObject * args)199 Value_init(Value* self, PyObject* args)
200 {
201   if (PyTuple_Check(args)) {
202     if (PyTuple_Size(args) == 0) {
203       lp_value_construct_zero(&self->v);
204     } else if (PyTuple_Size(args) == 1) {
205       PyObject* v = PyTuple_GetItem(args, 0);
206       if (PyLong_Check(v)) {
207         long v_int = PyLong_AsLong(v);
208         lp_value_construct_int(&self->v, v_int);
209       } else if (PyAlgebraicNumber_CHECK(v)) {
210         AlgebraicNumber* v_alg = (AlgebraicNumber*) v;
211         lp_value_construct(&self->v, LP_VALUE_ALGEBRAIC, &v_alg->a);
212       } else {
213         return -1;
214       }
215      } else {
216       return -1;
217      }
218   } else {
219     return -1;
220   }
221 
222   // All fine, initialized
223   return 0;
224 }
225 
226 static PyObject*
Value_to_double(PyObject * self)227 Value_to_double(PyObject* self) {
228 
229   Value* a = (Value*) self;
230 
231   double value = 0;
232 
233   switch (a->v.type) {
234   case LP_VALUE_NONE:
235     assert(0);
236     break;
237   case LP_VALUE_INTEGER:
238     value = lp_integer_to_int(&a->v.value.z);
239     break;
240   case LP_VALUE_DYADIC_RATIONAL:
241     value = lp_dyadic_rational_to_double(&a->v.value.dy_q);
242     break;
243   case LP_VALUE_RATIONAL:
244     value = lp_rational_to_double(&a->v.value.q);
245     break;
246   case LP_VALUE_ALGEBRAIC:
247     value = lp_algebraic_number_to_double(&a->v.value.a);
248     break;
249   case LP_VALUE_PLUS_INFINITY:
250     value = INFINITY;
251     break;
252   case LP_VALUE_MINUS_INFINITY:
253     value = -INFINITY;
254     break;
255   }
256 
257   return PyFloat_FromDouble(value);
258 }
259 
260 static PyObject*
Value_richcompare(PyObject * self,PyObject * other,int op)261 Value_richcompare(PyObject* self, PyObject* other, int op) {
262   PyObject *result = 0;
263 
264   if (!PyValue_CHECK(other)) {
265     result = Py_NotImplemented;
266   } else {
267     lp_value_t* self_v = &((Value*) self)->v;
268     lp_value_t* other_v = &((Value*) other)->v;
269     int cmp = lp_value_cmp(self_v, other_v);
270 
271     switch (op) {
272     case Py_LT:
273       result = cmp < 0 ? Py_True : Py_False;
274       break;
275     case Py_LE:
276       result = cmp <= 0 ? Py_True : Py_False;
277       break;
278     case Py_EQ:
279       result = cmp == 0 ? Py_True : Py_False;
280       break;
281     case Py_NE:
282       result = cmp != 0 ? Py_True : Py_False;
283       break;
284     case Py_GT:
285       result = cmp > 0 ? Py_True : Py_False;
286       break;
287     case Py_GE:
288       result = cmp >= 0 ? Py_True : Py_False;
289       break;
290     default:
291       assert(0);
292     }
293   }
294 
295   Py_INCREF(result);
296   return result;
297 }
298 
Value_str(PyObject * self)299 static PyObject* Value_str(PyObject* self) {
300   Value* v = (Value*) self;
301   char* cstr = lp_value_to_string(&v->v);
302   PyObject* pystr = PyUnicode_FromString(cstr);
303   free(cstr);
304   return pystr;
305 }
306 
307 static long
Value_hash(PyObject * self)308 Value_hash(PyObject* self) {
309   Value* v = (Value*) self;
310   long hash = lp_value_hash(&v->v);
311   if (hash == -1) {
312     // value -1 should not be returned as a normal return value
313     hash = 0;
314   }
315   return hash;
316 }
317 
318 static PyObject*
Value_get_value_between(PyObject * self,PyObject * args)319 Value_get_value_between(PyObject* self, PyObject* args) {
320   // self is always a polynomial
321   Value* v1 = (Value*) self;
322   if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
323     PyErr_SetString(PyExc_RuntimeError, "get_value_between(): need one argument.");
324     return NULL;
325   }
326   PyObject* other = PyTuple_GetItem(args, 0);
327 
328   // other should be a value
329   if (!PyValue_CHECK(other)) {
330     PyErr_SetString(PyExc_RuntimeError, "get_value_between(): argument not a value.");
331     return NULL;
332   }
333   Value* v2 = (Value*) other;
334 
335   // compare the values (they should be different)
336   if (v1->v.type == LP_VALUE_NONE || v2->v.type == LP_VALUE_NONE) {
337     PyErr_SetString(PyExc_RuntimeError, "get_value_between(): values should not be null.");
338     return NULL;
339   }
340   if (lp_value_cmp(&v1->v, &v2->v) == 0) {
341     PyErr_SetString(PyExc_RuntimeError, "get_value_between(): values should be different.");
342     return NULL;
343   }
344 
345   lp_value_t m;
346   lp_value_construct_none(&m);
347   lp_value_get_value_between(&v1->v, 1, &v2->v, 1, &m);
348   PyObject* result = PyValue_create(&m);
349   lp_value_destruct(&m);
350 
351   return result;
352 }
353 
354 static PyObject*
Value_add(PyObject * self,PyObject * other)355 Value_add(PyObject* self, PyObject* other) {
356   if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
357     Py_INCREF(Py_NotImplemented);
358     return Py_NotImplemented;
359   }
360 
361   Value* v1 = (Value*) self;
362   Value* v2 = (Value*) other;
363 
364   lp_value_t add;
365   lp_value_construct_none(&add);
366   lp_value_add(&add, &v1->v, &v2->v);
367   PyObject* result = PyValue_create(&add);
368   lp_value_destruct(&add);
369 
370   return result;
371 }
372 
373 static PyObject*
Value_neg(PyObject * self)374 Value_neg(PyObject* self) {
375   if (!PyValue_CHECK(self)) {
376     Py_INCREF(Py_NotImplemented);
377     return Py_NotImplemented;
378   }
379 
380   Value* v = (Value*) self;
381 
382   lp_value_t neg;
383   lp_value_construct_none(&neg);
384   lp_value_neg(&neg, &v->v);
385   PyObject* result = PyValue_create(&neg);
386   lp_value_destruct(&neg);
387 
388   return result;
389 }
390 
391 static PyObject*
Value_sub(PyObject * self,PyObject * other)392 Value_sub(PyObject* self, PyObject* other) {
393   if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
394     Py_INCREF(Py_NotImplemented);
395     return Py_NotImplemented;
396   }
397 
398   Value* v1 = (Value*) self;
399   Value* v2 = (Value*) other;
400 
401   lp_value_t sub;
402   lp_value_construct_none(&sub);
403   lp_value_sub(&sub, &v1->v, &v2->v);
404   PyObject* result = PyValue_create(&sub);
405   lp_value_destruct(&sub);
406 
407   return result;
408 }
409 
410 static PyObject*
Value_mul(PyObject * self,PyObject * other)411 Value_mul(PyObject* self, PyObject* other) {
412   if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
413     Py_INCREF(Py_NotImplemented);
414     return Py_NotImplemented;
415   }
416 
417   Value* v1 = (Value*) self;
418   Value* v2 = (Value*) other;
419 
420   lp_value_t mul;
421   lp_value_construct_none(&mul);
422   lp_value_mul(&mul, &v1->v, &v2->v);
423   PyObject* result = PyValue_create(&mul);
424   lp_value_destruct(&mul);
425 
426   return result;
427 }
428 
429 static PyObject*
Value_div(PyObject * self,PyObject * other)430 Value_div(PyObject* self, PyObject* other) {
431   if (!PyValue_CHECK(self) || !PyValue_CHECK(other)) {
432     Py_INCREF(Py_NotImplemented);
433     return Py_NotImplemented;
434   }
435 
436   Value* v1 = (Value*) self;
437   Value* v2 = (Value*) other;
438 
439   lp_value_t div;
440   lp_value_construct_none(&div);
441   lp_value_div(&div, &v1->v, &v2->v);
442   PyObject* result = PyValue_create(&div);
443   lp_value_destruct(&div);
444 
445   return result;
446 }
447 
448 
449 static PyObject*
Value_pow(PyObject * self,PyObject * other)450 Value_pow(PyObject* self, PyObject* other) {
451   if (!PyValue_CHECK(self) || !PyLong_Check(other)) {
452     Py_INCREF(Py_NotImplemented);
453     return Py_NotImplemented;
454   }
455 
456   Value* v = (Value*) self;
457   long n = PyLong_AsLong(other);
458 
459   lp_value_t mul;
460   lp_value_construct_none(&mul);
461   lp_value_pow(&mul, &v->v, n);
462   PyObject* result = PyValue_create(&mul);
463   lp_value_destruct(&mul);
464 
465   return result;
466 }
467 
468 // Returns the o converted to a long integer object on success, or NULL on
469 // failure. This is the equivalent of the Python 3 expression int(o).
470 // Return value: New reference.
471 static PyObject*
Value_long(PyObject * self)472 Value_long(PyObject* self) {
473   Value* value_obj = (Value*) self;
474   lp_integer_t int_cast;
475   lp_integer_construct(&int_cast);
476   lp_value_floor(&value_obj->v, &int_cast);
477   PyObject* py_int_cast = integer_to_PyLong(&int_cast);
478   lp_integer_destruct(&int_cast);
479   return py_int_cast;
480 }
481 
482 // Returns the o converted to a float object on success, or NULL on failure.
483 // This is the equivalent of the Python expression float(o).
484 // Return value: New reference.
485 static PyObject*
Value_float(PyObject * self)486 Value_float(PyObject* self) {
487   Value* value_obj = (Value*) self;
488   double value = lp_value_to_double(&value_obj->v);
489   return PyFloat_FromDouble(value);
490 }
491