1 /*
2 * Normaliz
3 * Copyright (C) 2007-2021 W. Bruns, B. Ichim, Ch. Soeger, U. v. d. Ohe
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * As an exception, when this program is distributed through (i) the App Store
18 * by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or (iii) Google Play
19 * by Google Inc., then that store may impose any digital rights management,
20 * device limits and/or redistribution restrictions that are required by its
21 * terms of service.
22 */
23 //---------------------------------------------------------------------------
24 #ifndef LIBNORMALIZ_VECTOR_OPERATIONS_H
25 #define LIBNORMALIZ_VECTOR_OPERATIONS_H
26 //---------------------------------------------------------------------------
27
28 #include <vector>
29 #include <ostream>
30 #include <list>
31
32 #include "libnormaliz/general.h"
33 #include "libnormaliz/integer.h"
34 // #include "libnormaliz/convert.h"
35 #include "libnormaliz/dynamic_bitset.h"
36
37
38 #ifdef NMZ_FLINT
39 #include "flint/flint.h"
40 #include "flint/fmpq_poly.h"
41 #endif
42
43 namespace libnormaliz {
44 using std::vector;
45
46 //---------------------------------------------------------------------------
47 // Output
48 //---------------------------------------------------------------------------
49
50 template <typename T>
51 std::ostream& operator<<(std::ostream& out, const vector<T>& vec) {
52 for (size_t i = 0; i < vec.size(); ++i) {
53 out << vec[i] << " ";
54 }
55 out << std::endl;
56 return out;
57 }
58
59 //---------------------------------------------------------------------------
60 // Prototypes for vector_operations.cpp
61 //---------------------------------------------------------------------------
62
63 template <typename Integer>
64 Integer v_scalar_product(const vector<Integer>& a, const vector<Integer>& b);
65
66 template <typename Integer>
67 Integer v_make_prime(vector<Integer>& v);
68
69 nmz_float l1norm(vector<nmz_float>& v);
70
71 template <typename Integer>
72 void v_scalar_division(vector<Integer>& v, const Integer scalar);
73
74 // special version of order_by_perm (below) since special swap is needed
75 void order_by_perm_bool(vector<bool>& v, const vector<key_t>& permfix);
76
77 template <typename Integer>
78 vector<Integer> v_select_coordinates(const vector<Integer>& v, const vector<key_t> projection_key);
79 template <typename Integer>
80 vector<Integer> v_insert_coordinates(const vector<Integer>& v, const vector<key_t> projection_key, const size_t nr_cols);
81
82 //---------------------------------------------------------------------------
83 // Templated functions
84 //---------------------------------------------------------------------------
85
86 // returns the scalar product of the truncations of vectors a and b to minimum of lengths
87 // template<typename Integer>
88 template <typename Integer>
v_scalar_product_vectors_unequal_lungth(const vector<Integer> & a,const vector<Integer> & b)89 Integer v_scalar_product_vectors_unequal_lungth(const vector<Integer>& a, const vector<Integer>& b) {
90 size_t n = std::min(a.size(), b.size());
91 vector<Integer> trunc_a = a;
92 vector<Integer> trunc_b = b;
93 trunc_a.resize(n);
94 trunc_b.resize(n);
95 return v_scalar_product(trunc_a, trunc_b);
96 }
97
98 // v = v * scalar
99 template <typename Integer>
v_scalar_multiplication(vector<Integer> & v,const Integer scalar)100 void v_scalar_multiplication(vector<Integer>& v, const Integer scalar) {
101 size_t i, size = v.size();
102 for (i = 0; i < size; i++) {
103 v[i] *= scalar;
104 }
105 }
106
107 // make random vector of length n with entries between -m and m
108 template <typename Integer>
v_random(size_t n,long m)109 vector<Integer> v_random(size_t n, long m) {
110 vector<Integer> result(n);
111 for (size_t i = 0; i < n; ++i)
112 result[i] = rand() % (2 * m + 1) - m;
113 return result;
114 }
115
116 template <typename Integer>
compare_last(const vector<Integer> & a,const vector<Integer> & b)117 bool compare_last(const vector<Integer>& a, const vector<Integer>& b) {
118 return a.back() < b.back();
119 }
120
121 // swaps entry i and j of the vector<bool> v
122 void v_bool_entry_swap(vector<bool>& v, size_t i, size_t j);
123
124 vector<key_t> identity_key(size_t n);
125 vector<key_t> reverse_key(size_t n);
126 vector<key_t> random_key(size_t n);
127
128 template <typename T>
order_by_perm(vector<T> & v,const vector<key_t> & permfix)129 void order_by_perm(vector<T>& v, const vector<key_t>& permfix) {
130 // orders v "in place", v --> w such that
131 // w[i]=v[permfix[i]]
132 // if v is the map i --> v[i], then the resulting map is v \circ permfix
133
134 vector<key_t> perm = permfix; // we may want to use permfix a second time
135 vector<key_t> inv(perm.size());
136 for (key_t i = 0; i < perm.size(); ++i)
137 inv[perm[i]] = i;
138 for (key_t i = 0; i < perm.size(); ++i) {
139 key_t j = perm[i];
140 std::swap(v[i], v[perm[i]]);
141 std::swap(perm[i], perm[inv[i]]);
142 std::swap(inv[i], inv[j]);
143 }
144 }
145
conjugate_perm(const vector<key_t> & p,const vector<key_t> & k)146 inline vector<key_t> conjugate_perm(const vector<key_t>& p, const vector<key_t>& k) {
147 // p is a permutation of [0,n-1], i --> p[i]
148 // k is an injective map [0,m-1] --> [0,n-1]
149 // k^{-1} is the partially defined inverse
150 // computes k^{-1} p k
151 // works only if Image(k) is stable under p.
152
153 vector<int> inv_k(p.size(), -1);
154 for (size_t i = 0; i < k.size(); ++i) {
155 inv_k[k[i]] = i;
156 }
157 vector<key_t> conj(k.size());
158 for (size_t i = 0; i < k.size(); ++i) {
159 assert(inv_k[k[i]] != -1);
160 conj[i] = inv_k[p[k[i]]];
161 }
162 return conj;
163 }
164
165 template <typename T>
sort_individual_vectors(vector<vector<T>> & vv)166 void sort_individual_vectors(vector<vector<T> >& vv) {
167 for (size_t i = 0; i < vv.size(); ++i)
168 sort(vv[i].begin(), vv[i].end());
169 }
170
171 template <typename Integer>
v_scalar_mult_mod_inner(vector<Integer> & w,const vector<Integer> & v,const Integer & scalar,const Integer & modulus)172 bool v_scalar_mult_mod_inner(vector<Integer>& w, const vector<Integer>& v, const Integer& scalar, const Integer& modulus) {
173 size_t i, size = v.size();
174 Integer test;
175 for (i = 0; i < size; i++) {
176 test = v[i] * scalar;
177 if (!check_range(test)) {
178 return false;
179 }
180 w[i] = test % modulus;
181 if (w[i] < 0)
182 w[i] += modulus;
183 }
184 return true;
185 }
186
187 template <typename Integer>
188 vector<Integer> v_scalar_mult_mod(const vector<Integer>& v, const Integer& scalar, const Integer& modulus);
189
190 //---------------------------------------------------------------------------
191
192 /*
193 template <typename Integer>
194 size_t v_nr_negative(const vector<Integer>& v) {
195 size_t tmp = 0;
196 for (size_t i = 0; i < v.size(); ++i) {
197 if (v[i] < 0)
198 tmp++;
199 }
200 return tmp;
201 }
202 */
203 //---------------------------------------------------------------------------
204
205 template <typename Integer>
v_non_negative(const vector<Integer> & v)206 bool v_non_negative(const vector<Integer>& v) {
207 for (size_t i = 0; i < v.size(); ++i) {
208 if (v[i] < 0)
209 return false;
210 }
211 return true;
212 }
213
214 //---------------------------------------------------------------------------
215 /*
216 // returns a key vector containing the positions of non-zero entrys of v
217 template <typename Integer>
218 vector<key_t> v_non_zero_pos(const vector<Integer>& v) {
219 vector<key_t> key;
220 size_t size = v.size();
221 key.reserve(size);
222 for (key_t i = 0; i < size; i++) {
223 if (v[i] != 0) {
224 key.push_back(i);
225 }
226 }
227 return key;
228 }
229 */
230
231 //---------------------------------------------------------------------------
232 // returns the vector of absolute values, does not change the argument
233 template <typename Integer>
v_abs_value(vector<Integer> & v)234 vector<Integer> v_abs_value(vector<Integer>& v) {
235 size_t i, size = v.size();
236 vector<Integer> w = v;
237 for (i = 0; i < size; i++) {
238 if (v[i] < 0)
239 w[i] = Iabs(v[i]);
240 }
241 return w;
242 }
243
244 //---------------------------------------------------------------------------
245 // returns gcd of the elements of v
246 template <typename Integer>
v_gcd(const vector<Integer> & v)247 inline Integer v_gcd(const vector<Integer>& v) {
248 size_t i, size = v.size();
249 Integer g = 0;
250 for (i = 0; i < size; i++) {
251 g = libnormaliz::gcd(g, v[i]);
252 if (g == 1) {
253 return 1;
254 }
255 }
256 return g;
257 }
258
259 template <>
v_gcd(const vector<mpq_class> & v)260 inline mpq_class v_gcd(const vector<mpq_class>& v) {
261 size_t i, size = v.size();
262 mpz_class g = 0;
263 for (i = 0; i < size; i++) {
264 g = libnormaliz::gcd(g, v[i].get_num());
265 if (g == 1) {
266 return 1;
267 }
268 }
269 return mpq_class(g);
270 }
271
272 #ifdef ENFNORMALIZ
273
get_gcd_num(const renf_elem_class & x)274 inline mpz_class get_gcd_num(const renf_elem_class& x) {
275 vector<mpz_class> numerator = x.num_vector();
276 return v_gcd(numerator);
277 }
278
279 template <>
v_gcd(const vector<renf_elem_class> & v)280 inline renf_elem_class v_gcd(const vector<renf_elem_class>& v) {
281 size_t i, size = v.size();
282 mpz_class g = 0;
283 mpz_class this_gcd;
284 for (i = 0; i < size; i++) {
285 // this_gcd=v[i].num_content();
286 this_gcd = get_gcd_num(v[i]);
287 g = libnormaliz::gcd(g, this_gcd);
288 if (g == 1) {
289 return 1;
290 }
291 }
292 return renf_elem_class(g);
293 }
294 #endif
295
296 //---------------------------------------------------------------------------
297 // returns lcm of the elements of v
298 template <typename Integer>
v_lcm(const vector<Integer> & v)299 Integer v_lcm(const vector<Integer>& v) {
300 size_t i, size = v.size();
301 Integer g = 1;
302 for (i = 0; i < size; i++) {
303 g = libnormaliz::lcm(g, v[i]);
304 if (g == 0) {
305 return 0;
306 }
307 }
308 return g;
309 }
310
311
312 // returns lcm of the elements of v from index k up to index j
313 template <typename Integer>
v_lcm_to(const vector<Integer> & v,const size_t k,const size_t j)314 Integer v_lcm_to(const vector<Integer>& v, const size_t k, const size_t j) {
315 assert(k <= j);
316 size_t i;
317 Integer g = 1;
318 for (i = k; i <= j; i++) {
319 g = libnormaliz::lcm(g, v[i]);
320 if (g == 0) {
321 return 0;
322 }
323 }
324 return g;
325 }
326
327
328 //---------------------------------------------------------------------------
329
330 template <typename Integer>
v_abs(vector<Integer> & v)331 vector<Integer>& v_abs(vector<Integer>& v) {
332 size_t i, size = v.size();
333 for (i = 0; i < size; i++) {
334 if (v[i] < 0)
335 v[i] = Iabs(v[i]);
336 }
337 return v;
338 }
339
340 //---------------------------------------------------------------------------
341 // returns a new vector with the content of a extended by b
342 template <typename T>
v_merge(const vector<T> & a,const T & b)343 vector<T> v_merge(const vector<T>& a, const T& b) {
344 size_t s = a.size();
345 vector<T> c(s + 1);
346 for (size_t i = 0; i < s; i++) {
347 c[i] = a[i];
348 }
349 c[s] = b;
350 return c;
351 }
352
353 //---------------------------------------------------------------------------
354
355 template <typename T>
v_merge(const vector<T> & a,const vector<T> & b)356 vector<T> v_merge(const vector<T>& a, const vector<T>& b) {
357 size_t s1 = a.size(), s2 = b.size(), i;
358 vector<T> c(s1 + s2);
359 for (i = 0; i < s1; i++) {
360 c[i] = a[i];
361 }
362 for (i = 0; i < s2; i++) {
363 c[s1 + i] = b[i];
364 }
365 return c;
366 }
367
368 //---------------------------------------------------------------------------
369
370 template <typename Integer>
v_reduction_modulo(vector<Integer> & v,const Integer & modulo)371 void v_reduction_modulo(vector<Integer>& v, const Integer& modulo) {
372 size_t i, size = v.size();
373 for (i = 0; i < size; i++) {
374 v[i] = v[i] % modulo;
375 if (v[i] < 0) {
376 v[i] = v[i] + modulo;
377 }
378 }
379 }
380
381 //---------------------------------------------------------------------------
382
383 template <typename Integer>
v_add_to_mod(vector<Integer> & a,const vector<Integer> & b,const Integer & m)384 vector<Integer>& v_add_to_mod(vector<Integer>& a, const vector<Integer>& b, const Integer& m) {
385 // assert(a.size() == b.size());
386 size_t i, s = a.size();
387 for (i = 0; i < s; i++) {
388 // a[i] = (a[i]+b[i])%m;
389 if ((a[i] += b[i]) >= m) {
390 a[i] -= m;
391 }
392 }
393 return a;
394 }
395
396 //---------------------------------------------------------------------------
397
398 template <typename Integer>
v_is_zero(const vector<Integer> & v)399 bool v_is_zero(const vector<Integer>& v) {
400 for (size_t i = 0; i < v.size(); ++i) {
401 if (v[i] != 0)
402 return false;
403 }
404 return true;
405 }
406
407 //---------------------------------------------------------------------------
408
409 template <typename Integer>
v_add(const vector<Integer> & a,const vector<Integer> & b)410 vector<Integer> v_add(const vector<Integer>& a, const vector<Integer>& b) {
411 assert(a.size() == b.size());
412 size_t i, s = a.size();
413 vector<Integer> d(s);
414 for (i = 0; i < s; i++) {
415 d[i] = a[i] + b[i];
416 }
417 return d;
418 }
419
420 //---------------------------------------------------------------------------
421
422 template <typename Integer>
v_add_result(vector<Integer> & result,const size_t s,const vector<Integer> & a,const vector<Integer> & b)423 void v_add_result(vector<Integer>& result, const size_t s, const vector<Integer>& a, const vector<Integer>& b) {
424 assert(a.size() == b.size() && a.size() == result.size());
425 size_t i;
426 // vector<Integer> d(s);
427 for (i = 0; i < s; i++) {
428 result[i] = a[i] + b[i];
429 }
430 // return d;
431 }
432
433 //---------------------------------------------------------------------------
434 /*
435 // returns a new vector with the last size entries of v
436 template <typename T>
437 vector<T> v_cut_front(const vector<T>& v, size_t size) {
438 size_t s, k;
439 vector<T> tmp(size);
440 s = v.size() - size;
441 for (k = 0; k < size; k++) {
442 tmp[k] = v[s + k];
443 }
444 return tmp;
445 }
446 */
447
448 //---------------------------------------------------------------------------
449
450 template <typename Integer>
v_is_symmetric(const vector<Integer> & v)451 bool v_is_symmetric(const vector<Integer>& v) {
452 for (size_t i = 0; i < v.size() / 2; ++i) {
453 if (v[i] != v[v.size() - 1 - i])
454 return false;
455 }
456 return true;
457 }
458
459 //---------------------------------------------------------------------------
460
461 template <typename Integer>
v_el_trans(const vector<Integer> & av,vector<Integer> & bv,const Integer & F,const size_t start)462 void v_el_trans(const vector<Integer>& av, vector<Integer>& bv, const Integer& F, const size_t start) {
463 size_t i, n = av.size();
464
465 auto a = av.begin();
466 auto b = bv.begin();
467
468 a += start;
469 b += start;
470 n -= start;
471
472 if (n >= 8) {
473 for (i = 0; i < (n >> 3); ++i, a += 8, b += 8) {
474 b[0] += F * a[0];
475 b[1] += F * a[1];
476 b[2] += F * a[2];
477 b[3] += F * a[3];
478 b[4] += F * a[4];
479 b[5] += F * a[5];
480 b[6] += F * a[6];
481 b[7] += F * a[7];
482 }
483 n -= i << 3;
484 }
485
486 if (n >= 4) {
487 b[0] += F * a[0];
488 b[1] += F * a[1];
489 b[2] += F * a[2];
490 b[3] += F * a[3];
491
492 n -= 4;
493 a += 4;
494 b += 4;
495 }
496
497 if (n >= 2) {
498 b[0] += F * a[0];
499 b[1] += F * a[1];
500
501 n -= 2;
502 a += 2;
503 b += 2;
504 }
505
506 if (n > 0)
507 b[0] += F * a[0];
508
509 for (size_t i = 0; i < bv.size(); ++i)
510 if (!check_range(bv[i]))
511 throw ArithmeticException("Vector entry out of range. Imminent danger of arithmetic overflow.");
512 }
513
514 /*
515 template <typename Integer>
516 Integer v_max_abs(const vector<Integer>& v) {
517 Integer tmp = 0;
518 for (size_t i = 0; i < v.size(); i++) {
519 if (Iabs(v[i]) > tmp)
520 tmp = Iabs(v[i]);
521 }
522 return tmp;
523 }
524 */
525
526 template <typename Integer>
527 Integer v_standardize(vector<Integer>& v, const vector<Integer>& LF);
528
529 template <typename Integer>
530 Integer v_standardize(vector<Integer>& v);
531
532 vector<bool> bitset_to_bool(const dynamic_bitset& BS);
533 vector<key_t> bitset_to_key(const dynamic_bitset& BS);
534 dynamic_bitset bool_to_bitset(const vector<bool>& val);
535 dynamic_bitset key_to_bitset(const vector<key_t>& key, long size);
536
537 template <typename Integer>
make_integral(vector<Integer> & vec)538 inline void make_integral(vector<Integer>& vec) {
539 }
540
541 // from the old renfxx.h
542
543 #ifdef ENFNORMALIZ
544
vector2fmpq_poly(fmpq_poly_t flp,const std::vector<mpq_class> & poly_vector)545 inline void vector2fmpq_poly(fmpq_poly_t flp, const std::vector<mpq_class>& poly_vector) {
546 slong n = (slong)poly_vector.size();
547
548 fmpq_poly_fit_length(flp, n);
549 for (size_t i = 0; i < poly_vector.size(); ++i) {
550 fmpq_poly_set_coeff_mpq(flp, (slong)i, poly_vector[i].get_mpq_t());
551 }
552 }
553
fmpq_poly2vector(std::vector<mpq_class> & poly_vector,const fmpq_poly_t flp)554 inline void fmpq_poly2vector(std::vector<mpq_class>& poly_vector, const fmpq_poly_t flp) {
555 slong length = fmpq_poly_length(flp);
556 if (length == 0) {
557 poly_vector.push_back(mpz_class(0));
558 return;
559 }
560 poly_vector.resize(length);
561 for (slong i = 0; i < length; i++) {
562 mpq_t current_coeff;
563 mpq_init(current_coeff);
564 fmpq_poly_get_coeff_mpq(current_coeff, flp, (slong)i);
565 poly_vector[i] = mpq_class(current_coeff);
566 }
567 }
568
569 template <>
make_integral(vector<renf_elem_class> & vec)570 inline void make_integral(vector<renf_elem_class>& vec) {
571 mpz_class denom = 1;
572 for (size_t i = 0; i < vec.size(); ++i) {
573 denom = libnormaliz::lcm(denom, vec[i].den());
574 }
575 renf_elem_class fact(denom);
576 if (fact != 1)
577 v_scalar_multiplication(vec, fact);
578 }
579 #endif
580
581 template <>
make_integral(vector<mpq_class> & vec)582 inline void make_integral(vector<mpq_class>& vec) {
583 mpz_class denom = 1;
584 for (size_t i = 0; i < vec.size(); ++i) {
585 denom = libnormaliz::lcm(denom, vec[i].get_den());
586 }
587 mpq_class fact(denom);
588 if (fact != 1)
589 v_scalar_multiplication(vec, fact);
590 }
591
592 //=============================================================
593
594 // old vector_operations.cpp
595
596 template <typename Integer>
v_scalar_product(const vector<Integer> & av,const vector<Integer> & bv)597 Integer v_scalar_product(const vector<Integer>& av, const vector<Integer>& bv) {
598 // loop stretching ; brings some small speed improvement
599
600 Integer ans = 0;
601 size_t i, n = av.size();
602
603 #if 0 // #ifdef __MIC__ // not for newer compiler versions
604 // this version seems to be better vectorizable on the mic
605 for (i=0; i<n; ++i)
606 ans += av[i]*bv[i];
607
608 #else // __MIC__
609 auto a = av.begin(), b = bv.begin();
610
611 if (n >= 16) {
612 for (i = 0; i < (n >> 4); ++i, a += 16, b += 16) {
613 ans += a[0] * b[0];
614 ans += a[1] * b[1];
615 ans += a[2] * b[2];
616 ans += a[3] * b[3];
617 ans += a[4] * b[4];
618 ans += a[5] * b[5];
619 ans += a[6] * b[6];
620 ans += a[7] * b[7];
621 ans += a[8] * b[8];
622 ans += a[9] * b[9];
623 ans += a[10] * b[10];
624 ans += a[11] * b[11];
625 ans += a[12] * b[12];
626 ans += a[13] * b[13];
627 ans += a[14] * b[14];
628 ans += a[15] * b[15];
629 }
630
631 n -= i << 4;
632 }
633
634 if (n >= 8) {
635 ans += a[0] * b[0];
636 ans += a[1] * b[1];
637 ans += a[2] * b[2];
638 ans += a[3] * b[3];
639 ans += a[4] * b[4];
640 ans += a[5] * b[5];
641 ans += a[6] * b[6];
642 ans += a[7] * b[7];
643
644 n -= 8;
645 a += 8;
646 b += 8;
647 }
648
649 if (n >= 4) {
650 ans += a[0] * b[0];
651 ans += a[1] * b[1];
652 ans += a[2] * b[2];
653 ans += a[3] * b[3];
654
655 n -= 4;
656 a += 4;
657 b += 4;
658 }
659
660 if (n >= 2) {
661 ans += a[0] * b[0];
662 ans += a[1] * b[1];
663
664 n -= 2;
665 a += 2;
666 b += 2;
667 }
668
669 if (n > 0)
670 ans += a[0] * b[0];
671 #endif // __MIC__
672
673 if (!check_range(ans)) {
674 #pragma omp atomic
675 GMP_scal_prod++;
676
677 // cout << "av " << av;
678 // cout << "bv " << bv;
679 vector<mpz_class> mpz_a(av.size()), mpz_b(bv.size());
680 convert(mpz_a, av);
681 convert(mpz_b, bv);
682 convert(ans, v_scalar_product(mpz_a, mpz_b));
683 }
684
685 return ans;
686 }
687
688 template <>
v_scalar_product(const vector<nmz_float> & av,const vector<nmz_float> & bv)689 inline nmz_float v_scalar_product(const vector<nmz_float>& av, const vector<nmz_float>& bv) {
690 // loop stretching ; brings some small speed improvement
691
692 nmz_float ans = 0;
693 size_t i, n = av.size();
694
695 auto a = av.begin(), b = bv.begin();
696
697 if (n >= 16) {
698 for (i = 0; i < (n >> 4); ++i, a += 16, b += 16) {
699 ans += a[0] * b[0];
700 ans += a[1] * b[1];
701 ans += a[2] * b[2];
702 ans += a[3] * b[3];
703 ans += a[4] * b[4];
704 ans += a[5] * b[5];
705 ans += a[6] * b[6];
706 ans += a[7] * b[7];
707 ans += a[8] * b[8];
708 ans += a[9] * b[9];
709 ans += a[10] * b[10];
710 ans += a[11] * b[11];
711 ans += a[12] * b[12];
712 ans += a[13] * b[13];
713 ans += a[14] * b[14];
714 ans += a[15] * b[15];
715 }
716
717 n -= i << 4;
718 }
719
720 if (n >= 8) {
721 ans += a[0] * b[0];
722 ans += a[1] * b[1];
723 ans += a[2] * b[2];
724 ans += a[3] * b[3];
725 ans += a[4] * b[4];
726 ans += a[5] * b[5];
727 ans += a[6] * b[6];
728 ans += a[7] * b[7];
729
730 n -= 8;
731 a += 8;
732 b += 8;
733 }
734
735 if (n >= 4) {
736 ans += a[0] * b[0];
737 ans += a[1] * b[1];
738 ans += a[2] * b[2];
739 ans += a[3] * b[3];
740
741 n -= 4;
742 a += 4;
743 b += 4;
744 }
745
746 if (n >= 2) {
747 ans += a[0] * b[0];
748 ans += a[1] * b[1];
749
750 n -= 2;
751 a += 2;
752 b += 2;
753 }
754
755 if (n > 0)
756 ans += a[0] * b[0];
757
758 return ans;
759 }
760
761 #ifdef ENFNORMALIZ
762
763 template <>
v_scalar_product(const vector<renf_elem_class> & av,const vector<renf_elem_class> & bv)764 inline renf_elem_class v_scalar_product(const vector<renf_elem_class>& av, const vector<renf_elem_class>& bv) {
765 // loop stretching ; brings some small speed improvement
766
767 assert(av.size() == bv.size());
768
769 renf_elem_class ans = 0;
770 size_t n = av.size();
771 renf_elem_class help;
772
773 for (size_t i = 0; i < n; ++i) {
774 if (av[i] != 0 && bv[i] != 0){
775 ans += av[i] * bv[i];
776 /* help = av[i];
777 help *= bv[i]; // does not seem to help
778 ans += help;*/
779 }
780 }
781 return ans;
782 }
783
784 #endif
785
786 //---------------------------------------------------------------------------
787
788 template <>
v_scalar_product(const vector<mpq_class> & av,const vector<mpq_class> & bv)789 inline mpq_class v_scalar_product(const vector<mpq_class>& av, const vector<mpq_class>& bv) {
790 // loop stretching ; brings some small speed improvement
791
792 assert(false);
793 return 0;
794
795 }
796
797 /* body removed for the time being
798 mpq_class ans = 0;
799 size_t i, n = av.size();
800
801 #if 0 // #ifdef __MIC__ // not for newer compiler versions
802 // this version seems to be better vectorizable on the mic
803 for (i=0; i<n; ++i)
804 ans += av[i]*bv[i];
805
806 #else // __MIC__
807 auto a = av.begin(), b = bv.begin();
808
809 if (n >= 16) {
810 for (i = 0; i < (n >> 4); ++i, a += 16, b += 16) {
811 ans += a[0] * b[0];
812 ans += a[1] * b[1];
813 ans += a[2] * b[2];
814 ans += a[3] * b[3];
815 ans += a[4] * b[4];
816 ans += a[5] * b[5];
817 ans += a[6] * b[6];
818 ans += a[7] * b[7];
819 ans += a[8] * b[8];
820 ans += a[9] * b[9];
821 ans += a[10] * b[10];
822 ans += a[11] * b[11];
823 ans += a[12] * b[12];
824 ans += a[13] * b[13];
825 ans += a[14] * b[14];
826 ans += a[15] * b[15];
827 }
828
829 n -= i << 4;
830 }
831
832 if (n >= 8) {
833 ans += a[0] * b[0];
834 ans += a[1] * b[1];
835 ans += a[2] * b[2];
836 ans += a[3] * b[3];
837 ans += a[4] * b[4];
838 ans += a[5] * b[5];
839 ans += a[6] * b[6];
840 ans += a[7] * b[7];
841
842 n -= 8;
843 a += 8;
844 b += 8;
845 }
846
847 if (n >= 4) {
848 ans += a[0] * b[0];
849 ans += a[1] * b[1];
850 ans += a[2] * b[2];
851 ans += a[3] * b[3];
852
853 n -= 4;
854 a += 4;
855 b += 4;
856 }
857
858 if (n >= 2) {
859 ans += a[0] * b[0];
860 ans += a[1] * b[1];
861
862 n -= 2;
863 a += 2;
864 b += 2;
865 }
866
867 if (n > 0)
868 ans += a[0] * b[0];
869 #endif // __MIC__
870
871 return ans;
872 }
873
874 */
875
876 //---------------------------------------------------------------------------
877
878 template <typename Integer>
v_select_coordinates(const vector<Integer> & v,const vector<key_t> projection_key)879 vector<Integer> v_select_coordinates(const vector<Integer>& v, const vector<key_t> projection_key) {
880 vector<Integer> w(projection_key.size());
881 for (size_t i = 0; i < w.size(); ++i)
882 w[i] = v[projection_key[i]];
883 return w;
884 }
885
886 //---------------------------------------------------------------------------
887
888 template <typename Integer>
v_insert_coordinates(const vector<Integer> & v,const vector<key_t> projection_key,const size_t nr_cols)889 vector<Integer> v_insert_coordinates(const vector<Integer>& v, const vector<key_t> projection_key, const size_t nr_cols) {
890 vector<Integer> w(nr_cols);
891 for (size_t i = 0; i < projection_key.size(); ++i) {
892 assert(projection_key[i] < nr_cols);
893 w[projection_key[i]] = v[i];
894 }
895 return w;
896 }
897 //---------------------------------------------------------------------------
898
899
l1norm(vector<nmz_float> & v)900 inline nmz_float l1norm(vector<nmz_float>& v) {
901 size_t i, size = v.size();
902 nmz_float g = 0;
903 for (i = 0; i < size; i++) {
904 if (Iabs(v[i]) > nmz_epsilon)
905 g += Iabs(v[i]);
906 else
907 v[i] = 0;
908 }
909 return g;
910 }
911
912 /*
913 mpq_class l1norm(vector<mpq_class>& v) {
914 size_t i, size = v.size();
915 mpq_class g = 0;
916 for (i = 0; i < size; i++) {
917 if (Iabs(v[i]) > 0)
918 g += Iabs(v[i]);
919 else
920 v[i] = 0;
921 }
922 return g;
923 }
924 */
925
926 /* for nmz_float is norms the vector to l_1 norm 1.
927 *
928 * for mpq_class and renf_elem_class it makes the vector coefficients integral
929 *
930 * then it extracts the gcd of the coefficients
931 */
932
933 template <typename Integer>
v_make_prime(vector<Integer> & v)934 Integer v_make_prime(vector<Integer>& v) {
935 size_t i, size = v.size();
936
937 #ifdef ENFNORMALIZ
938 if (using_renf<Integer>()) {
939 v_standardize(v);
940 make_integral(v);
941 return (1);
942 }
943 #endif
944
945 if (using_mpq_class<Integer>())
946 make_integral(v);
947 Integer g = v_gcd(v);
948 if (g != 0 && g != 1) {
949 for (i = 0; i < size; i++) {
950 v[i] /= g;
951 }
952 }
953 return g;
954 }
955
956
957 template <>
v_make_prime(vector<nmz_float> & v)958 inline nmz_float v_make_prime(vector<nmz_float>& v) {
959 size_t i, size = v.size();
960 nmz_float g = l1norm(v);
961 if (g != 0) {
962 for (i = 0; i < size; i++) {
963 v[i] /= g;
964 }
965 }
966 return g;
967 }
968
969
970 //---------------------------------------------------------------
971
972 // swaps entry i and j of the vector<bool> v
v_bool_entry_swap(vector<bool> & v,size_t i,size_t j)973 inline void v_bool_entry_swap(vector<bool>& v, size_t i, size_t j) {
974 if (v[i] != v[j]) {
975 v[i].flip();
976 v[j].flip();
977 }
978 }
979
980 //---------------------------------------------------------------
981
identity_key(size_t n)982 inline vector<key_t> identity_key(size_t n) {
983 vector<key_t> key(n);
984 for (size_t k = 0; k < n; ++k)
985 key[k] = k;
986 return key;
987 }
988
reverse_key(size_t n)989 inline vector<key_t> reverse_key(size_t n) {
990 vector<key_t> key(n);
991 for (size_t k = 0; k < n; ++k)
992 key[k] = (n - 1) - k;
993 return key;
994 }
995
random_key(size_t n)996 inline vector<key_t> random_key(size_t n) {
997 vector<key_t> key = identity_key(n);
998 for (size_t k = 0; k < 3*n; ++k)
999 std::swap(key[rand() % n], key[rand() % n]);
1000 return key;
1001 }
1002
1003 // vector<bool> is special because ordinary swap is not defined for it
order_by_perm_bool(vector<bool> & v,const vector<key_t> & permfix)1004 inline void order_by_perm_bool(vector<bool>& v, const vector<key_t>& permfix) {
1005 vector<key_t> perm = permfix; // we may want to use permfix a second time
1006 vector<key_t> inv(perm.size());
1007 for (key_t i = 0; i < perm.size(); ++i)
1008 inv[perm[i]] = i;
1009 for (key_t i = 0; i < perm.size(); ++i) {
1010 key_t j = perm[i];
1011 // v.swap(v[i],v[perm[i]]);
1012 v_bool_entry_swap(v, i, perm[i]);
1013 std::swap(perm[i], perm[inv[i]]);
1014 std::swap(inv[i], inv[j]);
1015 }
1016 }
1017
1018 //---------------------------------------------------------------------------
1019
1020 template <typename Integer>
v_scalar_division(vector<Integer> & v,const Integer scalar)1021 void v_scalar_division(vector<Integer>& v, const Integer scalar) {
1022 size_t i, size = v.size();
1023 assert(scalar != 0);
1024 for (i = 0; i < size; i++) {
1025 assert(v[i] % scalar == 0);
1026 v[i] /= scalar;
1027 }
1028 }
1029
1030 template <>
v_scalar_division(vector<nmz_float> & v,const nmz_float scalar)1031 inline void v_scalar_division(vector<nmz_float>& v, const nmz_float scalar) {
1032 size_t i, size = v.size();
1033 assert(scalar != 0);
1034 for (i = 0; i < size; i++) {
1035 v[i] /= scalar;
1036 }
1037 }
1038
1039
1040
1041 template <>
v_scalar_division(vector<mpq_class> & v,const mpq_class scalar)1042 inline void v_scalar_division(vector<mpq_class>& v, const mpq_class scalar) {
1043 size_t i, size = v.size();
1044 assert(scalar != 0);
1045 for (i = 0; i < size; i++) {
1046 v[i] /= scalar;
1047 }
1048 }
1049
1050
1051 #ifdef ENFNORMALIZ
1052 template <>
v_scalar_division(vector<renf_elem_class> & v,const renf_elem_class scalar)1053 inline void v_scalar_division(vector<renf_elem_class>& v, const renf_elem_class scalar) {
1054 size_t i, size = v.size();
1055 assert(scalar != 0);
1056 renf_elem_class fact = 1 / scalar;
1057 for (i = 0; i < size; i++) {
1058 v[i] *= fact;
1059 }
1060 }
1061 #endif
1062
1063 /* v_standardize
1064 *
1065 * defined only for mpq_class, nmz_float and renf_elem_class
1066 *
1067 * makes the value under LF equal to 1 (checks for positivity of value)
1068 *
1069 * or the last component equal to +-1
1070 */
1071
1072 template <typename Integer>
v_standardize(vector<Integer> & v,const vector<Integer> & LF)1073 Integer v_standardize(vector<Integer>& v, const vector<Integer>& LF) {
1074 assert(false);
1075 return 0;
1076 }
1077
1078 template <typename Integer>
v_standardize(vector<Integer> & v)1079 Integer v_standardize(vector<Integer>& v) {
1080 vector<Integer> LF;
1081 return v_standardize(v, LF);
1082 }
1083
1084 template <>
v_standardize(vector<nmz_float> & v,const vector<nmz_float> & LF)1085 inline nmz_float v_standardize(vector<nmz_float>& v, const vector<nmz_float>& LF) {
1086 nmz_float denom = 0;
1087 if (LF.size() == v.size()) {
1088 denom = v_scalar_product(v, LF);
1089 }
1090
1091 if (denom == 0) {
1092 for (long i = (long)v.size() - 1; i >= 0; --i) {
1093 if (v[i] != 0) {
1094 denom = v[i];
1095 break;
1096 }
1097 }
1098 }
1099 denom = Iabs(denom);
1100
1101 if (denom == 0)
1102 return denom;
1103 if (denom != 1)
1104 v_scalar_division(v, denom);
1105
1106 return denom;
1107 }
1108
1109 /*
1110 template <>
1111 mpq_class v_standardize(vector<mpq_class>& v, const vector<mpq_class>& LF) {
1112 mpq_class denom = 0;
1113 if (LF.size() == v.size()) {
1114 denom = v_scalar_product(v, LF);
1115 };
1116
1117 if (denom == 0) {
1118 for (long i = (long)v.size() - 1; i >= 0; --i) {
1119 if (v[i] != 0) {
1120 denom = v[i];
1121 break;
1122 }
1123 }
1124 }
1125 denom = Iabs(denom);
1126
1127 if (denom == 0)
1128 return denom;
1129 if (denom != 1)
1130 v_scalar_division(v, denom);
1131
1132 return denom;
1133 }
1134 */
1135
1136 #ifdef ENFNORMALIZ
1137
1138 template <>
v_standardize(vector<renf_elem_class> & v,const vector<renf_elem_class> & LF)1139 inline renf_elem_class v_standardize(vector<renf_elem_class>& v, const vector<renf_elem_class>& LF) {
1140 renf_elem_class denom = 0;
1141 if (LF.size() == v.size()) {
1142 denom = v_scalar_product(v, LF);
1143 }
1144
1145 if (denom == 0) {
1146 for (long i = (long)v.size() - 1; i >= 0; --i) {
1147 if (v[i] != 0) {
1148 denom = v[i];
1149 break;
1150 }
1151 }
1152 }
1153 denom = Iabs(denom);
1154
1155 if (denom == 0)
1156 return denom;
1157 if (denom != 1)
1158 v_scalar_division(v, denom);
1159
1160 return denom;
1161 }
1162 #endif
1163
1164
1165 /* Not used presently
1166 // the following function removes the denominators and then extracts the Gcd of the numerators
1167 mpq_class v_standardize(vector<mpq_class>& v, const vector<mpq_class>& LF){
1168 size_t size=v.size();
1169 mpz_class d=1;
1170 for (size_t i = 0; i < size; i++)
1171 //d=lcm(d,v[i].get_den()); // GMP C++ function only available in GMP >= 6.1
1172 mpz_lcm(d.get_mpz_t(), d.get_mpz_t(), v[i].get_den().get_mpz_t());
1173 for (size_t i = 0; i < size; i++)
1174 v[i]*=d;
1175 mpz_class g=0;
1176 for (size_t i = 0; i < size; i++)
1177 //g=gcd(g,v[i].get_num()); // GMP C++ function only available in GMP >= 6.1
1178 mpz_gcd(g.get_mpz_t(), g.get_mpz_t(), v[i].get_num().get_mpz_t());
1179 if (g==0)
1180 return 0;
1181 for (size_t i = 0; i < size; i++)
1182 v[i]/=g;
1183 return 1;
1184 }
1185 */
1186
1187 template <typename Integer>
v_scalar_mult_mod(const vector<Integer> & v,const Integer & scalar,const Integer & modulus)1188 vector<Integer> v_scalar_mult_mod(const vector<Integer>& v, const Integer& scalar, const Integer& modulus) {
1189 vector<Integer> w(v.size());
1190 if (v_scalar_mult_mod_inner(w, v, scalar, modulus))
1191 return w;
1192
1193 #pragma omp atomic
1194 GMP_scal_prod++;
1195 vector<mpz_class> x, y(v.size());
1196 convert(x, v);
1197 v_scalar_mult_mod_inner(y, x, convertTo<mpz_class>(scalar), convertTo<mpz_class>(modulus));
1198 return convertTo<vector<Integer> >(y);
1199 }
1200
bitset_to_bool(const dynamic_bitset & val)1201 inline vector<bool> bitset_to_bool(const dynamic_bitset& val) {
1202 vector<bool> ret(val.size());
1203 for (size_t i = 0; i < val.size(); ++i)
1204 ret[i] = val[i];
1205 return ret;
1206 }
1207
bool_to_bitset(const vector<bool> & val)1208 inline dynamic_bitset bool_to_bitset(const vector<bool>& val) {
1209 dynamic_bitset ret(val.size());
1210 for (size_t i = 0; i < val.size(); ++i)
1211 ret[i] = val[i];
1212 return ret;
1213 }
1214
bitset_to_key(const dynamic_bitset & val)1215 inline vector<key_t> bitset_to_key(const dynamic_bitset& val) {
1216 vector<key_t> ret;
1217 for (size_t i = 0; i < val.size(); ++i)
1218 if(val[i])
1219 ret.push_back(i);
1220 return ret;
1221 }
1222
key_to_bitset(const vector<key_t> & key,long size)1223 inline dynamic_bitset key_to_bitset(const vector<key_t>& key, long size){
1224
1225 dynamic_bitset bs(size);
1226 for(size_t i=0; i< key.size(); ++i){
1227 assert(key[i] < size);
1228 bs[key[i]] = 1;
1229 }
1230 return bs;
1231 }
1232
1233 template<typename T>
binary_expansion(T n)1234 vector<bool> binary_expansion(T n){
1235 vector<bool> bin;
1236 while(n != 0){
1237 bin.push_back(n & 1);
1238 n = n >> 1;
1239 }
1240 return bin;
1241 }
1242
1243 template <typename Integer>
vector_sum_cascade(vector<Integer> & summands)1244 Integer vector_sum_cascade(vector<Integer>& summands){
1245 size_t step =2;
1246 bool added = true;
1247 while(added){
1248 added = false;
1249 #pragma omp parallel for
1250 for(size_t k=0; k < summands.size(); k+=step){
1251 if(summands.size() > k + step/2){
1252 summands[k] += summands[k+ step/2];
1253 added = true;
1254 }
1255 }
1256 step *=2;
1257 }
1258 return summands[0];
1259 }
1260
1261 //--------------------------------------------------------------
1262
1263 template <typename Integer>
1264 class AdditionPyramid {
1265
1266 public:
1267
1268 vector<Integer> accumulator;
1269 vector<size_t> counter;
1270 size_t capacity;
1271 void add_inner(const Integer summand, const size_t level);
1272
1273 AdditionPyramid();
1274 AdditionPyramid(const size_t& given_capacity);
1275 void add(const Integer& summand);
1276 Integer sum();
1277 void reset();
1278 void set_capacity(const size_t& given_capacity);
1279 };
1280
1281 template <typename Integer>
add_inner(const Integer summand,const size_t level)1282 void AdditionPyramid<Integer>::add_inner(const Integer summand, const size_t level){
1283
1284 // cout << "***** " << summand << " -- " << level << endl;
1285
1286 assert(level <= counter.size());
1287
1288 if(level == counter.size()){
1289 counter.resize(level+1);
1290 accumulator.resize(level+1);
1291 // cout << "$$$$$ " << accumulator[level] << " -- " << summand << endl;
1292 accumulator[level] = summand;
1293 // cout << "+++ " << accumulator[level] << endl;
1294 return;
1295 }
1296
1297 counter[level]++;
1298
1299 if(counter[level] < capacity){
1300 accumulator[level] += summand;
1301 return;
1302 }
1303
1304 add_inner(accumulator[level], level+1);
1305 counter[level] = 0;
1306 accumulator[level] = summand;
1307 }
1308
1309 template <typename Integer>
AdditionPyramid()1310 AdditionPyramid<Integer>::AdditionPyramid(){
1311
1312 }
1313
1314 template <typename Integer>
reset()1315 void AdditionPyramid<Integer>::reset(){
1316
1317 counter.clear();
1318 accumulator.clear();
1319 }
1320
1321 template <typename Integer>
AdditionPyramid(const size_t & given_capacity)1322 AdditionPyramid<Integer>::AdditionPyramid(const size_t& given_capacity){
1323 capacity = given_capacity;
1324 reset();
1325 }
1326
1327 template <typename Integer>
set_capacity(const size_t & given_capacity)1328 void AdditionPyramid<Integer>::set_capacity(const size_t& given_capacity){
1329 capacity = given_capacity;
1330 }
1331
1332 template <typename Integer>
sum()1333 Integer AdditionPyramid<Integer>::sum(){
1334 Integer our_sum; // this version works also for CoCoALib::Bigrat
1335 our_sum = 0;
1336 for(size_t i=0; i<accumulator.size();++i)
1337 our_sum += accumulator[i];
1338 return our_sum;
1339 }
1340
1341 template <typename Integer>
add(const Integer & summand)1342 void AdditionPyramid<Integer>::add(const Integer& summand){
1343
1344 if(counter.size()>0){
1345 if(counter[0] < capacity-1){
1346 counter[0]++;
1347 accumulator[0] += summand;
1348 return;
1349 }
1350 }
1351 add_inner(summand,0);
1352 }
1353
1354
1355 } // namespace libnormaliz
1356
1357 //---------------------------------------------------------------------------
1358 #endif
1359 //---------------------------------------------------------------------------
1360