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