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 <rational_interval.h>
21 #include <algebraic_number.h>
22 #include <upolynomial.h>
23 
24 #include "number/value.h"
25 #include "number/integer.h"
26 #include "number/rational.h"
27 #include "number/dyadic_rational.h"
28 
29 #include "utils/debug_trace.h"
30 
31 #include <limits.h>
32 #include <math.h>
33 
lp_value_construct(lp_value_t * v,lp_value_type_t type,const void * data)34 void lp_value_construct(lp_value_t* v, lp_value_type_t type, const void* data) {
35   v->type = type;
36   switch(type) {
37   case LP_VALUE_PLUS_INFINITY:
38   case LP_VALUE_MINUS_INFINITY:
39   case LP_VALUE_NONE:
40     break;
41   case LP_VALUE_INTEGER:
42     integer_construct_copy(lp_Z, &v->value.z, data);
43     break;
44   case LP_VALUE_RATIONAL:
45     rational_construct_copy(&v->value.q, data);
46     break;
47   case LP_VALUE_DYADIC_RATIONAL:
48     dyadic_rational_construct_copy(&v->value.dy_q, data);
49     break;
50   case LP_VALUE_ALGEBRAIC:
51     lp_algebraic_number_construct_copy(&v->value.a, data);
52     break;
53   }
54 }
55 
lp_value_construct_zero(lp_value_t * v)56 void lp_value_construct_zero(lp_value_t* v) {
57   v->type = LP_VALUE_INTEGER;
58   integer_construct(&v->value.z);
59 }
60 
lp_value_construct_int(lp_value_t * v,long x)61 void lp_value_construct_int(lp_value_t* v, long x) {
62   v->type = LP_VALUE_INTEGER;
63   integer_construct_from_int(lp_Z, &v->value.z, x);
64 }
65 
lp_value_construct_none(lp_value_t * v)66 void lp_value_construct_none(lp_value_t* v) {
67   lp_value_construct(v, LP_VALUE_NONE, 0);
68 }
69 
70 lp_value_t value_none = {
71     .type = LP_VALUE_NONE
72 };
73 
lp_value_none(void)74 const lp_value_t* lp_value_none(void) {
75   return &value_none;
76 }
77 
78 lp_value_t value_minus_inf = {
79     .type = LP_VALUE_MINUS_INFINITY
80 };
81 
lp_value_minus_infinity(void)82 const lp_value_t* lp_value_minus_infinity(void) {
83   return &value_minus_inf;
84 }
85 
86 lp_value_t value_plus_inf = {
87     .type = LP_VALUE_PLUS_INFINITY
88 };
89 
lp_value_plus_infinity(void)90 const lp_value_t* lp_value_plus_infinity(void) {
91   return &value_plus_inf;
92 }
93 
lp_value_assign_raw(lp_value_t * v,lp_value_type_t type,const void * data)94 void lp_value_assign_raw(lp_value_t* v, lp_value_type_t type, const void* data) {
95   lp_value_destruct(v);
96   lp_value_construct(v, type, data);
97 }
98 
lp_value_assign(lp_value_t * v,const lp_value_t * from)99 void lp_value_assign(lp_value_t* v, const lp_value_t* from) {
100   if (v != from) {
101     lp_value_destruct(v);
102     lp_value_construct_copy(v, from);
103   }
104 }
105 
lp_value_assign_zero(lp_value_t * v)106 void lp_value_assign_zero(lp_value_t* v) {
107   lp_value_destruct(v);
108   lp_value_construct_zero(v);
109 }
110 
lp_value_swap(lp_value_t * v1,lp_value_t * v2)111 void lp_value_swap(lp_value_t* v1, lp_value_t* v2) {
112   lp_value_t tmp = *v1;
113   *v1 = *v2;
114   *v2 = tmp;
115 }
116 
lp_value_new(lp_value_type_t type,const void * data)117 lp_value_t* lp_value_new(lp_value_type_t type, const void* data) {
118   lp_value_t* result = malloc(sizeof(lp_value_t));
119   lp_value_construct(result, type, data);
120   return result;
121 }
122 
lp_value_new_copy(const lp_value_t * from)123 lp_value_t* lp_value_new_copy(const lp_value_t* from) {
124   lp_value_t* result = malloc(sizeof(lp_value_t));
125   lp_value_construct_copy(result, from);
126   return result;
127 }
128 
lp_value_construct_copy(lp_value_t * v,const lp_value_t * from)129 void lp_value_construct_copy(lp_value_t* v, const lp_value_t* from) {
130   switch(from->type) {
131   case LP_VALUE_NONE:
132   case LP_VALUE_PLUS_INFINITY:
133   case LP_VALUE_MINUS_INFINITY:
134     lp_value_construct(v, from->type, 0);
135     break;
136   case LP_VALUE_INTEGER:
137     lp_value_construct(v, LP_VALUE_INTEGER, &from->value.z);
138     break;
139   case LP_VALUE_RATIONAL:
140     lp_value_construct(v, LP_VALUE_RATIONAL, &from->value.q);
141     break;
142   case LP_VALUE_DYADIC_RATIONAL:
143     lp_value_construct(v, LP_VALUE_DYADIC_RATIONAL, &from->value.dy_q);
144     break;
145   case LP_VALUE_ALGEBRAIC:
146     lp_value_construct(v, LP_VALUE_ALGEBRAIC, &from->value.a);
147     break;
148   }
149 }
150 
lp_value_destruct(lp_value_t * v)151 void lp_value_destruct(lp_value_t* v) {
152   switch(v->type) {
153   case LP_VALUE_NONE:
154   case LP_VALUE_PLUS_INFINITY:
155   case LP_VALUE_MINUS_INFINITY:
156     break;
157   case LP_VALUE_INTEGER:
158     integer_destruct(&v->value.z);
159     break;
160   case LP_VALUE_RATIONAL:
161     rational_destruct(&v->value.q);
162     break;
163   case LP_VALUE_DYADIC_RATIONAL:
164     dyadic_rational_destruct(&v->value.dy_q);
165     break;
166   case LP_VALUE_ALGEBRAIC:
167     lp_algebraic_number_destruct(&v->value.a);
168     break;
169   }
170 }
171 
lp_value_delete(lp_value_t * v)172 void lp_value_delete(lp_value_t* v) {
173   lp_value_destruct(v);
174   free(v);
175 }
176 
177 // 1/2^20
178 #define LP_VALUE_APPROX_MIN_MAGNITUDE -20
179 
lp_value_approx(const lp_value_t * v,lp_rational_interval_t * out)180 void lp_value_approx(const lp_value_t* v, lp_rational_interval_t* out) {
181   int size;
182 
183   lp_rational_interval_t approx;
184 
185   switch (v->type) {
186   case LP_VALUE_NONE:
187   case LP_VALUE_PLUS_INFINITY:
188   case LP_VALUE_MINUS_INFINITY:
189     assert(0);
190     break;
191   case LP_VALUE_INTEGER: {
192     lp_rational_t point;
193     rational_construct_from_integer(&point, &v->value.z);
194     lp_rational_interval_construct_point(&approx, &point);
195     rational_destruct(&point);
196     break;
197   }
198   case LP_VALUE_RATIONAL:
199     lp_rational_interval_construct_point(&approx, &v->value.q);
200     break;
201   case LP_VALUE_DYADIC_RATIONAL:
202     lp_rational_interval_construct_from_dyadic(&approx, &v->value.dy_q, 0, &v->value.dy_q, 0);
203     break;
204   case LP_VALUE_ALGEBRAIC:
205     if (lp_value_is_rational(v)) {
206       lp_rational_t v_rat;
207       rational_construct(&v_rat);
208       lp_value_get_rational(v, &v_rat);
209       lp_rational_interval_construct_point(&approx, &v_rat);
210       rational_destruct(&v_rat);
211     } else {
212       // Make sure we're below the given size
213       size = lp_dyadic_interval_size(&v->value.a.I);
214       while (size > LP_VALUE_APPROX_MIN_MAGNITUDE) {
215         size --;
216         lp_algebraic_number_refine_const(&v->value.a);
217       }
218       lp_rational_interval_construct_from_dyadic_interval(&approx, &v->value.a.I);
219     }
220     break;
221   }
222 
223   lp_rational_interval_swap(&approx, out);
224   lp_rational_interval_destruct(&approx);
225 }
226 
lp_value_print(const lp_value_t * v,FILE * out)227 int lp_value_print(const lp_value_t* v, FILE* out) {
228   int ret = 0;
229   switch (v->type) {
230   case LP_VALUE_NONE:
231     ret += fprintf(out, "<null>");
232     break;
233   case LP_VALUE_PLUS_INFINITY:
234     ret += fprintf(out, "+inf");
235     break;
236   case LP_VALUE_MINUS_INFINITY:
237     ret += fprintf(out, "-inf");
238     break;
239   case LP_VALUE_INTEGER:
240     ret += integer_print(&v->value.z, out);
241     break;
242   case LP_VALUE_RATIONAL:
243     ret += rational_print(&v->value.q, out);
244     break;
245   case LP_VALUE_DYADIC_RATIONAL:
246     ret += dyadic_rational_print(&v->value.dy_q, out);
247     break;
248   case LP_VALUE_ALGEBRAIC:
249     ret += lp_algebraic_number_print(&v->value.a, out);
250     break;
251   }
252   return ret;
253 }
254 
lp_value_sgn(const lp_value_t * v)255 int lp_value_sgn(const lp_value_t* v) {
256   switch (v->type) {
257   case LP_VALUE_NONE:
258     assert(0);
259     return 0;
260   case LP_VALUE_PLUS_INFINITY:
261     return 1;
262   case LP_VALUE_MINUS_INFINITY:
263     return -1;
264   case LP_VALUE_INTEGER:
265     return lp_integer_sgn(lp_Z, &v->value.z);
266   case LP_VALUE_RATIONAL:
267     return lp_rational_sgn(&v->value.q);
268   case LP_VALUE_DYADIC_RATIONAL:
269     return lp_dyadic_rational_sgn(&v->value.dy_q);
270   case LP_VALUE_ALGEBRAIC:
271     return lp_algebraic_number_sgn(&v->value.a);
272   }
273   return 0;
274 }
275 
lp_value_cmp(const lp_value_t * v1,const lp_value_t * v2)276 int lp_value_cmp(const lp_value_t* v1, const lp_value_t* v2) {
277 
278   if (trace_is_enabled("value::cmp")) {
279     tracef("lp_value_cmp()\n")
280     tracef("v1 = "); lp_value_print(v1, trace_out); tracef("\n");
281     tracef("v2 = "); lp_value_print(v2, trace_out); tracef("\n");
282   }
283 
284   if (v1 == v2) {
285     return 0;
286   }
287 
288   if (v1->type == v2->type) {
289     lp_value_type_t type = v1->type;
290     switch (type) {
291     case LP_VALUE_NONE:
292     case LP_VALUE_PLUS_INFINITY:
293     case LP_VALUE_MINUS_INFINITY:
294       return 0;
295     case LP_VALUE_INTEGER:
296       return lp_integer_cmp(lp_Z, &v1->value.z, &v2->value.z);
297     case LP_VALUE_RATIONAL:
298       return rational_cmp(&v1->value.q, &v2->value.q);
299     case LP_VALUE_DYADIC_RATIONAL:
300       return dyadic_rational_cmp(&v1->value.dy_q, &v2->value.dy_q);
301     case LP_VALUE_ALGEBRAIC:
302       return lp_algebraic_number_cmp(&v1->value.a, &v2->value.a);
303     }
304   }
305 
306   // Different types
307   assert(v1->type != LP_VALUE_NONE && v2->type != LP_VALUE_NONE);
308   if (v1->type == LP_VALUE_MINUS_INFINITY) {
309     return -1;
310   }
311   if (v2->type == LP_VALUE_MINUS_INFINITY) {
312     return 1;
313   }
314   if (v1->type == LP_VALUE_PLUS_INFINITY) {
315     return 1;
316   }
317   if (v2->type == LP_VALUE_PLUS_INFINITY) {
318     return -1;
319   }
320 
321   // Make sure that the first one is bigger in the order int < dy_rat < rat < algebraic
322   if (v1->type < v2->type) {
323     return -lp_value_cmp(v2, v1);
324   }
325 
326   switch (v1->type) {
327   case LP_VALUE_DYADIC_RATIONAL:
328     switch (v2->type) {
329     case LP_VALUE_INTEGER:
330       return dyadic_rational_cmp_integer(&v1->value.dy_q, &v2->value.z);
331     default:
332       assert(0);
333     }
334     break;
335   case LP_VALUE_RATIONAL:
336     switch (v2->type) {
337     case LP_VALUE_INTEGER:
338       return rational_cmp_integer(&v1->value.q, &v2->value.z);
339     case LP_VALUE_DYADIC_RATIONAL:
340       return rational_cmp_dyadic_rational(&v1->value.q, &v2->value.dy_q);
341     default:
342       assert(0);
343     }
344     break;
345   case LP_VALUE_ALGEBRAIC:
346     switch (v2->type) {
347     case LP_VALUE_INTEGER:
348       return lp_algebraic_number_cmp_integer(&v1->value.a, &v2->value.z);
349     case LP_VALUE_DYADIC_RATIONAL:
350       return lp_algebraic_number_cmp_dyadic_rational(&v1->value.a, &v2->value.dy_q);
351     case LP_VALUE_RATIONAL:
352       return lp_algebraic_number_cmp_rational(&v1->value.a, &v2->value.q);
353     default:
354       assert(0);
355     }
356     break;
357   default:
358     assert(0);
359   }
360 
361   assert(0);
362 
363   return v1 == v2;
364 }
365 
lp_value_cmp_void(const void * v1,const void * v2)366 int lp_value_cmp_void(const void* v1, const void* v2) {
367   return lp_value_cmp(v1, v2);
368 }
369 
lp_value_cmp_rational(const lp_value_t * v,const lp_rational_t * q)370 int lp_value_cmp_rational(const lp_value_t* v, const lp_rational_t* q) {
371 
372   int cmp  = 0;
373 
374   switch (v->type) {
375   case LP_VALUE_PLUS_INFINITY:
376     cmp = 1;
377     break;
378   case LP_VALUE_MINUS_INFINITY:
379     cmp = -1;
380     break;
381   case LP_VALUE_INTEGER:
382     cmp = -lp_rational_cmp_integer(q, &v->value.z);
383     break;
384   case LP_VALUE_DYADIC_RATIONAL:
385     cmp = -lp_rational_cmp_dyadic_rational(q, &v->value.dy_q);
386     break;
387   case LP_VALUE_RATIONAL:
388     cmp = lp_rational_cmp(&v->value.q, q);
389     break;
390   case LP_VALUE_ALGEBRAIC:
391     cmp = lp_algebraic_number_cmp_rational(&v->value.a, q);
392     break;
393   default:
394     assert(0);
395   }
396 
397   return cmp;
398 }
399 
lp_value_is_rational(const lp_value_t * v)400 int lp_value_is_rational(const lp_value_t* v) {
401   switch (v->type) {
402   case LP_VALUE_INTEGER:
403   case LP_VALUE_DYADIC_RATIONAL:
404   case LP_VALUE_RATIONAL:
405     return 1;
406   case LP_VALUE_ALGEBRAIC:
407     return lp_algebraic_number_is_rational(&v->value.a);
408   default:
409     return 0;
410   }
411 }
412 
lp_value_is_integer(const lp_value_t * v)413 int lp_value_is_integer(const lp_value_t* v) {
414   switch (v->type) {
415   case LP_VALUE_INTEGER:
416     return 1;
417   case LP_VALUE_DYADIC_RATIONAL:
418     return lp_dyadic_rational_is_integer(&v->value.dy_q);
419   case LP_VALUE_RATIONAL:
420     return lp_rational_is_integer(&v->value.q);
421     break;
422   case LP_VALUE_ALGEBRAIC:
423     return lp_algebraic_number_is_integer(&v->value.a);
424   default:
425     return 0;
426   }
427 }
428 
lp_value_is_infinity(const lp_value_t * v)429 int lp_value_is_infinity(const lp_value_t* v) {
430   switch (v->type) {
431   case LP_VALUE_PLUS_INFINITY:
432   case LP_VALUE_MINUS_INFINITY:
433     return 1;
434   default:
435     return 0;
436   }
437 }
438 
lp_value_ceiling(const lp_value_t * v,lp_integer_t * v_ceiling)439 void lp_value_ceiling(const lp_value_t* v, lp_integer_t* v_ceiling) {
440   switch (v->type) {
441   case LP_VALUE_INTEGER:
442     lp_integer_assign(lp_Z, v_ceiling, &v->value.z);
443     break;
444   case LP_VALUE_DYADIC_RATIONAL:
445     lp_dyadic_rational_ceiling(&v->value.dy_q, v_ceiling);
446     break;
447   case LP_VALUE_RATIONAL:
448     lp_rational_ceiling(&v->value.q, v_ceiling);
449     break;
450   case LP_VALUE_ALGEBRAIC:
451     lp_algebraic_number_ceiling(&v->value.a, v_ceiling);
452     break;
453   default:
454     assert(0);
455   }
456 }
457 
lp_value_floor(const lp_value_t * v,lp_integer_t * v_floor)458 void lp_value_floor(const lp_value_t* v, lp_integer_t* v_floor) {
459   switch (v->type) {
460   case LP_VALUE_INTEGER:
461     lp_integer_assign(lp_Z, v_floor, &v->value.z);
462     break;
463   case LP_VALUE_DYADIC_RATIONAL:
464     lp_dyadic_rational_floor(&v->value.dy_q, v_floor);
465     break;
466   case LP_VALUE_RATIONAL:
467     lp_rational_floor(&v->value.q, v_floor);
468     break;
469   case LP_VALUE_ALGEBRAIC:
470     lp_algebraic_number_floor(&v->value.a, v_floor);
471     break;
472   default:
473     assert(0);
474   }
475 }
476 
lp_value_get_rational(const lp_value_t * v,lp_rational_t * q)477 void lp_value_get_rational(const lp_value_t* v, lp_rational_t* q) {
478   lp_rational_t result;
479 
480   switch (v->type) {
481   case LP_VALUE_INTEGER:
482     rational_construct_from_integer(&result, &v->value.z);
483     break;
484   case LP_VALUE_DYADIC_RATIONAL:
485     rational_construct_from_dyadic(&result, &v->value.dy_q);
486     break;
487   case LP_VALUE_RATIONAL:
488     rational_assign(q, &v->value.q);
489     return;
490   case LP_VALUE_ALGEBRAIC:
491     if (lp_dyadic_interval_is_point(&v->value.a.I)) {
492       // It's a point value, so we just get it
493       lp_rational_construct_from_dyadic(&result, lp_dyadic_interval_get_point(&v->value.a.I));
494     } else {
495       const lp_upolynomial_t* v_poly = v->value.a.f;
496       if (lp_upolynomial_degree(v_poly) == 1) {
497         // p = ax + b = 0 => x = -b/a
498         const lp_integer_t* b = lp_upolynomial_const_term(v_poly);
499         const lp_integer_t* a = lp_upolynomial_lead_coeff(v_poly);
500         if (b) {
501           rational_construct_from_div(&result, b, a);
502           rational_neg(&result, &result);
503         } else {
504           rational_construct(&result);
505         }
506       } else {
507         assert(0);
508       }
509     }
510     break;
511   default:
512     assert(0);
513   }
514 
515   rational_swap(&result, q);
516   rational_destruct(&result);
517 }
518 
lp_value_get_num(const lp_value_t * v,lp_integer_t * num)519 void lp_value_get_num(const lp_value_t* v, lp_integer_t* num) {
520   assert(lp_value_is_rational(v));
521   switch (v->type) {
522   case LP_VALUE_INTEGER:
523     integer_assign(lp_Z, num, &v->value.z);
524     break;
525   case LP_VALUE_DYADIC_RATIONAL:
526     dyadic_rational_get_num(&v->value.dy_q, num);
527     break;
528   case LP_VALUE_RATIONAL:
529     rational_get_num(&v->value.q, num);
530     break;
531   case LP_VALUE_ALGEBRAIC:
532     if (lp_dyadic_interval_is_point(&v->value.a.I)) {
533       // It's a point value, so we just get it
534       dyadic_rational_get_num(lp_dyadic_interval_get_point(&v->value.a.I), num);
535     } else {
536       const lp_upolynomial_t* v_poly = v->value.a.f;
537       if (lp_upolynomial_degree(v_poly) == 1) {
538         // p = ax + b = 0 => x = -b/a
539         lp_rational_t value;
540         const lp_integer_t* b = lp_upolynomial_const_term(v_poly);
541         const lp_integer_t* a = lp_upolynomial_lead_coeff(v_poly);
542         if (b) {
543           rational_construct_from_div(&value, b, a);
544           rational_neg(&value, &value);
545         } else {
546           rational_construct(&value);
547         }
548         rational_get_num(&value, num);
549         rational_destruct(&value);
550       } else {
551         assert(0);
552       }
553     }
554     break;
555   default:
556     assert(0);
557   }
558 }
559 
lp_value_get_den(const lp_value_t * v,lp_integer_t * den)560 void lp_value_get_den(const lp_value_t* v, lp_integer_t* den) {
561   assert(lp_value_is_rational(v));
562   switch (v->type) {
563   case LP_VALUE_INTEGER:
564     integer_assign_int(lp_Z, den, 1);
565     break;
566   case LP_VALUE_DYADIC_RATIONAL:
567     dyadic_rational_get_den(&v->value.dy_q, den);
568     break;
569   case LP_VALUE_RATIONAL:
570     rational_get_den(&v->value.q, den);
571     break;
572   case LP_VALUE_ALGEBRAIC:
573     if (lp_dyadic_interval_is_point(&v->value.a.I)) {
574       // It's a point value, so we just get it
575       dyadic_rational_get_den(lp_dyadic_interval_get_point(&v->value.a.I), den);
576     } else {
577       const lp_upolynomial_t* v_poly = v->value.a.f;
578       if (lp_upolynomial_degree(v_poly) == 1) {
579         // p = ax + b = 0 => x = -b/a
580         lp_rational_t value;
581         const lp_integer_t* b = lp_upolynomial_const_term(v_poly);
582         const lp_integer_t* a = lp_upolynomial_lead_coeff(v_poly);
583         if (b) {
584           rational_construct_from_div(&value, b, a);
585           rational_neg(&value, &value);
586         } else {
587           rational_construct(&value);
588         }
589         rational_get_den(&value, den);
590         rational_destruct(&value);
591       } else {
592         assert(0);
593       }
594     }
595     break;
596   default:
597     assert(0);
598   }
599 }
600 
lp_value_to_string(const lp_value_t * v)601 char* lp_value_to_string(const lp_value_t* v) {
602   char* str = 0;
603   size_t size = 0;
604   FILE* f = open_memstream(&str, &size);
605   lp_value_print(v, f);
606   fclose(f);
607   return str;
608 }
609 
lp_value_get_value_between(const lp_value_t * a,int a_strict,const lp_value_t * b,int b_strict,lp_value_t * v)610 void lp_value_get_value_between(const lp_value_t* a, int a_strict, const lp_value_t* b, int b_strict, lp_value_t* v) {
611 
612   if (trace_is_enabled("value::get_value_between")) {
613     tracef("lp_value_get_value_between()\n")
614     tracef("a = "); lp_value_print(a, trace_out); tracef(", a_strict = %d\n", a_strict);
615     tracef("b = "); lp_value_print(b, trace_out); tracef(", b_strict = %d\n", b_strict);
616   }
617 
618   // Compare a and b. If they are equal the only option is the value they hold.
619   // If a > b then we swap them
620   int cmp = lp_value_cmp(a, b);
621   if (cmp == 0) {
622     // Same, we're done
623     assert(!a_strict && !b_strict);
624     lp_value_assign(v, a);
625     return;
626   } else if (cmp > 0) {
627     const lp_value_t* tmp = a; a = b; b = tmp;
628     int strict_tmp = a_strict; a_strict = b_strict; b_strict = strict_tmp;
629   }
630 
631   // If the whole R we're done, just pick 0
632   if (a->type == LP_VALUE_MINUS_INFINITY && b->type == LP_VALUE_PLUS_INFINITY) {
633      // (-inf, +inf), just pick 0
634      lp_integer_t zero;
635      lp_integer_construct(&zero);
636      lp_value_assign_raw(v, LP_VALUE_INTEGER, &zero);
637      lp_integer_destruct(&zero);
638      return;
639    }
640 
641   // We have a < b, at least one of them is not infinity, and comparison ensures
642   // that the algebraic intervals will be disjoint
643 
644   // Get rational values a_ub and b_lb such that a <= a_ub <= b_lb <= b
645   lp_rational_t a_ub, b_lb;
646   int a_inf = 0, b_inf = 0;
647   int a_ub_strict = a_strict;
648   int b_lb_strict = b_strict;
649 
650 
651   switch (a->type) {
652   case LP_VALUE_MINUS_INFINITY:
653     a_inf = 1;
654     break;
655   case LP_VALUE_INTEGER:
656     rational_construct_from_integer(&a_ub, &a->value.z);
657     break;
658   case LP_VALUE_DYADIC_RATIONAL:
659     rational_construct_from_dyadic(&a_ub, &a->value.dy_q);
660     break;
661   case LP_VALUE_RATIONAL:
662     rational_construct_copy(&a_ub, &a->value.q);
663     break;
664   case LP_VALUE_ALGEBRAIC:
665     if (lp_value_is_rational(a)) {
666       rational_construct(&a_ub);
667       lp_value_get_rational(a, &a_ub);
668     } else {
669       // Get the upper bound of the interval as a_ub
670       rational_construct_from_dyadic(&a_ub, &a->value.a.I.b);
671       // Algebaic bound is strict so a_ub can be picked
672       a_ub_strict = 0;
673     }
674     break;
675   default:
676     assert(0);
677   }
678 
679   switch (b->type) {
680   case LP_VALUE_PLUS_INFINITY:
681     b_inf = 1;
682     break;
683   case LP_VALUE_INTEGER:
684     rational_construct_from_integer(&b_lb, &b->value.z);
685     break;
686   case LP_VALUE_DYADIC_RATIONAL:
687     rational_construct_from_dyadic(&b_lb, &b->value.dy_q);
688     break;
689   case LP_VALUE_RATIONAL:
690     rational_construct_copy(&b_lb, &b->value.q);
691     break;
692   case LP_VALUE_ALGEBRAIC:
693     if (lp_value_is_rational(b)) {
694       rational_construct(&b_lb);
695       lp_value_get_rational(b, &b_lb);
696     } else {
697       // Get the lower bound of the interval as b_lb
698       rational_construct_from_dyadic(&b_lb, &b->value.a.I.a);
699       // Algebraic bound is strict so b_lb can be picked
700       b_lb_strict = 0;
701     }
702     break;
703   default:
704     assert(0);
705   }
706 
707   assert(!a_inf || !b_inf);
708 
709   // We have rational values a_ub and b_ub such that a <= a_ub <= b_lb <= b
710   // or one of them is infinity
711 
712   if (a_inf) {
713     // -inf < b_lb <= b
714     // just pick the value to be floor(b_lb)-1
715     lp_integer_t result;
716     lp_integer_construct(&result);
717     rational_floor(&b_lb, &result);
718     lp_integer_dec(lp_Z, &result);
719     lp_value_assign_raw(v, LP_VALUE_INTEGER, &result);
720     lp_integer_destruct(&result);
721     lp_rational_destruct(&b_lb);
722     return;
723   }
724 
725   if (b_inf) {
726     // a <= a_ub < +inf
727     // just pick the value to be ceil(a_ub)+1
728     lp_integer_t result;
729     lp_integer_construct(&result);
730     rational_ceiling(&a_ub, &result);
731     lp_integer_inc(lp_Z, &result);
732     lp_value_assign_raw(v, LP_VALUE_INTEGER, &result);
733     lp_integer_destruct(&result);
734     lp_rational_destruct(&a_ub);
735     return;
736   }
737 
738   // We have rational values a_ub and b_ub such that a <= a_ub <= b_lb <= b
739   // Both a_ub and b_lb are constructed
740 
741   // If a_ub == b_lb, this is due to algebraic number intervals, so refine once more
742   cmp = rational_cmp(&a_ub, &b_lb);
743   if (cmp == 0) {
744     assert(!lp_value_is_rational(a) || !lp_value_is_rational(b));
745     if (!lp_value_is_rational(a)) {
746       assert(a->type == LP_VALUE_ALGEBRAIC);
747       lp_algebraic_number_refine_const(&a->value.a);
748     }
749     if (!lp_value_is_rational(b)) {
750       assert(b->type == LP_VALUE_ALGEBRAIC);
751       lp_algebraic_number_refine_const(&b->value.a);
752     }
753     lp_value_get_value_between(a, a_strict, b, b_strict, v);
754   } else {
755 
756     // To be constructed to the value
757     lp_rational_t result;
758 
759     // Get the smallest integer interval around [a_ub, b_lb] and refine
760 
761     // a <= a_ub < b_lb <= b
762     // m = (a_ub + b_lb)/2 so a < m < b
763     lp_rational_t m;
764     rational_construct(&m);
765     rational_add(&m, &a_ub, &b_lb);
766     rational_div_2exp(&m, &m, 1);
767 
768     // floor(m) <= m <= ceil(m)
769     lp_integer_t m_floor, m_ceil;
770     integer_construct(&m_floor);
771     rational_floor(&m, &m_floor);
772     integer_construct_copy(lp_Z, &m_ceil, &m_floor);
773     integer_inc(lp_Z, &m_ceil);
774 
775     if (trace_is_enabled("value::get_value_between")) {
776       tracef("a_ub = ");
777       lp_rational_print(&a_ub, trace_out);
778       tracef("\n");
779       tracef("b_ub = ");
780       lp_rational_print(&b_lb, trace_out);
781       tracef("\n");
782       tracef("m = ");
783       lp_rational_print(&m, trace_out);
784       tracef("\n");
785       tracef("m_floor = ");
786       lp_integer_print(&m_floor, trace_out);
787       tracef("\n");
788       tracef("m_ceil = ");
789       lp_integer_print(&m_ceil, trace_out);
790       tracef("\n");
791     }
792 
793     // If a_ub < m_floor (or equal and bound allows it), we can take this value
794     cmp = lp_rational_cmp_integer(&a_ub, &m_floor);
795     if (cmp < 0 || (cmp == 0 && !a_ub_strict)) {
796       lp_rational_construct_from_integer(&result, &m_floor);
797     } else {
798       // If m_ceil < b_lb (or equal and bound allows it), we can take this value
799       cmp = lp_rational_cmp_integer(&b_lb, &m_ceil);
800       if (cmp > 0 || (cmp == 0 && !b_lb_strict)) {
801         lp_rational_construct_from_integer(&result, &m_ceil);
802       } else {
803 
804         lp_rational_t lb, ub;
805         rational_construct_from_integer(&lb, &m_floor);
806         rational_construct_from_integer(&ub, &m_ceil);
807 
808         // We have to do the search
809         for (;;) {
810 
811           // always: lb < a_ub <= b_lb < ub
812           rational_add(&m, &lb, &ub);
813           rational_div_2exp(&m, &m, 1);
814 
815           // lb < m < a_ub => move lb to m
816           cmp = rational_cmp(&a_ub, &m);
817           // if ((a_strict && cmp >= 0) || (!a_strict && cmp > 0)) {
818           if (cmp >= 0) {
819             rational_swap(&m, &lb);
820             continue;
821           }
822 
823           // b_lb < m < ub => move ub to m
824           cmp = rational_cmp(&m, &b_lb);
825           // if ((b_strict && cmp >= 0) || (!b_strict && cmp > 0)) {
826           if (cmp >= 0) {
827             rational_swap(&ub, &m);
828             continue;
829           }
830 
831           // Got it l <= m <= u
832           rational_construct_copy(&result, &m);
833           break;
834         }
835 
836         rational_destruct(&lb);
837         rational_destruct(&ub);
838       }
839     }
840 
841     lp_value_assign_raw(v, LP_VALUE_RATIONAL, &result);
842 
843     rational_destruct(&result);
844     integer_destruct(&m_ceil);
845     integer_destruct(&m_floor);
846     rational_destruct(&m);
847   }
848 
849   rational_destruct(&a_ub);
850   rational_destruct(&b_lb);
851 
852   if (trace_is_enabled("value::get_value_between")) {
853     tracef("lp_value_get_value_between() => "); lp_value_print(v, trace_out); tracef("\n");
854   }
855 
856 }
857 
lp_value_get_distance_size_approx(const lp_value_t * lower,const lp_value_t * upper)858 int lp_value_get_distance_size_approx(const lp_value_t* lower, const lp_value_t* upper) {
859 
860   assert(lp_value_cmp(lower, upper) < 0);
861 
862   if (lower->type == LP_VALUE_MINUS_INFINITY) {
863     return INT_MAX;
864   }
865 
866   if (upper->type == LP_VALUE_PLUS_INFINITY) {
867     return INT_MAX;
868   }
869 
870   lp_rational_t lower_approx, upper_approx;
871   rational_construct(&lower_approx);
872   rational_construct(&upper_approx);
873 
874   // Get lower bound approximation
875   if (lp_value_is_rational(lower)) {
876     lp_value_get_rational(lower, &lower_approx);
877   } else {
878     assert(lower->type == LP_VALUE_ALGEBRAIC);
879     assert(!lower->value.a.I.is_point);
880     lp_algebraic_number_get_rational_midpoint(&lower->value.a, &lower_approx);
881   }
882 
883   if (lp_value_is_rational(upper)) {
884     lp_value_get_rational(upper, &upper_approx);
885   } else {
886     assert(upper->type == LP_VALUE_ALGEBRAIC);
887     assert(!upper->value.a.I.is_point);
888     lp_algebraic_number_get_rational_midpoint(&upper->value.a, &upper_approx);
889   }
890 
891   // Get the distance
892   lp_rational_t* m = &lower_approx;
893   lp_rational_sub(m, &upper_approx, &lower_approx);
894 
895   // The denominator and numerator
896   lp_integer_t num, den;
897   integer_construct(&num);
898   integer_construct(&den);
899   rational_get_num(m, &num);
900   rational_get_den(m, &den);
901 
902   // Size = log(num/den) = log(num) - log(den)
903   int size = ((int)integer_log2_abs(&num)) - ((int)integer_log2_abs(&den)) + 1;
904 
905   integer_destruct(&num);
906   integer_destruct(&den);
907   rational_destruct(&lower_approx);
908   rational_destruct(&upper_approx);
909 
910   return size;
911 }
912 
lp_value_hash(const lp_value_t * v)913 size_t lp_value_hash(const lp_value_t* v) {
914   return lp_value_hash_approx(v, 0);
915 }
916 
lp_value_hash_approx(const lp_value_t * v,unsigned precision)917 size_t lp_value_hash_approx(const lp_value_t* v, unsigned precision) {
918   switch (v->type) {
919   case LP_VALUE_NONE:
920     return 0;
921   case LP_VALUE_PLUS_INFINITY:
922     return SIZE_MAX-1;
923   case LP_VALUE_MINUS_INFINITY:
924     return SIZE_MAX;
925   case LP_VALUE_INTEGER:
926     return lp_integer_hash(&v->value.z);
927   case LP_VALUE_DYADIC_RATIONAL:
928     return lp_dyadic_rational_hash_approx(&v->value.dy_q, precision);
929   case LP_VALUE_RATIONAL:
930     return lp_rational_hash_approx(&v->value.q, precision);
931   case LP_VALUE_ALGEBRAIC:
932     return lp_algebraic_number_hash_approx(&v->value.a, precision);
933   default:
934     assert(0);
935     return 0;
936   }
937 }
938 
939 
lp_value_to_double(const lp_value_t * v)940 double lp_value_to_double(const lp_value_t* v) {
941   switch (v->type) {
942   case LP_VALUE_NONE:
943     return 0;
944   case LP_VALUE_PLUS_INFINITY:
945     return INFINITY;
946   case LP_VALUE_MINUS_INFINITY:
947     return -INFINITY;
948   case LP_VALUE_INTEGER:
949     return lp_integer_to_double(&v->value.z);
950   case LP_VALUE_DYADIC_RATIONAL:
951     return lp_dyadic_rational_to_double(&v->value.dy_q);
952   case LP_VALUE_RATIONAL:
953     return lp_rational_to_double(&v->value.q);
954   case LP_VALUE_ALGEBRAIC:
955     return lp_algebraic_number_to_double(&v->value.a);
956   default:
957     assert(0);
958     return 0;
959   }
960 }
961 
962 /**
963  * Case v1 and v2 to the same type.
964  *
965  * @param v1, v2 the values to case
966  * @param v1_tmp the value to use for allocating a new value
967  * @param v1_to_use, v2_to_use the cast values to use
968  */
lp_value_to_same_type(const lp_value_t * v1,const lp_value_t * v2,lp_value_t * v1_new,lp_value_t * v2_new,const lp_value_t ** v1_to_use,const lp_value_t ** v2_to_use)969 int lp_value_to_same_type(const lp_value_t* v1, const lp_value_t* v2,
970     lp_value_t* v1_new, lp_value_t* v2_new,
971     const lp_value_t** v1_to_use, const lp_value_t** v2_to_use) {
972 
973   // trivial
974   if (v1->type == v2->type) {
975     *v1_to_use = v1;
976     *v2_to_use = v2;
977     return 1;
978   }
979 
980   lp_rational_t tmp_rat;
981   lp_dyadic_rational_t tmp_dy;
982   lp_algebraic_number_t tmp_a;
983 
984   switch (v1->type) {
985   case LP_VALUE_INTEGER:
986     switch (v2->type) {
987     case LP_VALUE_DYADIC_RATIONAL:
988       // v1: integer
989       // v2: dyadic rational
990       lp_dyadic_rational_construct_from_integer(&tmp_dy, &v1->value.z);
991       lp_value_construct(v1_new, LP_VALUE_DYADIC_RATIONAL, &tmp_dy);
992       lp_dyadic_rational_destruct(&tmp_dy);
993       *v1_to_use = v1_new;
994       *v2_to_use = v2;
995       break;
996     case LP_VALUE_RATIONAL:
997       // v1: integer
998       // v2: rational
999       lp_rational_construct_from_integer(&tmp_rat, &v1->value.z);
1000       lp_value_construct(v1_new, LP_VALUE_RATIONAL, &tmp_rat);
1001       lp_rational_destruct(&tmp_rat);
1002       *v1_to_use = v1_new;
1003       *v2_to_use = v2;
1004       break;
1005     case LP_VALUE_ALGEBRAIC:
1006       // v1: integer
1007       // v2: algebraic
1008       lp_algebraic_number_construct_from_integer(&tmp_a, &v1->value.z);
1009       lp_value_construct(v1_new, LP_VALUE_ALGEBRAIC, &tmp_a);
1010       lp_algebraic_number_destruct(&tmp_a);
1011       *v1_to_use = v1_new;
1012       *v2_to_use = v2;
1013       break;
1014     default:
1015       // unsupported
1016       return 0;
1017     }
1018     break;
1019   case LP_VALUE_DYADIC_RATIONAL:
1020     switch (v2->type) {
1021     case LP_VALUE_INTEGER:
1022       // v1: dyadic rational
1023       // v2: integer
1024       lp_dyadic_rational_construct_from_integer(&tmp_dy, &v2->value.z);
1025       lp_value_construct(v2_new, LP_VALUE_DYADIC_RATIONAL, &tmp_dy);
1026       lp_dyadic_rational_destruct(&tmp_dy);
1027       *v1_to_use = v1;
1028       *v2_to_use = v2_new;
1029       break;
1030     case LP_VALUE_RATIONAL:
1031       // v1: dyadic rational
1032       // v2: rational
1033       lp_rational_construct_from_dyadic(&tmp_rat, &v1->value.dy_q);
1034       lp_value_construct(v1_new, LP_VALUE_RATIONAL, &tmp_rat);
1035       lp_rational_destruct(&tmp_rat);
1036       *v1_to_use = v1_new;
1037       *v2_to_use = v2;
1038       break;
1039     case LP_VALUE_ALGEBRAIC:
1040       // v1: dyadic rational
1041       // v2: algebraic
1042       lp_algebraic_number_construct_from_dyadic_rational(&tmp_a, &v1->value.dy_q);
1043       lp_value_construct(v1_new, LP_VALUE_ALGEBRAIC, &tmp_a);
1044       lp_algebraic_number_destruct(&tmp_a);
1045       *v1_to_use = v1_new;
1046       *v2_to_use = v2;
1047       break;
1048     default:
1049       // unsupported
1050       return 0;
1051     }
1052     break;
1053   case LP_VALUE_RATIONAL:
1054     switch (v2->type) {
1055     case LP_VALUE_INTEGER:
1056       // v1: rational
1057       // v2: integer
1058       lp_rational_construct_from_integer(&tmp_rat, &v2->value.z);
1059       lp_value_construct(v2_new, LP_VALUE_RATIONAL, &tmp_rat);
1060       lp_rational_destruct(&tmp_rat);
1061       *v1_to_use = v1;
1062       *v2_to_use = v2_new;
1063       break;
1064     case LP_VALUE_DYADIC_RATIONAL:
1065       // v1: rational
1066       // v2: dyadic rational
1067       lp_rational_construct_from_dyadic(&tmp_rat, &v2->value.dy_q);
1068       lp_value_construct(v2_new, LP_VALUE_RATIONAL, &tmp_rat);
1069       lp_rational_destruct(&tmp_rat);
1070       *v1_to_use = v1;
1071       *v2_to_use = v2_new;
1072       break;
1073     case LP_VALUE_ALGEBRAIC:
1074       // v1: rational
1075       // v2: algebraic_number
1076       lp_algebraic_number_construct_from_rational(&tmp_a, &v1->value.q);
1077       lp_value_construct(v1_new, LP_VALUE_ALGEBRAIC, &tmp_a);
1078       lp_algebraic_number_destruct(&tmp_a);
1079       *v1_to_use = v1_new;
1080       *v2_to_use = v2;
1081       break;
1082     default:
1083       // unsupported
1084       return 0;
1085     }
1086     break;
1087   case LP_VALUE_ALGEBRAIC:
1088     switch (v2->type) {
1089     case LP_VALUE_INTEGER:
1090       // v1: algebraic number
1091       // v2: integer
1092       lp_algebraic_number_construct_from_integer(&tmp_a, &v2->value.z);
1093       lp_value_construct(v2_new, LP_VALUE_ALGEBRAIC, &tmp_a);
1094       lp_algebraic_number_destruct(&tmp_a);
1095       *v1_to_use = v1;
1096       *v2_to_use = v2_new;
1097       break;
1098     case LP_VALUE_DYADIC_RATIONAL:
1099       // v1: algebraic number
1100       // v2: dyadic rational
1101       lp_algebraic_number_construct_from_dyadic_rational(&tmp_a, &v2->value.dy_q);
1102       lp_value_construct(v2_new, LP_VALUE_ALGEBRAIC, &tmp_a);
1103       lp_algebraic_number_destruct(&tmp_a);
1104       *v1_to_use = v1;
1105       *v2_to_use = v2_new;
1106       break;
1107     case LP_VALUE_RATIONAL:
1108       // v1: algebraic number
1109       // v2: ratioal number
1110       lp_algebraic_number_construct_from_rational(&tmp_a, &v2->value.q);
1111       lp_value_construct(v2_new, LP_VALUE_ALGEBRAIC, &tmp_a);
1112       lp_algebraic_number_destruct(&tmp_a);
1113       *v1_to_use = v1;
1114       *v2_to_use = v2_new;
1115       break;
1116     default:
1117       // unsupported
1118       return 0;
1119     }
1120     break;
1121   default:
1122     // unsupported
1123     return 0;
1124   }
1125 
1126   return 1;
1127 }
1128 
lp_value_add(lp_value_t * sum,const lp_value_t * a,const lp_value_t * b)1129 void lp_value_add(lp_value_t* sum, const lp_value_t* a, const lp_value_t* b) {
1130 
1131   lp_value_t a_new, b_new;
1132   const lp_value_t *a_to_use = 0;
1133   const lp_value_t *b_to_use = 0;
1134 
1135   // Check for infinities
1136   if (a->type == LP_VALUE_PLUS_INFINITY) {
1137     if (b->type != LP_VALUE_MINUS_INFINITY) {
1138       lp_value_assign_raw(sum, LP_VALUE_PLUS_INFINITY, 0);
1139     } else {
1140       assert(0);
1141     }
1142     return;
1143   } else if (a->type == LP_VALUE_MINUS_INFINITY) {
1144     if (b->type != LP_VALUE_PLUS_INFINITY) {
1145       lp_value_assign_raw(sum, LP_VALUE_MINUS_INFINITY, 0);
1146     } else {
1147       assert(0);
1148     }
1149     return;
1150   } else if (b->type == LP_VALUE_PLUS_INFINITY) {
1151     if (a->type != LP_VALUE_MINUS_INFINITY) {
1152       lp_value_assign_raw(sum, LP_VALUE_PLUS_INFINITY, 0);
1153     } else {
1154       assert(0);
1155     }
1156     return;
1157   } else if (b->type == LP_VALUE_MINUS_INFINITY) {
1158     if (a->type != LP_VALUE_PLUS_INFINITY) {
1159       lp_value_assign_raw(sum, LP_VALUE_MINUS_INFINITY, 0);
1160     } else {
1161       assert(0);
1162     }
1163     return;
1164   }
1165 
1166   // All other cases, cast and run the operation
1167   int ret = lp_value_to_same_type(a, b, &a_new, &b_new, &a_to_use, &b_to_use);
1168   (void) ret;
1169   assert(ret);
1170 
1171   lp_value_t result;
1172 
1173   result.type = a_to_use->type;
1174   switch (result.type) {
1175   case LP_VALUE_INTEGER:
1176     lp_integer_construct(&result.value.z);
1177     lp_integer_add(lp_Z, &result.value.z, &a_to_use->value.z, &b_to_use->value.z);
1178     break;
1179   case LP_VALUE_DYADIC_RATIONAL:
1180     lp_dyadic_rational_construct(&result.value.dy_q);
1181     lp_dyadic_rational_add(&result.value.dy_q, &a_to_use->value.dy_q, &b_to_use->value.dy_q);
1182     break;
1183   case LP_VALUE_RATIONAL:
1184     lp_rational_construct(&result.value.q);
1185     lp_rational_add(&result.value.q, &a_to_use->value.q, &b_to_use->value.q);
1186     break;
1187   case LP_VALUE_ALGEBRAIC:
1188     lp_algebraic_number_construct_zero(&result.value.a);
1189     lp_algebraic_number_add(&result.value.a, &a_to_use->value.a, &b_to_use->value.a);
1190     break;
1191   default:
1192     assert(0);
1193     break;
1194   }
1195 
1196   if (a_to_use != a) {
1197     lp_value_destruct(&a_new);
1198   }
1199   if (b_to_use != b) {
1200     lp_value_destruct(&b_new);
1201   }
1202 
1203   lp_value_swap(sum, &result);
1204   lp_value_destruct(&result);
1205 }
1206 
lp_value_sub(lp_value_t * sub,const lp_value_t * a,const lp_value_t * b)1207 void lp_value_sub(lp_value_t* sub, const lp_value_t* a, const lp_value_t* b) {
1208   lp_value_t b_neg;
1209   lp_value_construct_none(&b_neg);
1210   lp_value_neg(&b_neg, b);
1211   lp_value_add(sub, a, &b_neg);
1212   lp_value_destruct(&b_neg);
1213 }
1214 
lp_value_neg(lp_value_t * neg,const lp_value_t * a)1215 void lp_value_neg(lp_value_t* neg, const lp_value_t* a) {
1216 
1217   lp_value_t result;
1218 
1219   result.type = a->type;
1220   switch(a->type) {
1221   case LP_VALUE_NONE:
1222     break;
1223   case LP_VALUE_INTEGER:
1224     lp_integer_construct(&result.value.z);
1225     lp_integer_neg(lp_Z, &result.value.z, &a->value.z);
1226     break;
1227   case LP_VALUE_DYADIC_RATIONAL:
1228     lp_dyadic_rational_construct(&result.value.dy_q);
1229     lp_dyadic_rational_neg(&result.value.dy_q, &a->value.dy_q);
1230     break;
1231   case LP_VALUE_RATIONAL:
1232     lp_rational_construct(&result.value.q);
1233     lp_rational_neg(&result.value.q, &a->value.q);
1234     break;
1235   case LP_VALUE_ALGEBRAIC:
1236     lp_algebraic_number_construct_zero(&result.value.a);
1237     lp_algebraic_number_neg(&result.value.a, &a->value.a);
1238     break;
1239   case LP_VALUE_PLUS_INFINITY:
1240     result.type = LP_VALUE_MINUS_INFINITY;
1241     break;
1242   case LP_VALUE_MINUS_INFINITY:
1243     result.type = LP_VALUE_PLUS_INFINITY;
1244     break;
1245   }
1246 
1247   lp_value_swap(neg, &result);
1248   lp_value_destruct(&result);
1249 }
1250 
lp_value_mul(lp_value_t * mul,const lp_value_t * a,const lp_value_t * b)1251 void lp_value_mul(lp_value_t* mul, const lp_value_t* a, const lp_value_t* b) {
1252 
1253   lp_value_t a_new, b_new;
1254   const lp_value_t *a_to_use;
1255   const lp_value_t *b_to_use;
1256 
1257   // Check for infinities
1258   if (lp_value_is_infinity(a) || lp_value_is_infinity(b)) {
1259     int sgn_a = lp_value_sgn(a);
1260     int sgn_b = lp_value_sgn(b);
1261     int sgn_mul = sgn_a * sgn_b;
1262     if (sgn_mul > 0) {
1263       lp_value_assign_raw(mul, LP_VALUE_PLUS_INFINITY, 0);
1264     } else if (sgn_mul) {
1265       lp_value_assign_raw(mul, LP_VALUE_MINUS_INFINITY, 0);
1266     } else {
1267       assert(0);
1268     }
1269     return;
1270   }
1271 
1272   // All other cases, cast and run the operation
1273   int ret = lp_value_to_same_type(a, b, &a_new, &b_new, &a_to_use, &b_to_use);
1274   (void) ret;
1275   assert(ret);
1276 
1277   lp_value_t result;
1278 
1279   result.type = a_to_use->type;
1280   switch (result.type) {
1281   case LP_VALUE_INTEGER:
1282     lp_integer_construct(&result.value.z);
1283     lp_integer_mul(lp_Z, &result.value.z, &a_to_use->value.z, &b_to_use->value.z);
1284     break;
1285   case LP_VALUE_DYADIC_RATIONAL:
1286     lp_dyadic_rational_construct(&result.value.dy_q);
1287     lp_dyadic_rational_mul(&result.value.dy_q, &a_to_use->value.dy_q, &b_to_use->value.dy_q);
1288     break;
1289   case LP_VALUE_RATIONAL:
1290     lp_rational_construct(&result.value.q);
1291     lp_rational_mul(&result.value.q, &a_to_use->value.q, &b_to_use->value.q);
1292     break;
1293   case LP_VALUE_ALGEBRAIC:
1294     lp_algebraic_number_construct_zero(&result.value.a);
1295     lp_algebraic_number_mul(&result.value.a, &a_to_use->value.a, &b_to_use->value.a);
1296     break;
1297   default:
1298     assert(0);
1299     break;
1300   }
1301 
1302   if (a_to_use != a) {
1303     lp_value_destruct(&a_new);
1304   }
1305   if (b_to_use != b) {
1306     lp_value_destruct(&b_new);
1307   }
1308 
1309   lp_value_swap(mul, &result);
1310   lp_value_destruct(&result);
1311 }
1312 
lp_value_inv(lp_value_t * inv,const lp_value_t * a)1313 void lp_value_inv(lp_value_t* inv, const lp_value_t* a) {
1314 
1315   lp_value_t result;
1316 
1317   switch(a->type) {
1318   case LP_VALUE_NONE:
1319     break;
1320   case LP_VALUE_INTEGER:
1321     result.type = LP_VALUE_RATIONAL;
1322     lp_rational_construct_from_integer(&result.value.q, &a->value.z);
1323     lp_rational_inv(&result.value.q, &result.value.q);
1324     break;
1325   case LP_VALUE_DYADIC_RATIONAL:
1326     result.type = LP_VALUE_RATIONAL;
1327     lp_rational_construct_from_dyadic(&result.value.q, &a->value.dy_q);
1328     lp_rational_inv(&result.value.q, &result.value.q);
1329     break;
1330   case LP_VALUE_RATIONAL:
1331     result.type = LP_VALUE_RATIONAL;
1332     lp_rational_construct(&result.value.q);
1333     lp_rational_inv(&result.value.q, &a->value.q);
1334     break;
1335   case LP_VALUE_ALGEBRAIC:
1336     result.type = LP_VALUE_ALGEBRAIC;
1337     lp_algebraic_number_construct_zero(&result.value.a);
1338     lp_algebraic_number_inv(&result.value.a, &a->value.a);
1339     break;
1340   case LP_VALUE_PLUS_INFINITY:
1341   case LP_VALUE_MINUS_INFINITY:
1342     lp_value_construct_zero(&result);
1343     break;
1344   }
1345 
1346   lp_value_swap(inv, &result);
1347   lp_value_destruct(&result);
1348 }
1349 
lp_value_div(lp_value_t * div,const lp_value_t * a,const lp_value_t * b)1350 void lp_value_div(lp_value_t* div, const lp_value_t* a, const lp_value_t* b) {
1351   lp_value_t b_inv;
1352   lp_value_construct_none(&b_inv);
1353   lp_value_inv(&b_inv, b);
1354   lp_value_mul(div, a, &b_inv);
1355   lp_value_destruct(&b_inv);
1356 }
1357 
lp_value_pow(lp_value_t * pow,const lp_value_t * a,unsigned n)1358 void lp_value_pow(lp_value_t* pow, const lp_value_t* a, unsigned n) {
1359 
1360   lp_value_t result;
1361 
1362   result.type = a->type;
1363   switch(a->type) {
1364   case LP_VALUE_NONE:
1365     break;
1366   case LP_VALUE_INTEGER:
1367     lp_integer_construct(&result.value.z);
1368     lp_integer_pow(lp_Z, &result.value.z, &a->value.z, n);
1369     break;
1370   case LP_VALUE_DYADIC_RATIONAL:
1371     lp_dyadic_rational_construct(&result.value.dy_q);
1372     lp_dyadic_rational_pow(&result.value.dy_q, &a->value.dy_q, n);
1373     break;
1374   case LP_VALUE_RATIONAL:
1375     lp_rational_construct(&result.value.q);
1376     lp_rational_pow(&result.value.q, &a->value.q, n);
1377     break;
1378   case LP_VALUE_ALGEBRAIC:
1379     lp_algebraic_number_construct_zero(&result.value.a);
1380     lp_algebraic_number_pow(&result.value.a, &a->value.a, n);
1381     break;
1382   case LP_VALUE_PLUS_INFINITY:
1383     result.type = LP_VALUE_MINUS_INFINITY;
1384     break;
1385   case LP_VALUE_MINUS_INFINITY:
1386     if (n % 2) {
1387       result.type = LP_VALUE_MINUS_INFINITY;
1388     } else {
1389       result.type = LP_VALUE_PLUS_INFINITY;
1390     }
1391     break;
1392   }
1393 
1394   lp_value_swap(pow, &result);
1395   lp_value_destruct(&result);
1396 }
1397 
1398