Orbiter 2022
Combinatorial Objects
linear_algebra2.cpp
Go to the documentation of this file.
1/*
2 * linear_algebra2.cpp
3 *
4 * Created on: Jan 10, 2022
5 * Author: betten
6 */
7
8
9
10
11#include "foundations.h"
12
13using namespace std;
14
15
16
17namespace orbiter {
18namespace layer1_foundations {
19namespace linear_algebra {
20
21
22void linear_algebra::get_coefficients_in_linear_combination(
23 int k, int n, int *basis_of_subspace,
24 int *input_vector, int *coefficients, int verbose_level)
25// basis[k * n]
26// coefficients[k]
27// input_vector[n] is the input vector.
28// At the end, coefficients[k] are the coefficients of the linear combination
29// which expresses input_vector[n] in terms of the given basis of the subspace.
30{
31 int f_v = (verbose_level >= 1);
32 int i;
33
34 if (f_v) {
35 cout << "linear_algebra::get_coefficients_in_linear_combination" << endl;
36 }
37
38 int *M;
39 int *base_cols;
40 int j;
41
42 M = NEW_int(n * (k + 1));
43 base_cols = NEW_int(n);
44 for (j = 0; j < k; j++) {
45 for (i = 0; i < n; i++) {
46 M[i * (k + 1) + j] = basis_of_subspace[j * n + i];
47 }
48 }
49 for (i = 0; i < n; i++) {
50 M[i * (k + 1) + k] = input_vector[i];
51 }
52
53 if (f_v) {
54 cout << "linear_algebra::get_coefficients_in_linear_combination before Gauss_int" << endl;
55 Int_matrix_print(M, n, k + 1);
56 }
57
58 Gauss_int(M, FALSE /* f_special */,
59 TRUE /* f_complete */, base_cols,
60 FALSE /* f_P */, NULL /* P */, n, k + 1,
61 k + 1 /* Pn */, 0 /* verbose_level */);
62
63
64 if (f_v) {
65 cout << "linear_algebra::get_coefficients_in_linear_combination after Gauss_int" << endl;
66 Int_matrix_print(M, n, k + 1);
67 }
68
69 for (i = 0; i < k; i++) {
70 coefficients[i] = M[i * (k + 1) + k];
71 }
72
73 if (f_v) {
74 cout << "linear_algebra::get_coefficients_in_linear_combination done" << endl;
75 }
76}
77
78
79void linear_algebra::reduce_mod_subspace_and_get_coefficient_vector(
80 int k, int len, int *basis, int *base_cols,
81 int *v, int *coefficients, int verbose_level)
82// basis[k * len]
83// base_cols[k]
84// coefficients[k]
85// v[len] is the input vector and the output vector.
86// At the end, it is the residue,
87// i.e. the reduced coset representative modulo the subspace
88{
89 int f_v = (verbose_level >= 1);
90 int f_vv = (verbose_level >= 2);
91 int i, idx;
92
93 if (f_v) {
94 cout << "linear_algebra::reduce_mod_subspace_and_get_coefficient_vector" << endl;
95 }
96 if (f_vv) {
97 cout << "linear_algebra::reduce_mod_subspace_and_get_coefficient_vector: v=";
98 Int_vec_print(cout, v, len);
99 cout << endl;
100 }
101 if (f_vv) {
102 cout << "linear_algebra::reduce_mod_subspace_and_get_coefficient_vector "
103 "subspace basis:" << endl;
104 Int_vec_print_integer_matrix_width(cout, basis, k, len, len, F->log10_of_q);
105 }
106 for (i = 0; i < k; i++) {
107 idx = base_cols[i];
108 if (basis[i * len + idx] != 1) {
109 cout << "linear_algebra::reduce_mod_subspace_and_get_coefficient_vector "
110 "pivot entry is not one" << endl;
111 cout << "i=" << i << endl;
112 cout << "idx=" << idx << endl;
114 k, len, len, F->log10_of_q);
115 exit(1);
116 }
117 coefficients[i] = v[idx];
118 if (v[idx]) {
119 Gauss_step(basis + i * len, v, len, idx, 0/*verbose_level*/);
120 if (v[idx]) {
121 cout << "linear_algebra::reduce_mod_subspace_and_get_coefficient_vector "
122 "fatal: v[idx]" << endl;
123 exit(1);
124 }
125 }
126 }
127 if (f_vv) {
128 cout << "linear_algebra::reduce_mod_subspace_and_get_coefficient_vector "
129 "after: v=";
130 Int_vec_print(cout, v, len);
131 cout << endl;
132 cout << "coefficients=";
133 Int_vec_print(cout, coefficients, k);
134 cout << endl;
135 }
136 if (f_v) {
137 cout << "linear_algebra::reduce_mod_subspace_and_get_coefficient_vector done" << endl;
138 }
139}
140
141void linear_algebra::reduce_mod_subspace(int k,
142 int len, int *basis, int *base_cols,
143 int *v, int verbose_level)
144{
145 int f_v = (verbose_level >= 1);
146 int f_vv = (verbose_level >= 2);
147 int i, idx;
148
149 if (f_v) {
150 cout << "linear_algebra::reduce_mod_subspace" << endl;
151 }
152 if (f_vv) {
153 cout << "linear_algebra::reduce_mod_subspace before: v=";
154 Int_vec_print(cout, v, len);
155 cout << endl;
156 }
157 if (f_vv) {
158 cout << "linear_algebra::reduce_mod_subspace subspace basis:" << endl;
160 len, len, F->log10_of_q);
161 }
162 for (i = 0; i < k; i++) {
163 idx = base_cols[i];
164 if (v[idx]) {
165 Gauss_step(basis + i * len,
166 v, len, idx, 0/*verbose_level*/);
167 if (v[idx]) {
168 cout << "linear_algebra::reduce_mod_subspace fatal: v[idx]" << endl;
169 exit(1);
170 }
171 }
172 }
173 if (f_vv) {
174 cout << "linear_algebra::reduce_mod_subspace after: v=";
175 Int_vec_print(cout, v, len);
176 cout << endl;
177 }
178 if (f_v) {
179 cout << "linear_algebra::reduce_mod_subspace done" << endl;
180 }
181}
182
183int linear_algebra::is_contained_in_subspace(int k,
184 int len, int *basis, int *base_cols,
185 int *v, int verbose_level)
186{
187 int f_v = (verbose_level >= 1);
188 int f_vv = (verbose_level >= 2);
189 int i;
190
191 if (f_v) {
192 cout << "linear_algebra::is_contained_in_subspace" << endl;
193 }
194 if (f_vv) {
195 cout << "linear_algebra::is_contained_in_subspace testing v=";
196 Int_vec_print(cout, v, len);
197 cout << endl;
198 }
199 reduce_mod_subspace(k, len, basis,
200 base_cols, v, verbose_level - 1);
201 for (i = 0; i < len; i++) {
202 if (v[i]) {
203 if (f_vv) {
204 cout << "linear_algebra::is_contained_in_subspace "
205 "is NOT in the subspace" << endl;
206 }
207 return FALSE;
208 }
209 }
210 if (f_vv) {
211 cout << "linear_algebra::is_contained_in_subspace "
212 "is contained in the subspace" << endl;
213 }
214 if (f_v) {
215 cout << "linear_algebra::is_contained_in_subspace done" << endl;
216 }
217 return TRUE;
218}
219
220int linear_algebra::is_subspace(int d, int dim_U,
221 int *Basis_U, int dim_V, int *Basis_V,
222 int verbose_level)
223{
224 int f_v = (verbose_level >= 1);
225 int *Basis;
226 int h, rk, ret;
227
228 if (f_v) {
229 cout << "linear_algebra::is_subspace" << endl;
230 }
231 Basis = NEW_int((dim_V + 1) * d);
232 for (h = 0; h < dim_U; h++) {
233
234 Int_vec_copy(Basis_V, Basis, dim_V * d);
235 Int_vec_copy(Basis_U + h * d, Basis + dim_V * d, d);
236 rk = Gauss_easy(Basis, dim_V + 1, d);
237 if (rk > dim_V) {
238 ret = FALSE;
239 goto done;
240 }
241 }
242 ret = TRUE;
243done:
244 FREE_int(Basis);
245 if (f_v) {
246 cout << "linear_algebra::is_subspace done" << endl;
247 }
248 return ret;
249}
250
251void linear_algebra::Kronecker_product(int *A, int *B, int n, int *AB)
252{
253 int i, j, I, J, u, v, a, b, c, n2;
254
255 n2 = n * n;
256 for (I = 0; I < n; I++) {
257 for (J = 0; J < n; J++) {
258 b = B[I * n + J];
259 for (i = 0; i < n; i++) {
260 for (j = 0; j < n; j++) {
261 a = A[i * n + j];
262 c = F->mult(a, b);
263 u = I * n + i;
264 v = J * n + j;
265 AB[u * n2 + v] = c;
266 }
267 }
268 }
269 }
270}
271
272void linear_algebra::Kronecker_product_square_but_arbitrary(
273 int *A, int *B,
274 int na, int nb, int *AB, int &N,
275 int verbose_level)
276{
277 int f_v = (verbose_level >= 1);
278 int i, j, I, J, u, v, a, b, c;
279
280 if (f_v) {
281 cout << "linear_algebra::Kronecker_product_square_but_arbitrary"
282 << endl;
283 cout << "na=" << na << endl;
284 cout << "nb=" << nb << endl;
285 }
286 N = na * nb;
287 if (f_v) {
288 cout << "N=" << N << endl;
289 }
290 for (I = 0; I < nb; I++) {
291 for (J = 0; J < nb; J++) {
292 b = B[I * nb + J];
293 for (i = 0; i < na; i++) {
294 for (j = 0; j < na; j++) {
295 a = A[i * na + j];
296 c = F->mult(a, b);
297 u = I * na + i;
298 v = J * na + j;
299 AB[u * N + v] = c;
300 }
301 }
302 }
303 }
304 if (f_v) {
305 cout << "linear_algebra::Kronecker_product_square_but_arbitrary "
306 "done" << endl;
307 }
308}
309
310int linear_algebra::dependency(int d,
311 int *v, int *A, int m, int *rho,
312 int verbose_level)
313// Lueneburg~\cite{Lueneburg87a} p. 104.
314// A is a matrix of size d + 1 times d
315// v[d]
316// rho is a column permutation of degree d
317{
318 int f_v = (verbose_level >= 1);
319 int f_vv = (verbose_level >= 2);
320 int i, j, k, f_null, c;
321
322 if (f_v) {
323 cout << "linear_algebra::dependency" << endl;
324 cout << "m = " << m << endl;
325 cout << "d = " << d << endl;
326 }
327 if (f_vv) {
328 cout << "linear_algebra::dependency A=" << endl;
329 Int_matrix_print(A, m, d);
330 cout << "v = ";
331 Int_vec_print(cout, v, d);
332 cout << endl;
333 }
334 // fill the m-th row of matrix A with v^rho:
335 for (j = 0; j < d; j++) {
336 A[m * d + j] = v[rho[j]];
337 }
338 if (f_vv) {
339 cout << "linear_algebra::dependency "
340 "after putting in row " << m << " A=" << endl;
341 Int_matrix_print(A, m + 1, d);
342 cout << "rho = ";
343 Int_vec_print(cout, rho, d);
344 cout << endl;
345 }
346 for (k = 0; k < m; k++) {
347
348 if (f_vv) {
349 cout << "linear_algebra::dependency "
350 "k=" << k << " / m=" << m << endl;
351 cout << "finite_field::dependency A=" << endl;
352 Int_matrix_print(A, m + 1, d);
353 }
354
355 for (j = k + 1; j < d; j++) {
356
357 if (f_vv) {
358 cout << "linear_algebra::dependency "
359 "k=" << k << " / m=" << m
360 << ", j=" << j << " / " << d << endl;
361 }
362
363
364 // a_{m,j} := a_{k,k} * a_{m,j}:
365
366 A[m * d + j] = F->mult(A[k * d + k], A[m * d + j]);
367
368
369 // a_{m,j} = a_{m,j} - a_{m,k} * a_{k,j}:
370
371 c = F->negate(F->mult(A[m * d + k], A[k * d + j]));
372 A[m * d + j] = F->add(A[m * d + j], c);
373
374 if (k > 0) {
375
376 // a_{m,j} := a_{m,j} / a_{k-1,k-1}:
377
378 c = F->inverse(A[(k - 1) * d + k - 1]);
379 A[m * d + j] = F->mult(A[m * d + j], c);
380 }
381
382 if (f_vv) {
383 cout << "linear_algebra::dependency "
384 "k=" << k << " / m=" << m
385 << ", j=" << j << " / " << d << " done" << endl;
386 cout << "linear_algebra::dependency A=" << endl;
387 Int_matrix_print(A, m + 1, d);
388 }
389
390 } // next j
391
392 if (f_vv) {
393 cout << "linear_algebra::dependency "
394 "k=" << k << " / m=" << m << " done" << endl;
395 cout << "finite_field::dependency A=" << endl;
396 Int_matrix_print(A, m + 1, d);
397 }
398
399 } // next k
400
401 if (f_vv) {
402 cout << "linear_algebra::dependency "
403 "m=" << m << " after reapply, A=" << endl;
404 Int_matrix_print(A, m + 1, d);
405 cout << "rho = ";
406 Int_vec_print(cout, rho, d);
407 cout << endl;
408 }
409
410 if (m == d) {
411 f_null = TRUE;
412 }
413 else {
414 f_null = FALSE;
415 }
416
417 if (!f_null) {
418
419 // search for a pivot in row m:
420 //
421 // search for an non-zero entry
422 // in row m starting in column m.
423 // permute that column into column m,
424 // change the col-permutation rho
425
426 j = m;
427 while ((A[m * d + j] == 0) && (j < d - 1)) {
428 j++;
429 }
430 f_null = (A[m * d + j] == 0);
431
432 if (!f_null && j > m) {
433 if (f_vv) {
434 cout << "linear_algebra::dependency "
435 "choosing column " << j << endl;
436 }
437
438 // swap columns m and j (only the first m + 1 elements in each column):
439
440 for (i = 0; i <= m; i++) {
441 c = A[i * d + m];
442 A[i * d + m] = A[i * d + j];
443 A[i * d + j] = c;
444 }
445
446 // update the permutation rho:
447 c = rho[m];
448 rho[m] = rho[j];
449 rho[j] = c;
450 }
451 }
452 if (f_vv) {
453 cout << "linear_algebra::dependency m=" << m
454 << " after pivoting, A=" << endl;
455 Int_matrix_print(A, m + 1, d);
456 cout << "rho = ";
457 Int_vec_print(cout, rho, d);
458 cout << endl;
459 }
460
461 if (f_v) {
462 cout << "linear_algebra::dependency "
463 "done, f_null = " << f_null << endl;
464 }
465 return f_null;
466}
467
468void linear_algebra::order_ideal_generator(int d,
469 int idx, int *mue, int &mue_deg,
470 int *A, int *Frobenius,
471 int verbose_level)
472// Lueneburg~\cite{Lueneburg87a} p. 105.
473// Frobenius is a matrix of size d x d
474// A is (d + 1) x d
475// mue[d + 1]
476{
477 int f_v = (verbose_level >= 1);
478 int deg;
479 int *v, *v1, *rho;
480 int i, j, m, a, f_null;
481
482 if (f_v) {
483 cout << "linear_algebra::order_ideal_generator "
484 "d = " << d << " idx = " << idx << endl;
485 }
486 deg = d;
487
488 v = NEW_int(deg);
489 v1 = NEW_int(deg);
490 rho = NEW_int(deg);
491
492 // make v the idx-th unit vector:
493 Int_vec_zero(v, deg);
494 v[idx] = 1;
495
496 // make rho the identity permutation:
497 for (i = 0; i < deg; i++) {
498 rho[i] = i;
499 }
500
501 m = 0;
502 if (f_v) {
503 cout << "linear_algebra::order_ideal_generator "
504 "d = " << d << " idx = " << idx << " m=" << m << " before dependency" << endl;
505 }
506 f_null = dependency(d, v, A, m, rho, verbose_level - 1);
507 if (f_v) {
508 cout << "linear_algebra::order_ideal_generator "
509 "d = " << d << " idx = " << idx << " m=" << m << " after dependency" << endl;
510 }
511
512 while (!f_null) {
513
514 // apply frobenius
515 // (the images are written in the columns):
516
517 if (f_v) {
518 cout << "linear_algebra::order_ideal_generator v=";
519 Int_vec_print(cout, v, deg);
520 cout << endl;
521 }
522 mult_vector_from_the_right(Frobenius, v, v1, deg, deg);
523 if (f_v) {
524 cout << "linear_algebra::order_ideal_generator v1=";
525 Int_vec_print(cout, v1, deg);
526 cout << endl;
527 }
528 Int_vec_copy(v1, v, deg);
529
530 m++;
531 if (f_v) {
532 cout << "linear_algebra::order_ideal_generator "
533 "d = " << d << " idx = " << idx
534 << " m=" << m << " before dependency" << endl;
535 }
536 f_null = dependency(d, v, A, m, rho, verbose_level - 1);
537 if (f_v) {
538 cout << "linear_algebra::order_ideal_generator "
539 "d = " << d << " idx = " << idx
540 << " m=" << m << " after dependency, f_null=" << f_null << endl;
541 }
542
543 if (m == deg && !f_null) {
544 cout << "linear_algebra::order_ideal_generator "
545 "m == deg && ! f_null" << endl;
546 exit(1);
547 }
548 }
549
550 mue_deg = m;
551 mue[m] = 1;
552 for (j = m - 1; j >= 0; j--) {
553 mue[j] = A[m * deg + j];
554 if (f_v) {
555 cout << "linear_algebra::order_ideal_generator "
556 "mue[" << j << "] = " << mue[j] << endl;
557 }
558 for (i = m - 1; i >= j + 1; i--) {
559 a = F->mult(mue[i], A[i * deg + j]);
560 mue[j] = F->add(mue[j], a);
561 if (f_v) {
562 cout << "linear_algebra::order_ideal_generator "
563 "mue[" << j << "] = " << mue[j] << endl;
564 }
565 }
566 a = F->negate(F->inverse(A[j * deg + j]));
567 mue[j] = F->mult(mue[j], a);
568 //g_asr(- mue[j] * -
569 // g_inv_mod(Normal_basis[j * dim_nb + j], chi), chi);
570 if (f_v) {
571 cout << "linear_algebra::order_ideal_generator "
572 "mue[" << j << "] = " << mue[j] << endl;
573 }
574 }
575
576 if (f_v) {
577 cout << "linear_algebra::order_ideal_generator "
578 "after preparing mue:" << endl;
579 cout << "mue_deg = " << mue_deg << endl;
580 cout << "mue = ";
581 Int_vec_print(cout, mue, mue_deg + 1);
582 cout << endl;
583 }
584
585 FREE_int(v);
586 FREE_int(v1);
587 FREE_int(rho);
588 if (f_v) {
589 cout << "linear_algebra::order_ideal_generator done" << endl;
590 }
591}
592
593void linear_algebra::span_cyclic_module(int *A,
594 int *v, int n, int *Mtx, int verbose_level)
595{
596 int f_v = (verbose_level >= 1);
597 int *w1, *w2;
598 int i, j;
599
600 if (f_v) {
601 cout << "linear_algebra::span_cyclic_module" << endl;
602 }
603 w1 = NEW_int(n);
604 w2 = NEW_int(n);
605 Int_vec_copy(v, w1, n);
606 for (j = 0; j < n; j++) {
607
608 // put w1 in the j-th column of A:
609 for (i = 0; i < n; i++) {
610 A[i * n + j] = w1[i];
611 }
612 mult_vector_from_the_right(Mtx, w1, w2, n, n);
613 Int_vec_copy(w2, w1, n);
614 }
615
616 FREE_int(w1);
617 FREE_int(w2);
618 if (f_v) {
619 cout << "linear_algebra::span_cyclic_module done" << endl;
620 }
621}
622
623void linear_algebra::random_invertible_matrix(int *M,
624 int k, int verbose_level)
625{
626 int f_v = (verbose_level >= 1);
627 int f_vv = (verbose_level >= 2);
628 int *N;
629 int i, qk, r, rk;
633
634 if (f_v) {
635 cout << "linear_algebra::random_invertible_matrix" << endl;
636 }
637 qk = NT.i_power_j(F->q, k);
638 N = NEW_int(k * k);
639 for (i = 0; i < k; i++) {
640 if (f_vv) {
641 cout << "i=" << i << endl;
642 }
643 while (TRUE) {
644 r = Os.random_integer(qk);
645 if (f_vv) {
646 cout << "r=" << r << endl;
647 }
648 Gg.AG_element_unrank(F->q, M + i * k, 1, k, r);
649 if (f_vv) {
650 Int_matrix_print(M, i + 1, k);
651 }
652
653 Int_vec_copy(M, N, (i + 1) * k);
654 rk = Gauss_easy(N, i + 1, k);
655 if (f_vv) {
656 cout << "rk=" << rk << endl;
657 }
658 if (rk == i + 1) {
659 if (f_vv) {
660 cout << "has full rank" << endl;
661 }
662 break;
663 }
664 }
665 }
666 if (f_v) {
667 cout << "linear_algebra::random_invertible_matrix "
668 "Random invertible matrix:" << endl;
669 Int_matrix_print(M, k, k);
670 }
671 FREE_int(N);
672}
673
674void linear_algebra::adjust_basis(int *V, int *U,
675 int n, int k, int d, int verbose_level)
676// V[k * n], U[d * n] and d <= k.
677{
678 int f_v = (verbose_level >= 1);
679 int i, j, ii, b;
680 int *base_cols;
681 int *M;
683
684 if (f_v) {
685 cout << "linear_algebra::adjust_basis" << endl;
686 }
687 base_cols = NEW_int(n);
688 M = NEW_int((k + d) * n);
689
690 Int_vec_copy(U, M, d * n);
691 if (f_v) {
692 cout << "linear_algebra::adjust_basis before Gauss step, U=" << endl;
693 Int_matrix_print(M, d, n);
694 }
695
696 if (Gauss_simple(M, d, n, base_cols,
697 0 /* verbose_level */) != d) {
698 cout << "linear_algebra::adjust_basis rank "
699 "of matrix is not d" << endl;
700 exit(1);
701 }
702 if (f_v) {
703 cout << "linear_algebra::adjust_basis after Gauss step, M=" << endl;
704 Int_matrix_print(M, d, n);
705 }
706
707 ii = 0;
708 for (i = 0; i < k; i++) {
709
710 // take the i-th vector of V:
711 Int_vec_copy(V + i * n, M + (d + ii) * n, n);
712
713
714 // and reduce it modulo the basis of the d-dimensional subspace U:
715
716 for (j = 0; j < d; j++) {
717 b = base_cols[j];
718 if (f_v) {
719 cout << "linear_algebra::adjust_basis before Gauss step:" << endl;
720 Int_matrix_print(M, d + ii + 1, n);
721 }
722 Gauss_step(M + j * n, M + (d + ii) * n,
723 n, b, 0 /* verbose_level */);
724
725 // corrected a mistake! A Betten 11/1/2021,
726 // the first argument was M + b * n but should be M + j * n
727 if (f_v) {
728 cout << "linear_algebra::adjust_basis after Gauss step:" << endl;
729 Int_matrix_print(M, d + ii + 1, n);
730 }
731 }
732 if (Sorting.int_vec_is_zero(M + (d + ii) * n, n)) {
733 // the vector lies in the subspace. Skip
734 }
735 else {
736
737 // the vector is not in the subspace, keep:
738
739 ii++;
740 }
741
742 // stop when we have reached a basis for V:
743
744 if (d + ii == k) {
745 break;
746 }
747 }
748 if (d + ii != k) {
749 cout << "linear_algebra::adjust_basis d + ii != k" << endl;
750 cout << "linear_algebra::adjust_basis d = " << d << endl;
751 cout << "linear_algebra::adjust_basis ii = " << ii << endl;
752 cout << "linear_algebra::adjust_basis k = " << k << endl;
753 cout << "V=" << endl;
754 Int_matrix_print(V, k, n);
755 cout << endl;
756 cout << "U=" << endl;
757 Int_matrix_print(V, d, n);
758 cout << endl;
759 exit(1);
760 }
761 Int_vec_copy(M, V, k * n);
762
763
764 FREE_int(M);
765 FREE_int(base_cols);
766 if (f_v) {
767 cout << "linear_algebra::adjust_basis done" << endl;
768 }
769}
770
771void linear_algebra::choose_vector_in_here_but_not_in_here_column_spaces(
773 int verbose_level)
774{
775 int f_v = (verbose_level >= 1);
776 int n, k, d;
777 int *Gen;
778 int *base_cols;
779 int i, j, ii, b;
781
782 if (f_v) {
783 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_"
784 "column_spaces" << endl;
785 }
786 n = V->m;
787 if (V->m != W->m) {
788 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_"
789 "column_spaces V->m != W->m" << endl;
790 exit(1);
791 }
792 k = V->n;
793 d = W->n;
794 if (d >= k) {
795 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_"
796 "column_spaces W->n >= V->n" << endl;
797 exit(1);
798 }
799 Gen = NEW_int(k * n);
800 base_cols = NEW_int(n);
801
802 for (i = 0; i < d; i++) {
803 for (j = 0; j < n; j++) {
804 Gen[i * n + j] = W->s_ij(j, i);
805 }
806 }
807 if (Gauss_simple(Gen, d, n,
808 base_cols, 0 /* verbose_level */) != d) {
809 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_"
810 "column_spaces rank of matrix is not d" << endl;
811 exit(1);
812 }
813 ii = 0;
814 for (i = 0; i < k; i++) {
815 for (j = 0; j < n; j++) {
816 Gen[(d + ii) * n + j] = V->s_ij(j, i);
817 }
818 b = base_cols[i];
819 Gauss_step(Gen + b * n, Gen + (d + ii) * n,
820 n, b, 0 /* verbose_level */);
821 if (Sorting.int_vec_is_zero(Gen + (d + ii) * n, n)) {
822 }
823 else {
824 ii++;
825 }
826 }
827 if (d + ii != k) {
828 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_"
829 "column_spaces d + ii != k" << endl;
830 exit(1);
831 }
832 Int_vec_copy(Gen + d * n, v, n);
833
834
835 FREE_int(Gen);
836 FREE_int(base_cols);
837 if (f_v) {
838 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_"
839 "column_spaces done" << endl;
840 }
841}
842
843void linear_algebra::choose_vector_in_here_but_not_in_here_or_here_column_spaces(
846 int verbose_level)
847{
848
849 int coset = 0;
850
852 coset, V, W1, W2, v, verbose_level);
853
854}
855
856int linear_algebra::choose_vector_in_here_but_not_in_here_or_here_column_spaces_coset(
857 int &coset,
860 int verbose_level)
861{
862 int f_v = (verbose_level >= 1);
863 int f_vv = (verbose_level >= 2);
864 int n, k, d1, d2, rk;
865 int *Gen;
866 int *base_cols;
867 int *w;
868 int *z;
869 int i, j, b;
870 int ret = TRUE;
874
875 if (f_v) {
876 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_or_here_"
877 "column_spaces_coset coset=" << coset << endl;
878 cout << "verbose_level = " << verbose_level << endl;
879 }
880 if (f_vv) {
881 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_or_here_"
882 "column_spaces_coset" << endl;
883 cout << "V=" << endl;
884 V->print();
885 cout << "W1=" << endl;
886 W1->print();
887 cout << "W2=" << endl;
888 W2->print();
889 }
890 n = V->m;
891 if (V->m != W1->m) {
892 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_or_here_"
893 "column_spaces_coset V->m != W1->m" << endl;
894 exit(1);
895 }
896 if (V->m != W2->m) {
897 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_or_here_"
898 "column_spaces_coset V->m != W2->m" << endl;
899 exit(1);
900 }
901 k = V->n;
902 d1 = W1->n;
903 d2 = W2->n;
904 if (d1 >= k) {
905 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_or_here_"
906 "column_spaces_coset W1->n >= V->n" << endl;
907 exit(1);
908 }
909 Gen = NEW_int((d1 + d2 + k) * n);
910 base_cols = NEW_int(n);
911 w = NEW_int(k);
912 z = NEW_int(n);
913
914 for (i = 0; i < d1; i++) {
915 for (j = 0; j < n; j++) {
916 Gen[i * n + j] = W1->s_ij(j, i);
917 }
918 }
919 for (i = 0; i < d2; i++) {
920 for (j = 0; j < n; j++) {
921 Gen[(d1 + i) * n + j] = W2->s_ij(j, i);
922 }
923 }
924 rk = Gauss_simple(Gen, d1 + d2, n, base_cols, 0 /* verbose_level */);
925
926
927 int a;
928
929 while (TRUE) {
930 if (coset >= NT.i_power_j(F->q, k)) {
931 if (f_vv) {
932 cout << "coset = " << coset << " = " << NT.i_power_j(F->q, k)
933 << " break" << endl;
934 }
935 ret = FALSE;
936 break;
937 }
938 Gg.AG_element_unrank(F->q, w, 1, k, coset);
939
940 if (f_vv) {
941 cout << "coset=" << coset << " w=";
942 Int_vec_print(cout, w, k);
943 cout << endl;
944 }
945
946 coset++;
947
948 // get a linear combination of the generators of V:
949 for (j = 0; j < n; j++) {
950 Gen[rk * n + j] = 0;
951 for (i = 0; i < k; i++) {
952 a = w[i];
953 Gen[rk * n + j] = F->add(Gen[rk * n + j], F->mult(a, V->s_ij(j, i)));
954 }
955 }
956 Int_vec_copy(Gen + rk * n, z, n);
957 if (f_vv) {
958 cout << "before reduce=";
959 Int_vec_print(cout, Gen + rk * n, n);
960 cout << endl;
961 }
962
963 // reduce modulo the subspace:
964 for (j = 0; j < rk; j++) {
965 b = base_cols[j];
966 Gauss_step(Gen + j * n, Gen + rk * n, n, b, 0 /* verbose_level */);
967 }
968
969 if (f_vv) {
970 cout << "after reduce=";
971 Int_vec_print(cout, Gen + rk * n, n);
972 cout << endl;
973 }
974
975
976 // see if we got something nonzero:
977 if (!Sorting.int_vec_is_zero(Gen + rk * n, n)) {
978 break;
979 }
980 // keep moving on to the next vector
981
982 } // while
983
984 Int_vec_copy(z, v, n);
985
986
987 FREE_int(Gen);
988 FREE_int(base_cols);
989 FREE_int(w);
990 FREE_int(z);
991 if (f_v) {
992 cout << "linear_algebra::choose_vector_in_here_but_not_in_here_"
993 "or_here_column_spaces_coset done ret = " << ret << endl;
994 }
995 return ret;
996}
997
998void linear_algebra::vector_add_apply(int *v, int *w, int c, int n)
999{
1000 int i;
1001
1002 for (i = 0; i < n; i++) {
1003 v[i] = F->add(v[i], F->mult(c, w[i]));
1004 }
1005}
1006
1007void linear_algebra::vector_add_apply_with_stride(int *v, int *w,
1008 int stride, int c, int n)
1009{
1010 int i;
1011
1012 for (i = 0; i < n; i++) {
1013 v[i] = F->add(v[i], F->mult(c, w[i * stride]));
1014 }
1015}
1016
1017int linear_algebra::test_if_commute(int *A, int *B, int k, int verbose_level)
1018{
1019 int f_v = (verbose_level >= 1);
1020 int *M1, *M2;
1021 int ret;
1023
1024 if (f_v) {
1025 cout << "linear_algebra::test_if_commute" << endl;
1026 }
1027 M1 = NEW_int(k * k);
1028 M2 = NEW_int(k * k);
1029
1030 mult_matrix_matrix(A, B, M1, k, k, k, 0 /* verbose_level */);
1031 mult_matrix_matrix(B, A, M2, k, k, k, 0 /* verbose_level */);
1032 if (Sorting.int_vec_compare(M1, M2, k * k) == 0) {
1033 ret = TRUE;
1034 }
1035 else {
1036 ret = FALSE;
1037 }
1038
1039 FREE_int(M1);
1040 FREE_int(M2);
1041 if (f_v) {
1042 cout << "linear_algebra::test_if_commute done" << endl;
1043 }
1044 return ret;
1045}
1046
1047void linear_algebra::unrank_point_in_PG(int *v, int len, int rk)
1048// len is the length of the vector, not the projective dimension
1049{
1050
1051 F->PG_element_unrank_modified(v, 1 /* stride */, len, rk);
1052}
1053
1054int linear_algebra::rank_point_in_PG(int *v, int len)
1055{
1056 int rk;
1057
1058 F->PG_element_rank_modified(v, 1 /* stride */, len, rk);
1059 return rk;
1060}
1061
1062int linear_algebra::nb_points_in_PG(int n)
1063// n is projective dimension
1064{
1065 int N;
1067
1068 N = Gg.nb_PG_elements(n, F->q);
1069 return N;
1070}
1071
1072void linear_algebra::Borel_decomposition(int n, int *M,
1073 int *B1, int *B2, int *pivots, int verbose_level)
1074{
1075 //verbose_level = 1;
1076 int f_v = (verbose_level >= 1);
1077 //int f_vv = (verbose_level >= 2);
1078 int i, j, a, av, b, c, h, k, d, e, mc;
1079 int *f_is_pivot;
1080
1081 if (f_v) {
1082 cout << "linear_algebra::Borel_decomposition" << endl;
1083 }
1084 if (f_v) {
1085 cout << "linear_algebra::Borel_decomposition input matrix:" << endl;
1086 cout << "M:" << endl;
1087 Int_matrix_print(M, n, n);
1088 }
1089
1090 identity_matrix(B1, n);
1091 identity_matrix(B2, n);
1092
1093
1094 f_is_pivot = NEW_int(n);
1095 for (i = 0; i < n; i++) {
1096 f_is_pivot[i] = FALSE;
1097 }
1098 if (f_v) {
1099 cout << "linear_algebra::Borel_decomposition going down "
1100 "from the right" << endl;
1101 }
1102 for (j = n - 1; j >= 0; j--) {
1103 for (i = 0; i < n; i++) {
1104 if (f_is_pivot[i]) {
1105 continue;
1106 }
1107 if (M[i * n + j]) {
1108 if (f_v) {
1109 cout << "linear_algebra::Borel_decomposition pivot "
1110 "at (" << i << " " << j << ")" << endl;
1111 }
1112 f_is_pivot[i] = TRUE;
1113 pivots[j] = i;
1114 a = M[i * n + j];
1115 av = F->inverse(a);
1116
1117 // we can only go down:
1118 for (h = i + 1; h < n; h++) {
1119 b = M[h * n + j];
1120 if (b) {
1121 c = F->mult(av, b);
1122 mc = F->negate(c);
1123 for (k = 0; k < n; k++) {
1124 d = F->mult(M[i * n + k], mc);
1125 e = F->add(M[h * n + k], d);
1126 M[h * n + k] = e;
1127 }
1128 //mc = negate(c);
1129 //cout << "finite_field::Borel_decomposition "
1130 // "i=" << i << " h=" << h << " mc=" << mc << endl;
1131 // multiply the inverse of the elementary matrix
1132 // to the right of B1:
1133 for (k = 0; k < n; k++) {
1134 d = F->mult(B1[k * n + h], c);
1135 e = F->add(B1[k * n + i], d);
1136 B1[k * n + i] = e;
1137 }
1138 //cout << "finite_field::Borel_decomposition B1:"
1139 //<< endl;
1140 //int_matrix_print(B1, n, n);
1141 }
1142 }
1143 if (f_v) {
1144 cout << "linear_algebra::Borel_decomposition after going "
1145 "down in column " << j << endl;
1146 cout << "M:" << endl;
1147 Int_matrix_print(M, n, n);
1148 }
1149
1150 // now we go to the left from the pivot:
1151 for (h = 0; h < j; h++) {
1152 b = M[i * n + h];
1153 if (b) {
1154 c = F->mult(av, b);
1155 mc = F->negate(c);
1156 for (k = i; k < n; k++) {
1157 d = F->mult(M[k * n + j], mc);
1158 e = F->add(M[k * n + h], d);
1159 M[k * n + h] = e;
1160 }
1161 //mc = negate(c);
1162 //cout << "finite_field::Borel_decomposition "
1163 // "j=" << j << " h=" << h << " mc=" << mc << endl;
1164 // multiply the inverse of the elementary matrix
1165 // to the left of B2:
1166 for (k = 0; k < n; k++) {
1167 d = F->mult(B2[h * n + k], c);
1168 e = F->add(B2[j * n + k], d);
1169 B2[j * n + k] = e;
1170 }
1171 }
1172 }
1173 if (f_v) {
1174 cout << "linear_algebra::Borel_decomposition after going "
1175 "across to the left:" << endl;
1176 cout << "M:" << endl;
1177 Int_matrix_print(M, n, n);
1178 }
1179 break;
1180 }
1181
1182 }
1183 }
1184 FREE_int(f_is_pivot);
1185 if (f_v) {
1186 cout << "linear_algebra::Borel_decomposition done" << endl;
1187 }
1188}
1189
1190void linear_algebra::map_to_standard_frame(int d, int *A,
1191 int *Transform, int verbose_level)
1192// d = vector space dimension
1193// maps d + 1 points to the frame e_1, e_2, ..., e_d, e_1+e_2+..+e_d
1194// A is (d + 1) x d
1195// Transform is d x d
1196{
1197 int f_v = (verbose_level >= 1);
1198 int *B;
1199 int *A2;
1200 int n, xd, x, i, j;
1201
1202 if (f_v) {
1203 cout << "linear_algebra::map_to_standard_frame" << endl;
1204 }
1205
1206 if (f_v) {
1207 cout << "A=" << endl;
1208 Int_matrix_print(A, d + 1, d);
1209 }
1210
1211 n = d + 1;
1212 B = NEW_int(n * n);
1213 A2 = NEW_int(d * d);
1214 for (i = 0; i < n; i++) {
1215 for (j = 0; j < d; j++) {
1216 B[j * n + i] = A[i * d + j];
1217 }
1218 }
1219 if (f_v) {
1220 cout << "B before=" << endl;
1221 Int_matrix_print(B, d, n);
1222 }
1223 RREF_and_kernel(n, d, B, 0 /* verbose_level */);
1224 if (f_v) {
1225 cout << "B after=" << endl;
1226 Int_matrix_print(B, n, n);
1227 }
1228 xd = B[d * n + d - 1];
1229 x = F->negate(F->inverse(xd));
1230 for (i = 0; i < d; i++) {
1231 B[d * n + i] = F->mult(x, B[d * n + i]);
1232 }
1233 if (f_v) {
1234 cout << "last row of B after scaling : " << endl;
1235 Int_matrix_print(B + d * n, 1, n);
1236 }
1237 for (i = 0; i < d; i++) {
1238 for (j = 0; j < d; j++) {
1239 A2[i * d + j] = F->mult(B[d * n + i], A[i * d + j]);
1240 }
1241 }
1242 if (f_v) {
1243 cout << "A2=" << endl;
1244 Int_matrix_print(A2, d, d);
1245 }
1246 matrix_inverse(A2, Transform, d, 0 /* verbose_level */);
1247
1248 FREE_int(B);
1249 FREE_int(A2);
1250 if (f_v) {
1251 cout << "linear_algebra::map_to_standard_frame done" << endl;
1252 }
1253}
1254
1255void linear_algebra::map_frame_to_frame_with_permutation(int d,
1256 int *A, int *perm, int *B, int *Transform,
1257 int verbose_level)
1258{
1259 int f_v = (verbose_level >= 1);
1260 int *T1;
1261 int *T2;
1262 int *T3;
1263 int *A1;
1264 int i, j;
1265
1266 if (f_v) {
1267 cout << "linear_algebra::map_frame_to_frame_with_permutation" << endl;
1268 }
1269 T1 = NEW_int(d * d);
1270 T2 = NEW_int(d * d);
1271 T3 = NEW_int(d * d);
1272 A1 = NEW_int((d + 1) * d);
1273
1274 if (f_v) {
1275 cout << "permutation: ";
1276 Int_vec_print(cout, perm, d + 1);
1277 cout << endl;
1278 }
1279 if (f_v) {
1280 cout << "A=" << endl;
1281 Int_matrix_print(A, d + 1, d);
1282 }
1283 if (f_v) {
1284 cout << "B=" << endl;
1285 Int_matrix_print(B, d + 1, d);
1286 }
1287
1288 for (i = 0; i < d + 1; i++) {
1289 j = perm[i];
1290 Int_vec_copy(A + j * d, A1 + i * d, d);
1291 }
1292
1293 if (f_v) {
1294 cout << "A1=" << endl;
1295 Int_matrix_print(A1, d + 1, d);
1296 }
1297
1298
1299 if (f_v) {
1300 cout << "mapping A1 to standard frame:" << endl;
1301 }
1302 map_to_standard_frame(d, A1, T1, verbose_level);
1303 if (f_v) {
1304 cout << "T1=" << endl;
1305 Int_matrix_print(T1, d, d);
1306 }
1307 if (f_v) {
1308 cout << "mapping B to standard frame:" << endl;
1309 }
1310 map_to_standard_frame(d, B, T2, 0 /* verbose_level */);
1311 if (f_v) {
1312 cout << "T2=" << endl;
1313 Int_matrix_print(T2, d, d);
1314 }
1315 matrix_inverse(T2, T3, d, 0 /* verbose_level */);
1316 if (f_v) {
1317 cout << "T3=" << endl;
1318 Int_matrix_print(T3, d, d);
1319 }
1320 mult_matrix_matrix(T1, T3, Transform, d, d, d, 0 /* verbose_level */);
1321 if (f_v) {
1322 cout << "Transform=" << endl;
1323 Int_matrix_print(Transform, d, d);
1324 }
1325
1326 FREE_int(T1);
1327 FREE_int(T2);
1328 FREE_int(T3);
1329 FREE_int(A1);
1330 if (f_v) {
1331 cout << "linear_algebra::map_frame_to_frame_with_permutation done"
1332 << endl;
1333 }
1334}
1335
1336
1337void linear_algebra::map_points_to_points_projectively(int d, int k,
1338 int *A, int *B, int *Transform, int &nb_maps,
1339 int verbose_level)
1340// A and B are (d + k + 1) x d
1341// Transform is d x d
1342// returns TRUE if a map exists
1343{
1344 int f_v = (verbose_level >= 1);
1345 int *lehmercode;
1346 int *perm;
1347 int *A1;
1348 int *B1;
1349 int *B_set;
1350 int *image_set;
1351 int *v;
1352 int h, i, j, a;
1353 int *subset; // [d + k + 1]
1354 int nCk;
1355 int cnt, overall_cnt;
1358
1359 if (f_v) {
1360 cout << "linear_algebra::map_points_to_points_projectively" << endl;
1361 }
1362 lehmercode = NEW_int(d + 1);
1363 perm = NEW_int(d + 1);
1364 A1 = NEW_int((d + k + 1) * d);
1365 B1 = NEW_int((d + k + 1) * d);
1366 B_set = NEW_int(d + k + 1);
1367 image_set = NEW_int(d + k + 1);
1368 subset = NEW_int(d + k + 1);
1369 v = NEW_int(d);
1370
1371 Int_vec_copy(B, B1, (d + k + 1) * d);
1372 for (i = 0; i < d + k + 1; i++) {
1373 //PG_element_normalize(*this, B1 + i * d, 1, d);
1374 F->PG_element_rank_modified(B1 + i * d, 1, d, a);
1375 B_set[i] = a;
1376 }
1377 Sorting.int_vec_heapsort(B_set, d + k + 1);
1378 if (f_v) {
1379 cout << "B_set = ";
1380 Int_vec_print(cout, B_set, d + k + 1);
1381 cout << endl;
1382 }
1383
1384
1385 overall_cnt = 0;
1386 nCk = Combi.int_n_choose_k(d + k + 1, d + 1);
1387 for (h = 0; h < nCk; h++) {
1388 Combi.unrank_k_subset(h, subset, d + k + 1, d + 1);
1389 Combi.set_complement(subset, d + 1, subset + d + 1, k, d + k + 1);
1390
1391 if (f_v) {
1392 cout << "subset " << h << " / " << nCk << " is ";
1393 Int_vec_print(cout, subset, d + 1);
1394 cout << ", the complement is ";
1395 Int_vec_print(cout, subset + d + 1, k);
1396 cout << endl;
1397 }
1398
1399
1400 for (i = 0; i < d + k + 1; i++) {
1401 j = subset[i];
1402 Int_vec_copy(A + j * d, A1 + i * d, d);
1403 }
1404 if (f_v) {
1405 cout << "A1=" << endl;
1406 Int_matrix_print(A1, d + k + 1, d);
1407 }
1408
1409 cnt = 0;
1410 Combi.first_lehmercode(d + 1, lehmercode);
1411 while (TRUE) {
1412 if (f_v) {
1413 cout << "lehmercode: ";
1414 Int_vec_print(cout, lehmercode, d + 1);
1415 cout << endl;
1416 }
1417 Combi.lehmercode_to_permutation(d + 1, lehmercode, perm);
1418 if (f_v) {
1419 cout << "permutation: ";
1420 Int_vec_print(cout, perm, d + 1);
1421 cout << endl;
1422 }
1424 B1, Transform, verbose_level);
1425
1426 for (i = 0; i < d + k + 1; i ++) {
1427 mult_vector_from_the_left(A1 + i * d, Transform, v, d, d);
1428 F->PG_element_rank_modified(v, 1, d, a);
1429 image_set[i] = a;
1430 }
1431 if (f_v) {
1432 cout << "image_set before sorting: ";
1433 Int_vec_print(cout, image_set, d + k + 1);
1434 cout << endl;
1435 }
1436 Sorting.int_vec_heapsort(image_set, d + k + 1);
1437 if (f_v) {
1438 cout << "image_set after sorting: ";
1439 Int_vec_print(cout, image_set, d + k + 1);
1440 cout << endl;
1441 }
1442
1443 if (Sorting.int_vec_compare(image_set, B_set, d + k + 1) == 0) {
1444 cnt++;
1445 }
1446
1447 if (!Combi.next_lehmercode(d + 1, lehmercode)) {
1448 break;
1449 }
1450 }
1451
1452 cout << "subset " << h << " / " << nCk << " we found "
1453 << cnt << " mappings" << endl;
1454 overall_cnt += cnt;
1455 }
1456
1457 FREE_int(perm);
1458 FREE_int(lehmercode);
1459 FREE_int(A1);
1460 FREE_int(B1);
1461 FREE_int(B_set);
1462 FREE_int(image_set);
1463 FREE_int(subset);
1464 FREE_int(v);
1465
1466 nb_maps = overall_cnt;
1467
1468 if (f_v) {
1469 cout << "linear_algebra::map_points_to_points_projectively done"
1470 << endl;
1471 }
1472}
1473
1474int linear_algebra::BallChowdhury_matrix_entry(int *Coord,
1475 int *C, int *U, int k, int sz_U,
1476 int *T, int verbose_level)
1477{
1478 int f_v = (verbose_level >= 1);
1479 int f_vv = (verbose_level >= 2);
1480 int i, d, d1, u, a;
1481
1482 if (f_v) {
1483 cout << "linear_algebra::BallChowdhury_matrix_entry" << endl;
1484 }
1485 d = 1;
1486 for (u = 0; u < sz_U; u++) {
1487 a = U[u];
1488 Int_vec_copy(Coord + a * k, T + (k - 1) * k, k);
1489 for (i = 0; i < k - 1; i++) {
1490 a = C[i];
1491 Int_vec_copy(Coord + a * k, T + i * k, k);
1492 }
1493 if (f_vv) {
1494 cout << "u=" << u << " / " << sz_U << " the matrix is:" << endl;
1495 Int_matrix_print(T, k, k);
1496 }
1497 d1 = matrix_determinant(T, k, 0 /* verbose_level */);
1498 if (f_vv) {
1499 cout << "determinant = " << d1 << endl;
1500 }
1501 d = F->mult(d, d1);
1502 }
1503 if (f_v) {
1504 cout << "linear_algebra::BallChowdhury_matrix_entry d=" << d << endl;
1505 }
1506 return d;
1507}
1508
1509void linear_algebra::cubic_surface_family_24_generators(
1510 int f_with_normalizer,
1511 int f_semilinear,
1512 int *&gens, int &nb_gens, int &data_size,
1513 int &group_order, int verbose_level)
1514{
1515 int f_v = (verbose_level >= 1);
1516 int m_one;
1517
1518 if (f_v) {
1519 cout << "linear_algebra::cubic_surface_family_24_generators" << endl;
1520 }
1521 m_one = F->minus_one();
1522 nb_gens = 3;
1523 data_size = 16;
1524 if (f_semilinear) {
1525 data_size++;
1526 }
1527 if (EVEN(F->q)) {
1528 group_order = 6;
1529 }
1530 else {
1531 group_order = 24;
1532 }
1533 if (f_with_normalizer) {
1534 nb_gens++;
1535 group_order *= F->q - 1;
1536 }
1537 gens = NEW_int(nb_gens * data_size);
1538 Int_vec_zero(gens, nb_gens * data_size);
1539 // this sets the field automorphism index
1540 // to zero if we are semilinear
1541
1542 gens[0 * data_size + 0 * 4 + 0] = 1;
1543 gens[0 * data_size + 1 * 4 + 2] = 1;
1544 gens[0 * data_size + 2 * 4 + 1] = 1;
1545 gens[0 * data_size + 3 * 4 + 3] = 1;
1546 gens[1 * data_size + 0 * 4 + 1] = 1;
1547 gens[1 * data_size + 1 * 4 + 0] = 1;
1548 gens[1 * data_size + 2 * 4 + 2] = 1;
1549 gens[1 * data_size + 3 * 4 + 3] = 1;
1550 gens[2 * data_size + 0 * 4 + 0] = m_one;
1551 gens[2 * data_size + 1 * 4 + 2] = 1;
1552 gens[2 * data_size + 2 * 4 + 1] = 1;
1553 gens[2 * data_size + 3 * 4 + 3] = m_one;
1554 if (f_with_normalizer) {
1555 gens[3 * data_size + 0 * 4 + 0] = 1;
1556 gens[3 * data_size + 1 * 4 + 1] = 1;
1557 gens[3 * data_size + 2 * 4 + 2] = 1;
1558 gens[3 * data_size + 3 * 4 + 3] = F->primitive_root();
1559 }
1560 if (f_v) {
1561 cout << "linear_algebra::cubic_surface_family_24_generators "
1562 "done" << endl;
1563 }
1564}
1565
1566void linear_algebra::cubic_surface_family_G13_generators(
1567 int a,
1568 int *&gens, int &nb_gens, int &data_size,
1569 int &group_order, int verbose_level)
1570{
1571 int f_v = (verbose_level >= 1);
1572 int data[] = {
1573 // A1:
1574 1,0,0,0,
1575 0,1,0,0,
1576 3,2,1,0,
1577 3,0,0,1,
1578
1579 // A2:
1580 1,0,0,0,
1581 0,1,0,0,
1582 1,1,1,0,
1583 1,0,0,1,
1584
1585 // A3:
1586 0,1,0,0,
1587 1,0,0,0,
1588 0,0,1,0,
1589 1,1,1,1,
1590
1591 // A4:
1592 0,1,0,0,
1593 1,0,0,0,
1594 1,1,1,0,
1595 7,6,1,1,
1596
1597 // A5:
1598 2,3,0,0,
1599 3,2,0,0,
1600 0,0,1,0,
1601 3,3,5,1,
1602
1603 // A6:
1604 2,2,1,0,
1605 3,3,1,0,
1606 1,0,1,0,
1607 1,4,2,1,
1608
1609 };
1610
1611 data_size = 16 + 1;
1612 nb_gens = 6;
1613 group_order = 192;
1614
1615 gens = NEW_int(nb_gens * data_size);
1616 Int_vec_zero(gens, nb_gens * data_size);
1617
1618 int h, i, j, c, m, l;
1619 int *v;
1622
1623 m = orbiter_kernel_system::Orbiter->Int_vec->maximum(data, nb_gens * data_size);
1624 l = NT.int_log2(m) + 1;
1625
1626 v = NEW_int(l);
1627
1628
1629 for (h = 0; h < nb_gens; h++) {
1630 for (i = 0; i < 16; i++) {
1631 Int_vec_zero(v, l);
1632 Gg.AG_element_unrank(F->p, v, 1, l, data[h * 16 + i]);
1633 c = 0;
1634 for (j = 0; j < l; j++) {
1635 c = F->mult(c, a);
1636 if (v[l - 1 - j]) {
1637 c = F->add(c, v[l - 1 - j]);
1638 }
1639 }
1640 gens[h * data_size + i] = c;
1641 }
1642 gens[h * data_size + 16] = 0;
1643 }
1644 FREE_int(v);
1645
1646 if (f_v) {
1647 cout << "linear_algebra::cubic_surface_family_G13_generators" << endl;
1648 for (h = 0; h < nb_gens; h++) {
1649 cout << "generator " << h << ":" << endl;
1650 Int_matrix_print(gens + h * data_size, 4, 4);
1651 }
1652 }
1653 if (f_v) {
1654 cout << "linear_algebra::cubic_surface_family_G13_generators done" << endl;
1655 }
1656}
1657
1658void linear_algebra::cubic_surface_family_F13_generators(
1659 int a,
1660 int *&gens, int &nb_gens, int &data_size,
1661 int &group_order, int verbose_level)
1662{
1663 int f_v = (verbose_level >= 1);
1664 // 2 = a
1665 // 3 = a+1
1666 // 4 = a^2
1667 // 5 = a^2+1
1668 // 6 = a^2 + a
1669 // 7 = a^2 + a + 1
1670 // 8 = a^3
1671 // 9 = a^3 + 1
1672 // 10 = a^3 + a
1673 // 11 = a^3 + a + 1
1674 // 12 = a^3 + a^2
1675 // 13 = a^3 + a^2 + 1
1676 // 14 = a^3 + a^2 + a
1677 // 15 = a^3 + a^2 + a + 1 = (a+1)^3
1678 // 16 = a^4
1679 // 17 = a^4 + 1 = (a+1)^4
1680 // 18 = a^4 + a
1681 // 19 = a^4 + a + 1
1682 // 20 = a^4 + a^2 = a^2(a+1)^2
1683 // 23 = (a+1)(a^3+a^2+1)
1684 // 34 = a(a+1)^4
1685 // 45 = (a+1)^3(a^2+a+1)
1686 // 52 = a^2(a^3+a^2+1)
1687 // 54 = a(a+1)^2(a^2+a+1)
1688 // 57 = (a+1)^2(a^3+a^2+1)
1689 // 60 = a^2(a+1)^3
1690 // 63 = (a+1)(a^2+a+1)^2
1691 // 75 = (a+1)^3(a^3+a^2+1)
1692 // 90 = a(a+1)^3(a^2+a+1) = a^6 + a^4 + a^3 + a
1693 // 170 = a(a+1)^6
1694 int data[] = {
1695 // A1:
1696 10,0,0,0,
1697 0,10,0,0,
1698 4,10,10,0,
1699 0,17,0,10,
1700
1701 // A2:
1702 10,0,0,0,
1703 0,10,0,0,
1704 2,0,10,0,
1705 0,15,0,10,
1706
1707 // A3:
1708 10,0,0,0,
1709 2,10,0,0,
1710 0,0,10,0,
1711 0,0,15,10,
1712
1713 // A4:
1714 60,0,0,0,
1715 12,60,0,0,
1716 12,0,60,0,
1717 54,34,34,60,
1718
1719 // A5:
1720 12,0,0,0,
1721 4,12,0,0,
1722 0,0,12,0,
1723 0,0,34,12,
1724
1725 // A6:
1726 10,0,0,0,
1727 4,0,10,0,
1728 0,10,10,0,
1729 10,60,17,10,
1730
1731 };
1732
1733 data_size = 16 + 1;
1734 nb_gens = 6;
1735 group_order = 192;
1736
1737 gens = NEW_int(nb_gens * data_size);
1738 Int_vec_zero(gens, nb_gens * data_size);
1739
1740 int h, i, j, c, m, l;
1741 int *v;
1744
1745 m = orbiter_kernel_system::Orbiter->Int_vec->maximum(data, nb_gens * data_size);
1746 l = NT.int_log2(m) + 1;
1747
1748 v = NEW_int(l);
1749
1750
1751 for (h = 0; h < nb_gens; h++) {
1752 for (i = 0; i < 16; i++) {
1753 Int_vec_zero(v, l);
1754 Gg.AG_element_unrank(F->p, v, 1, l, data[h * 16 + i]);
1755 c = 0;
1756 for (j = 0; j < l; j++) {
1757 c = F->mult(c, a);
1758 if (v[l - 1 - j]) {
1759 c = F->add(c, v[l - 1 - j]);
1760 }
1761 }
1762 gens[h * data_size + i] = c;
1763 }
1764 gens[h * data_size + 16] = 0;
1765 }
1766 FREE_int(v);
1767
1768 if (f_v) {
1769 cout << "linear_algebra::cubic_surface_family_F13_generators" << endl;
1770 for (h = 0; h < nb_gens; h++) {
1771 cout << "generator " << h << ":" << endl;
1772 Int_matrix_print(gens + h * data_size, 4, 4);
1773 }
1774 }
1775 if (f_v) {
1776 cout << "linear_algebra::cubic_surface_family_F13_generators done" << endl;
1777 }
1778}
1779
1780int linear_algebra::is_unit_vector(int *v, int len, int k)
1781{
1782 int i;
1783
1784 for (i = 0; i < len; i++) {
1785 if (i == k) {
1786 if (v[i] != 1) {
1787 return FALSE;
1788 }
1789 }
1790 else {
1791 if (v[i] != 0) {
1792 return FALSE;
1793 }
1794 }
1795 }
1796 return TRUE;
1797}
1798
1799
1800void linear_algebra::make_Fourier_matrices(
1801 int omega, int k, int *N, int **A, int **Av,
1802 int *Omega, int verbose_level)
1803{
1804 int f_v = (verbose_level >= 1);
1805 int h, i, j, om;
1806
1807 if (f_v) {
1808 cout << "linear_algebra::make_Fourier_matrices" << endl;
1809 }
1810
1811 Omega[k] = omega;
1812 for (h = k; h > 0; h--) {
1813 Omega[h - 1] = F->mult(Omega[h], Omega[h]);
1814 }
1815
1816 for (h = k; h >= 0; h--) {
1817 A[h] = NEW_int(N[h] * N[h]);
1818 om = Omega[h];
1819 for (i = 0; i < N[h]; i++) {
1820 for (j = 0; j < N[h]; j++) {
1821 A[h][i * N[h] + j] = F->power(om, (i * j) % N[k]);
1822 }
1823 }
1824 }
1825
1826 for (h = k; h >= 0; h--) {
1827 Av[h] = NEW_int(N[h] * N[h]);
1828 om = F->inverse(Omega[h]);
1829 for (i = 0; i < N[h]; i++) {
1830 for (j = 0; j < N[h]; j++) {
1831 Av[h][i * N[h] + j] = F->power(om, (i * j) % N[k]);
1832 }
1833 }
1834 }
1835
1836 if (f_v) {
1837 for (h = k; h >= 0; h--) {
1838 cout << "A_" << N[h] << ":" << endl;
1839 Int_matrix_print(A[h], N[h], N[h]);
1840 }
1841
1842 for (h = k; h >= 0; h--) {
1843 cout << "Av_" << N[h] << ":" << endl;
1844 Int_matrix_print(Av[h], N[h], N[h]);
1845 }
1846 }
1847 if (f_v) {
1848 cout << "linear_algebra::make_Fourier_matrices done" << endl;
1849 }
1850}
1851
1852
1853
1854}}}
1855
void set_complement(int *subset, int subset_size, int *complement, int &size_complement, int universal_set_size)
a collection of functions related to sorted vectors
void PG_element_rank_modified(int *v, int stride, int len, int &a)
void PG_element_unrank_modified(int *v, int stride, int len, int a)
various functions related to geometries
Definition: geometry.h:721
void AG_element_unrank(int q, int *v, int stride, int len, long int a)
void mult_vector_from_the_left(int *v, int *A, int *vA, int m, int n)
void map_to_standard_frame(int d, int *A, int *Transform, int verbose_level)
int Gauss_int(int *A, int f_special, int f_complete, int *base_cols, int f_P, int *P, int m, int n, int Pn, int verbose_level)
int matrix_determinant(int *A, int n, int verbose_level)
int choose_vector_in_here_but_not_in_here_or_here_column_spaces_coset(int &coset, data_structures::int_matrix *V, data_structures::int_matrix *W1, data_structures::int_matrix *W2, int *v, int verbose_level)
void mult_matrix_matrix(int *A, int *B, int *C, int m, int n, int o, int verbose_level)
void mult_vector_from_the_right(int *A, int *v, int *Av, int m, int n)
int dependency(int d, int *v, int *A, int m, int *rho, int verbose_level)
void Gauss_step(int *v1, int *v2, int len, int idx, int verbose_level)
void reduce_mod_subspace(int k, int len, int *basis, int *base_cols, int *v, int verbose_level)
int RREF_and_kernel(int n, int k, int *A, int verbose_level)
void map_frame_to_frame_with_permutation(int d, int *A, int *perm, int *B, int *Transform, int verbose_level)
int Gauss_simple(int *A, int m, int n, int *base_cols, int verbose_level)
void matrix_inverse(int *A, int *Ainv, int n, int verbose_level)
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define NEW_int(n)
Definition: foundations.h:625
#define Int_vec_print_integer_matrix_width(A, B, C, D, E, F)
Definition: foundations.h:691
#define Int_matrix_print(A, B, C)
Definition: foundations.h:707
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define EVEN(x)
Definition: foundations.h:221
#define Int_vec_copy(A, B, C)
Definition: foundations.h:693
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
orbiter_kernel_system::orbiter_session * Orbiter
global Orbiter session
the orbiter library for the classification of combinatorial objects