Orbiter 2022
Combinatorial Objects
linear_algebra.cpp
Go to the documentation of this file.
1/*
2 * linear_algebra.cpp
3 *
4 * Created on: Jan 10, 2022
5 * Author: betten
6 */
7
8
9
10
11
12#include "foundations.h"
13
14using namespace std;
15
16
17
18namespace orbiter {
19namespace layer1_foundations {
20namespace linear_algebra {
21
22
24{
25 F = NULL;
26}
27
28linear_algebra::~linear_algebra()
29{
30}
31
32void linear_algebra::init(field_theory::finite_field *F, int verbose_level)
33{
34 int f_v = (verbose_level >= 1);
35
36 if (f_v) {
37 cout << "linear_algebra::init" << endl;
38 }
40 if (f_v) {
41 cout << "linear_algebra::init done" << endl;
42 }
43}
44
45void linear_algebra::copy_matrix(int *A, int *B, int ma, int na)
46{
47
48 Int_vec_copy(A, B, ma * na);
49}
50
51void linear_algebra::reverse_matrix(int *A, int *B, int m, int n)
52{
53 int i, j;
54
55 for (i = 0; i < m; i++) {
56 for (j = 0; j < n; j++) {
57 B[i * n + j] = A[(m - 1 - i) * n + (n - 1 - j)];
58 }
59 }
60}
61
62void linear_algebra::identity_matrix(int *A, int n)
63{
64 int i, j;
65
66 for (i = 0; i < n; i++) {
67 for (j = 0; j < n; j++) {
68 if (i == j) {
69 A[i * n + j] = 1;
70 }
71 else {
72 A[i * n + j] = 0;
73 }
74 }
75 }
76}
77
78int linear_algebra::is_identity_matrix(int *A, int n)
79{
80 int i, j;
81
82 for (i = 0; i < n; i++) {
83 for (j = 0; j < n; j++) {
84 if (i == j) {
85 if (A[i * n + j] != 1) {
86 return FALSE;
87 }
88 }
89 else {
90 if (A[i * n + j]) {
91 return FALSE;
92 }
93 }
94 }
95 }
96 return TRUE;
97}
98
99int linear_algebra::is_diagonal_matrix(int *A, int n)
100{
102
103 return Algebra.is_diagonal_matrix(A, n);
104}
105
106int linear_algebra::is_scalar_multiple_of_identity_matrix(
107 int *A, int n, int &scalar)
108{
109 int i;
110
111 if (!is_diagonal_matrix(A, n)) {
112 return FALSE;
113 }
114 scalar = A[0 * n + 0];
115 for (i = 1; i < n; i++) {
116 if (A[i * n + i] != scalar) {
117 return FALSE;
118 }
119 }
120 return TRUE;
121}
122
123void linear_algebra::diagonal_matrix(int *A, int n, int alpha)
124{
125 int i, j;
126
127 for (i = 0; i < n; i++) {
128 for (j = 0; j < n; j++) {
129 if (i == j) {
130 A[i * n + j] = alpha;
131 }
132 else {
133 A[i * n + j] = 0;
134 }
135 }
136 }
137}
138
139void linear_algebra::matrix_minor(int f_semilinear,
140 int *A, int *B, int n, int f, int l)
141// initializes B as the l x l minor of A
142// (which is n x n) starting from row f.
143{
144 int i, j;
145
146 if (f + l > n) {
147 cout << "linear_algebra::matrix_minor f + l > n" << endl;
148 exit(1);
149 }
150 for (i = 0; i < l; i++) {
151 for (j = 0; j < l; j++) {
152 B[i * l + j] = A[(f + i) * n + (f + j)];
153 }
154 }
155 if (f_semilinear) {
156 B[l * l] = A[n * n];
157 }
158}
159
160void linear_algebra::mult_vector_from_the_left(int *v,
161 int *A, int *vA, int m, int n)
162// v[m], A[m][n], vA[n]
163{
165 v, A, vA,
166 1, m, n, 0 /*verbose_level */);
167}
168
169void linear_algebra::mult_vector_from_the_right(int *A,
170 int *v, int *Av, int m, int n)
171// A[m][n], v[n], Av[m]
172{
174 A, v, Av,
175 m, n, 1, 0 /*verbose_level */);
176}
177
178void linear_algebra::mult_matrix_matrix(
179 int *A, int *B, int *C,
180 int m, int n, int o, int verbose_level)
181// matrix multiplication C := A * B,
182// where A is m x n and B is n x o, so that C is m by o
183{
184 int f_v = (verbose_level >= 1);
185 int f_vv = (verbose_level >= 2);
186 int i, j, k, a, b;
187
188 if (f_v) {
189 cout << "linear_algebra::mult_matrix_matrix" << endl;
190 }
191 if (f_vv) {
192 cout << "A=" << endl;
193 Int_matrix_print(A, m, n);
194 cout << "B=" << endl;
195 Int_matrix_print(B, n, o);
196 }
198 for (i = 0; i < m; i++) {
199 for (j = 0; j < o; j++) {
200 a = 0;
201 for (k = 0; k < n; k++) {
202 b = F->mult(A[i * n + k], B[k * o + j]);
203 a = F->add(a, b);
204 }
205 C[i * o + j] = a;
206 }
207 }
208 if (f_v) {
209 cout << "linear_algebra::mult_matrix_matrix done" << endl;
210 }
211}
212
213void linear_algebra::semilinear_matrix_mult(int *A, int *B, int *AB, int n)
214// (A,f1) * (B,f2) = (A*B^{\varphi^{-f1}},f1+f2)
215{
216 int i, j, k, a, b, ab, c, f1, f2, f1inv;
217 int *B2;
219
220 B2 = NEW_int(n * n);
221 f1 = A[n * n];
222 f2 = B[n * n];
223 f1inv = NT.mod(-f1, F->e);
224 Int_vec_copy(B, B2, n * n);
225 vector_frobenius_power_in_place(B2, n * n, f1inv);
226 for (i = 0; i < n; i++) {
227 for (j = 0; j < n; j++) {
228 c = 0;
229 for (k = 0; k < n; k++) {
230 //cout << "i=" << i << "j=" << j << "k=" << k;
231 a = A[i * n + k];
232 //cout << "a=A[" << i << "][" << k << "]=" << a;
233 b = B2[k * n + j];
234 ab = F->mult(a, b);
235 c = F->add(c, ab);
236 //cout << "b=" << b << "ab=" << ab << "c=" << c << endl;
237 }
238 AB[i * n + j] = c;
239 }
240 }
241 AB[n * n] = NT.mod(f1 + f2, F->e);
242 //vector_frobenius_power_in_place(B, n * n, f1);
243 FREE_int(B2);
244}
245
246void linear_algebra::semilinear_matrix_mult_memory_given(
247 int *A, int *B, int *AB, int *tmp_B, int n, int verbose_level)
248// (A,f1) * (B,f2) = (A*B^{\varphi^{-f1}},f1+f2)
249{
250 int f_v = (verbose_level >= 1);
251 int f_vv = (verbose_level >= 2);
252 int i, j, k, a, b, ab, c, f1, f2, f1inv;
253 int *B2 = tmp_B;
255
256 if (f_v) {
257 cout << "linear_algebra::semilinear_matrix_mult_memory_given" << endl;
258 }
259 //B2 = NEW_int(n * n);
260 f1 = A[n * n];
261 f2 = B[n * n];
262 f1inv = NT.mod(-f1, F->e);
263 if (f_vv) {
264 cout << "linear_algebra::semilinear_matrix_mult_memory_given f1=" << f1 << endl;
265 cout << "linear_algebra::semilinear_matrix_mult_memory_given f2=" << f2 << endl;
266 cout << "linear_algebra::semilinear_matrix_mult_memory_given f1inv=" << f1inv << endl;
267 }
268
269 Int_vec_copy(B, B2, n * n);
270 vector_frobenius_power_in_place(B2, n * n, f1inv);
271 for (i = 0; i < n; i++) {
272 for (j = 0; j < n; j++) {
273 c = 0;
274 for (k = 0; k < n; k++) {
275 //cout << "i=" << i << "j=" << j << "k=" << k;
276 a = A[i * n + k];
277 //cout << "a=A[" << i << "][" << k << "]=" << a;
278 b = B2[k * n + j];
279 ab = F->mult(a, b);
280 c = F->add(c, ab);
281 //cout << "b=" << b << "ab=" << ab << "c=" << c << endl;
282 }
283 AB[i * n + j] = c;
284 }
285 }
286 AB[n * n] = NT.mod(f1 + f2, F->e);
287 //vector_frobenius_power_in_place(B, n * n, f1);
288 //FREE_int(B2);
289 if (f_v) {
290 cout << "linear_algebra::semilinear_matrix_mult_memory_given done" << endl;
291 }
292}
293
294void linear_algebra::matrix_mult_affine(int *A, int *B, int *AB,
295 int n, int verbose_level)
296{
297 int f_v = (verbose_level >= 1);
298 int f_vv = (verbose_level >= 2);
299 int *b1, *b2, *b3;
300 int *A1, *A2, *A3;
301
302 if (f_v) {
303 cout << "linear_algebra::matrix_mult_affine" << endl;
304 }
305 A1 = A;
306 A2 = B;
307 A3 = AB;
308 b1 = A + n * n;
309 b2 = B + n * n;
310 b3 = AB + n * n;
311 if (f_vv) {
312 cout << "A1=" << endl;
313 Int_matrix_print(A1, n, n);
314 cout << "b1=" << endl;
315 Int_matrix_print(b1, 1, n);
316 cout << "A2=" << endl;
317 Int_matrix_print(A2, n, n);
318 cout << "b2=" << endl;
319 Int_matrix_print(b2, 1, n);
320 }
321
322 mult_matrix_matrix(A1, A2, A3, n, n, n, 0 /* verbose_level */);
323 if (f_vv) {
324 cout << "A3=" << endl;
325 Int_matrix_print(A3, n, n);
326 }
327 mult_matrix_matrix(b1, A2, b3, 1, n, n, 0 /* verbose_level */);
328 if (f_vv) {
329 cout << "b3=" << endl;
330 Int_matrix_print(b3, 1, n);
331 }
332 add_vector(b3, b2, b3, n);
333 if (f_vv) {
334 cout << "b3 after adding b2=" << endl;
335 Int_matrix_print(b3, 1, n);
336 }
337
338 if (f_v) {
339 cout << "linear_algebra::matrix_mult_affine done" << endl;
340 }
341}
342
343void linear_algebra::semilinear_matrix_mult_affine(
344 int *A, int *B, int *AB, int n)
345{
346 int f1, f2, f12, f1inv;
347 int *b1, *b2, *b3;
348 int *A1, *A2, *A3;
349 int *T;
351
352 T = NEW_int(n * n);
353 A1 = A;
354 A2 = B;
355 A3 = AB;
356 b1 = A + n * n;
357 b2 = B + n * n;
358 b3 = AB + n * n;
359
360 f1 = A[n * n + n];
361 f2 = B[n * n + n];
362 f12 = NT.mod(f1 + f2, F->e);
363 f1inv = NT.mod(F->e - f1, F->e);
364
365 Int_vec_copy(A2, T, n * n);
366 vector_frobenius_power_in_place(T, n * n, f1inv);
367 mult_matrix_matrix(A1, T, A3, n, n, n, 0 /* verbose_level */);
368 //vector_frobenius_power_in_place(A2, n * n, f1);
369
370 mult_matrix_matrix(b1, A2, b3, 1, n, n, 0 /* verbose_level */);
372 add_vector(b3, b2, b3, n);
373
374 AB[n * n + n] = f12;
375 FREE_int(T);
376}
377
378int linear_algebra::matrix_determinant(int *A, int n, int verbose_level)
379{
380 int f_v = (verbose_level >= 1);
381 int f_vv = (verbose_level >= 2);
382 int i, j, eps = 1, a, det, det1, det2;
383 int *Tmp, *Tmp1;
384
385 if (f_v) {
386 cout << "linear_algebra::matrix_determinant" << endl;
387 }
388 if (n == 1) {
389 return A[0];
390 }
391 if (f_vv) {
392 cout << "linear_algebra::matrix_determinant determinant of " << endl;
393 Int_vec_print_integer_matrix_width(cout, A, n, n, n, 2);
394 }
395 Tmp = NEW_int(n * n);
396 Tmp1 = NEW_int(n * n);
397 Int_vec_copy(A, Tmp, n * n);
398
399 // search for nonzero element in the first column:
400 for (i = 0; i < n; i++) {
401 if (Tmp[i * n + 0]) {
402 break;
403 }
404 }
405 if (i == n) {
406 FREE_int(Tmp);
407 FREE_int(Tmp1);
408 return 0;
409 }
410
411 // possibly permute the row with the nonzero element up front:
412 if (i != 0) {
413 for (j = 0; j < n; j++) {
414 a = Tmp[0 * n + j];
415 Tmp[0 * n + j] = Tmp[i * n + j];
416 Tmp[i * n + j] = a;
417 }
418 if (ODD(i)) {
419 eps *= -1;
420 }
421 }
422
423 // pick the pivot element:
424 det = Tmp[0 * n + 0];
425
426 // eliminate the first column:
427 for (i = 1; i < n; i++) {
428 Gauss_step(Tmp, Tmp + i * n, n, 0, 0 /* verbose_level */);
429 }
430
431
432 if (eps < 0) {
433 det = F->negate(det);
434 }
435 if (f_vv) {
436 cout << "linear_algebra::matrix_determinant after Gauss " << endl;
437 Int_vec_print_integer_matrix_width(cout, Tmp, n, n, n, 2);
438 cout << "linear_algebra::matrix_determinant det= " << det << endl;
439 }
440
441 // delete the first row and column and form the matrix
442 // Tmp1 of size (n - 1) x (n - 1):
443 for (i = 1; i < n; i++) {
444 for (j = 1; j < n; j++) {
445 Tmp1[(i - 1) * (n - 1) + j - 1] = Tmp[i * n + j];
446 }
447 }
448 if (f_vv) {
449 cout << "linear_algebra::matrix_determinant computing determinant of " << endl;
450 Int_vec_print_integer_matrix_width(cout, Tmp1, n - 1, n - 1, n - 1, 2);
451 }
452 det1 = matrix_determinant(Tmp1, n - 1, 0/*verbose_level*/);
453 if (f_vv) {
454 cout << "as " << det1 << endl;
455 }
456
457 // multiply the pivot element:
458 det2 = F->mult(det, det1);
459
460 FREE_int(Tmp);
461 FREE_int(Tmp1);
462 if (f_vv) {
463 cout << "linear_algebra::matrix_determinant determinant is " << det2 << endl;
464 }
465
466 return det2;
467#if 0
468 int *Tmp, *Tmp_basecols, *P, *perm;
469 int rk, det, i, j, eps;
470
471 Tmp = NEW_int(n * n + 1);
472 Tmp_basecols = NEW_int(n);
473 P = NEW_int(n * n);
474 perm = NEW_int(n);
475
476 for (i = 0; i < n; i++) {
477 for (j = 0; j < n; j++) {
478 if (i == j)
479 P[i * n + j] = 1;
480 else
481 P[i * n + j] = 0;
482 }
483 }
484
485 copy_matrix(A, Tmp, n, n);
486 cout << "before Gauss:" << endl;
487 print_integer_matrix_width(cout, Tmp, n, n, n, 2);
488 rk = Gauss_int(Tmp,
489 TRUE /* f_special */,
490 FALSE /*f_complete */, Tmp_basecols,
491 TRUE /* f_P */, P, n, n, n, verbose_level - 2);
492 cout << "after Gauss:" << endl;
493 print_integer_matrix_width(cout, Tmp, n, n, n, 2);
494 cout << "P:" << endl;
495 print_integer_matrix_width(cout, P, n, n, n, 2);
496 if (rk < n) {
497 det = 0;
498 }
499 else {
500 for (i = 0; i < n; i++) {
501 for (j = 0; j < n; j++) {
502 if (P[i * n + j]) {
503 perm[i] = j;
504 break;
505 }
506 }
507 }
508 cout << "permutation : ";
509 perm_print_list(cout, perm, n);
510 perm_print(cout, perm, n);
511 cout << endl;
512 eps = perm_signum(perm, n);
513
514 det = 1;
515 for (i = 0; i < n; i++) {
516 det = mult(det, Tmp[i * n + i]);
517 }
518 if (eps < 0) {
519 det = mult(det, negate(1));
520 }
521 }
522 cout << "det=" << det << endl;
523
524 FREE_int(Tmp);
525 FREE_int(Tmp_basecols);
526 FREE_int(P);
527 FREE_int(perm);
528 return det;
529#endif
530 if (f_v) {
531 cout << "linear_algebra::matrix_determinant done" << endl;
532 }
533}
534
535void linear_algebra::matrix_inverse(int *A, int *Ainv, int n,
536 int verbose_level)
537{
538 int f_v = (verbose_level >= 1);
539 int *Tmp, *Tmp_basecols;
540
541 if (f_v) {
542 cout << "linear_algebra::matrix_inverse" << endl;
543 }
544 Tmp = NEW_int(n * n + 1);
545 Tmp_basecols = NEW_int(n);
546
547 matrix_invert(A, Tmp, Tmp_basecols, Ainv, n, verbose_level);
548
549 FREE_int(Tmp);
550 FREE_int(Tmp_basecols);
551 if (f_v) {
552 cout << "linear_algebra::matrix_inverse done" << endl;
553 }
554}
555
556void linear_algebra::matrix_invert(int *A, int *Tmp, int *Tmp_basecols,
557 int *Ainv, int n, int verbose_level)
558// Tmp[n * n + 1]
559// Tmp_basecols[n]
560{
561 int rk;
562 int f_v = (verbose_level >= 1);
563 int f_vv = (verbose_level >= 2);
564
565 if (f_v) {
566 cout << "linear_algebra::matrix_invert" << endl;
567 }
568 if (f_vv) {
569 Int_vec_print_integer_matrix_width(cout, A, n, n, n, F->log10_of_q + 1);
570 }
571 copy_matrix(A, Tmp, n, n);
572 identity_matrix(Ainv, n);
573 rk = Gauss_int(Tmp,
574 FALSE /* f_special */, TRUE /*f_complete */, Tmp_basecols,
575 TRUE /* f_P */, Ainv, n, n, n, verbose_level - 2);
576 if (rk < n) {
577 cout << "linear_algebra::matrix_invert not invertible" << endl;
578 cout << "input matrix:" << endl;
579 Int_vec_print_integer_matrix_width(cout, A, n, n, n, F->log10_of_q + 1);
580 cout << "Tmp matrix:" << endl;
581 Int_vec_print_integer_matrix_width(cout, Tmp, n, n, n, F->log10_of_q + 1);
582 cout << "rk=" << rk << endl;
583 exit(1);
584 }
585 if (f_vv) {
586 cout << "the inverse is" << endl;
587 Int_vec_print_integer_matrix_width(cout, Ainv, n, n, n, F->log10_of_q + 1);
588 }
589 if (f_v) {
590 cout << "linear_algebra::matrix_invert done" << endl;
591 }
592}
593
594void linear_algebra::semilinear_matrix_invert(int *A,
595 int *Tmp, int *Tmp_basecols, int *Ainv, int n,
596 int verbose_level)
597// Tmp[n * n + 1]
598// Tmp_basecols[n]
599{
600 int f, finv;
601 int f_v = (verbose_level >= 1);
602 int f_vv = (verbose_level >= 2);
604
605 if (f_v) {
606 cout << "linear_algebra::semilinear_matrix_invert" << endl;
607 }
608 if (f_vv) {
609 Int_vec_print_integer_matrix_width(cout, A, n, n, n, F->log10_of_q + 1);
610 cout << "frobenius: " << A[n * n] << endl;
611 }
612 matrix_invert(A, Tmp, Tmp_basecols, Ainv, n, verbose_level - 1);
613 f = A[n * n];
614 vector_frobenius_power_in_place(Ainv, n * n, f);
615 finv = NT.mod(-f, F->e);
616 Ainv[n * n] = finv;
617 if (f_vv) {
618 cout << "the inverse is" << endl;
619 Int_vec_print_integer_matrix_width(cout, Ainv, n, n, n, F->log10_of_q + 1);
620 cout << "frobenius: " << Ainv[n * n] << endl;
621 }
622 if (f_v) {
623 cout << "linear_algebra::semilinear_matrix_invert done" << endl;
624 }
625}
626
627void linear_algebra::semilinear_matrix_invert_affine(int *A,
628 int *Tmp, int *Tmp_basecols, int *Ainv, int n,
629 int verbose_level)
630// Tmp[n * n + 1]
631// Tmp_basecols[n]
632{
633 int f, finv;
634 int *b1, *b2;
635 int f_v = (verbose_level >= 1);
636 int f_vv = (verbose_level >= 2);
638
639 if (f_v) {
640 cout << "linear_algebra::semilinear_matrix_invert_affine" << endl;
641 }
642 if (f_vv) {
643 Int_vec_print_integer_matrix_width(cout, A, n, n, n, F->log10_of_q + 1);
644 cout << "b: ";
645 Int_vec_print(cout, A + n * n, n);
646 cout << " frobenius: " << A[n * n + n] << endl;
647 }
648 b1 = A + n * n;
649 b2 = Ainv + n * n;
650 matrix_invert(A, Tmp, Tmp_basecols, Ainv, n, verbose_level - 1);
651 f = A[n * n + n];
652 finv = NT.mod(-f, F->e);
653 vector_frobenius_power_in_place(Ainv, n * n, f);
654
655 mult_matrix_matrix(b1, Ainv, b2, 1, n, n, 0 /* verbose_level */);
656
658
660
661 Ainv[n * n + n] = finv;
662 if (f_vv) {
663 cout << "the inverse is" << endl;
664 Int_vec_print_integer_matrix_width(cout, Ainv, n, n, n, F->log10_of_q + 1);
665 cout << "b: ";
666 Int_vec_print(cout, Ainv + n * n, n);
667 cout << " frobenius: " << Ainv[n * n + n] << endl;
668 }
669 if (f_v) {
670 cout << "linear_algebra::semilinear_matrix_invert_affine done" << endl;
671 }
672}
673
674
675void linear_algebra::matrix_invert_affine(int *A,
676 int *Tmp, int *Tmp_basecols, int *Ainv, int n,
677 int verbose_level)
678// Tmp[n * n + 1]
679// Tmp_basecols[n]
680{
681 int *b1, *b2;
682 int f_v = (verbose_level >= 1);
683 int f_vv = (verbose_level >= 2);
684
685 if (f_v) {
686 cout << "linear_algebra::matrix_invert_affine" << endl;
687 }
688 if (f_vv) {
689 Int_vec_print_integer_matrix_width(cout, A, n, n, n, F->log10_of_q + 1);
690 cout << "b: ";
691 Int_vec_print(cout, A + n * n, n);
692 cout << endl;
693 }
694 b1 = A + n * n;
695 b2 = Ainv + n * n;
696 matrix_invert(A, Tmp, Tmp_basecols, Ainv, n, verbose_level - 1);
697
698 mult_matrix_matrix(b1, Ainv, b2, 1, n, n, 0 /* verbose_level */);
699
701
702 if (f_vv) {
703 cout << "the inverse is" << endl;
704 Int_vec_print_integer_matrix_width(cout, Ainv, n, n, n, F->log10_of_q + 1);
705 cout << "b: ";
706 Int_vec_print(cout, Ainv + n * n, n);
707 cout << endl;
708 }
709 if (f_v) {
710 cout << "linear_algebra::matrix_invert_affine done" << endl;
711 }
712}
713
714
715void linear_algebra::projective_action_from_the_right(int f_semilinear,
716 int *v, int *A, int *vA, int n,
717 int verbose_level)
718// vA = (v * A)^{p^f} if f_semilinear
719// (where f = A[n * n]), vA = v * A otherwise
720{
721 int f_v = (verbose_level >= 1);
722
723 if (f_v) {
724 cout << "linear_algebra::projective_action_from_the_right" << endl;
725 }
726 if (f_semilinear) {
728 }
729 else {
730 mult_vector_from_the_left(v, A, vA, n, n);
731 }
732 if (f_v) {
733 cout << "linear_algebra::projective_action_from_the_right done" << endl;
734 }
735}
736
737void linear_algebra::general_linear_action_from_the_right(int f_semilinear,
738 int *v, int *A, int *vA, int n,
739 int verbose_level)
740{
741 int f_v = (verbose_level >= 1);
742
743 if (f_v) {
744 cout << "linear_algebra::general_linear_action_from_the_right"
745 << endl;
746 }
747 if (f_semilinear) {
749 }
750 else {
751 mult_vector_from_the_left(v, A, vA, n, n);
752 }
753 if (f_v) {
754 cout << "linear_algebra::general_linear_action_from_the_right done"
755 << endl;
756 }
757}
758
759
760void linear_algebra::semilinear_action_from_the_right(
761 int *v, int *A, int *vA, int n)
762// vA = (v * A)^{p^f} (where f = A[n * n])
763{
764 int f;
765
766 f = A[n * n];
767 mult_vector_from_the_left(v, A, vA, n, n);
769}
770
771void linear_algebra::semilinear_action_from_the_left(
772 int *A, int *v, int *Av, int n)
773// Av = A * v^{p^f}
774{
775 int f;
776
777 f = A[n * n];
778 mult_vector_from_the_right(A, v, Av, n, n);
780}
781
782void linear_algebra::affine_action_from_the_right(
783 int f_semilinear, int *v, int *A, int *vA, int n)
784// vA = (v * A)^{p^f} + b
785{
786 mult_vector_from_the_left(v, A, vA, n, n);
787 if (f_semilinear) {
788 int f;
789
790 f = A[n * n + n];
792 }
793 add_vector(vA, A + n * n, vA, n);
794}
795
796void linear_algebra::zero_vector(int *A, int m)
797{
798 int i;
799
800 for (i = 0; i < m; i++) {
801 A[i] = 0;
802 }
803}
804
805void linear_algebra::all_one_vector(int *A, int m)
806{
807 int i;
808
809 for (i = 0; i < m; i++) {
810 A[i] = 1;
811 }
812}
813
814void linear_algebra::support(int *A, int m, int *&support, int &size)
815{
816 int i;
817
818 support = NEW_int(m);
819 size = 0;
820 for (i = 0; i < m; i++) {
821 if (A[i]) {
822 support[size++] = i;
823 }
824 }
825}
826
827void linear_algebra::characteristic_vector(int *A, int m, int *set, int size)
828{
829 int i;
830
831 zero_vector(A, m);
832 for (i = 0; i < size; i++) {
833 A[set[i]] = 1;
834 }
835}
836
837int linear_algebra::is_zero_vector(int *A, int m)
838{
839 int i;
840
841 for (i = 0; i < m; i++) {
842 if (A[i]) {
843 return FALSE;
844 }
845 }
846 return TRUE;
847}
848
849void linear_algebra::add_vector(int *A, int *B, int *C, int m)
850{
851 int i;
852
853 for (i = 0; i < m; i++) {
854 C[i] = F->add(A[i], B[i]);
855 }
856}
857
858void linear_algebra::linear_combination_of_vectors(
859 int a, int *A, int b, int *B, int *C, int len)
860{
861 int i;
862
863 for (i = 0; i < len; i++) {
864 C[i] = F->add(F->mult(a, A[i]), F->mult(b, B[i]));
865 }
866}
867
868void linear_algebra::linear_combination_of_three_vectors(
869 int a, int *A, int b, int *B, int c, int *C, int *D, int len)
870{
871 int i;
872
873 for (i = 0; i < len; i++) {
874 D[i] = F->add3(F->mult(a, A[i]), F->mult(b, B[i]), F->mult(c, C[i]));
875 }
876}
877
878void linear_algebra::negate_vector(int *A, int *B, int m)
879{
880 int i;
881
882 for (i = 0; i < m; i++) {
883 B[i] = F->negate(A[i]);
884 }
885}
886
887void linear_algebra::negate_vector_in_place(int *A, int m)
888{
889 int i;
890
891 for (i = 0; i < m; i++) {
892 A[i] = F->negate(A[i]);
893 }
894}
895
896void linear_algebra::scalar_multiply_vector_in_place(int c, int *A, int m)
897{
898 int i;
899
900 for (i = 0; i < m; i++) {
901 A[i] = F->mult(c, A[i]);
902 }
903}
904
905void linear_algebra::vector_frobenius_power_in_place(int *A, int m, int f)
906{
907 int i;
908
909 for (i = 0; i < m; i++) {
910 A[i] = F->frobenius_power(A[i], f);
911 }
912}
913
914int linear_algebra::dot_product(int len, int *v, int *w)
915{
916 int i, a = 0, b;
917
918 for (i = 0; i < len; i++) {
919 b = F->mult(v[i], w[i]);
920 a = F->add(a, b);
921 }
922 return a;
923}
924
925void linear_algebra::transpose_matrix(int *A, int *At, int ma, int na)
926{
927 int i, j;
928
929 for (i = 0; i < ma; i++) {
930 for (j = 0; j < na; j++) {
931 At[j * ma + i] = A[i * na + j];
932 }
933 }
934}
935
936void linear_algebra::transpose_matrix_in_place(int *A, int m)
937{
938 int i, j, a;
939
940 for (i = 0; i < m; i++) {
941 for (j = i + 1; j < m; j++) {
942 a = A[i * m + j];
943 A[i * m + j] = A[j * m + i];
944 A[j * m + i] = a;
945 }
946 }
947}
948
949void linear_algebra::invert_matrix(int *A, int *A_inv, int n, int verbose_level)
950{
951 int f_v = (verbose_level >= 1);
952 int *A_tmp;
953 int *basecols;
954
955 if (f_v) {
956 cout << "linear_algebra::invert_matrix" << endl;
957 }
958 A_tmp = NEW_int(n * n);
959 basecols = NEW_int(n);
960
961
962 invert_matrix_memory_given(A, A_inv, n, A_tmp, basecols, verbose_level);
963
964 FREE_int(A_tmp);
965 FREE_int(basecols);
966 if (f_v) {
967 cout << "linear_algebra::invert_matrix done" << endl;
968 }
969}
970
971void linear_algebra::invert_matrix_memory_given(int *A, int *A_inv, int n,
972 int *tmp_A, int *tmp_basecols, int verbose_level)
973{
974 int f_v = (verbose_level >= 1);
975 int i, j, a, rk;
976 int *A_tmp;
977 int *base_cols;
978
979 if (f_v) {
980 cout << "linear_algebra::invert_matrix_memory_given" << endl;
981 }
982 A_tmp = tmp_A;
983 base_cols = tmp_basecols;
984
985
986 for (i = 0; i < n; i++) {
987 for (j = 0; j < n; j++) {
988 if (i == j) {
989 a = 1;
990 }
991 else {
992 a = 0;
993 }
994 A_inv[i * n + j] = a;
995 }
996 }
997 Int_vec_copy(A, A_tmp, n * n);
998
999 rk = Gauss_int(A_tmp,
1000 FALSE /* f_special */,
1001 TRUE /*f_complete */, base_cols,
1002 TRUE /* f_P */, A_inv, n, n, n, 0 /* verbose_level */);
1003 if (rk < n) {
1004 cout << "linear_algebra::invert_matrix "
1005 "matrix is not invertible, the rank is " << rk << endl;
1006 exit(1);
1007 }
1008
1009 if (f_v) {
1010 cout << "linear_algebra::invert_matrix_memory_given done" << endl;
1011 }
1012}
1013
1014void linear_algebra::transform_form_matrix(int *A,
1015 int *Gram, int *new_Gram, int d, int verbose_level)
1016// computes new_Gram = A * Gram * A^\top
1017{
1018 int f_v = (verbose_level >= 1);
1019 int *Tmp1, *Tmp2;
1020
1021 if (f_v) {
1022 cout << "linear_algebra::transform_form_matrix" << endl;
1023 }
1024 Tmp1 = NEW_int(d * d);
1025 Tmp2 = NEW_int(d * d);
1026
1027 transpose_matrix(A, Tmp1, d, d);
1028 mult_matrix_matrix(A, Gram, Tmp2, d, d, d, 0 /* verbose_level */);
1029 mult_matrix_matrix(Tmp2, Tmp1, new_Gram, d, d, d, 0 /* verbose_level */);
1030
1031 FREE_int(Tmp1);
1032 FREE_int(Tmp2);
1033 if (f_v) {
1034 cout << "linear_algebra::transform_form_matrix done" << endl;
1035 }
1036}
1037
1038int linear_algebra::rank_of_matrix(int *A, int m, int verbose_level)
1039{
1040 int f_v = (verbose_level >= 1);
1041 int *B, *base_cols, rk;
1042
1043 if (f_v) {
1044 cout << "linear_algebra::rank_of_matrix" << endl;
1045 }
1046 B = NEW_int(m * m);
1047 base_cols = NEW_int(m);
1048
1050 m, B, base_cols, verbose_level);
1051
1052 FREE_int(base_cols);
1053 FREE_int(B);
1054 if (f_v) {
1055 cout << "linear_algebra::rank_of_matrix done" << endl;
1056 }
1057 return rk;
1058}
1059
1060int linear_algebra::rank_of_matrix_memory_given(int *A,
1061 int m, int *B, int *base_cols, int verbose_level)
1062{
1063 int f_v = (verbose_level >= 1);
1064 int f_vv = (verbose_level >= 2);
1065 int rk;
1066
1067 if (f_v) {
1068 cout << "linear_algebra::rank_of_matrix_memory_given" << endl;
1069 }
1070 Int_vec_copy(A, B, m * m);
1071 rk = Gauss_int(B, FALSE, FALSE, base_cols, FALSE,
1072 NULL, m, m, m, 0 /* verbose_level */);
1073 if (FALSE) {
1074 cout << "the matrix ";
1075 if (f_vv) {
1076 cout << endl;
1077 Int_vec_print_integer_matrix_width(cout, A, m, m, m, 2);
1078 }
1079 cout << "has rank " << rk << endl;
1080 }
1081 if (f_v) {
1082 cout << "linear_algebra::rank_of_matrix_memory_given done" << endl;
1083 }
1084 return rk;
1085}
1086
1087int linear_algebra::rank_of_rectangular_matrix(int *A,
1088 int m, int n, int verbose_level)
1089{
1090 int f_v = (verbose_level >= 1);
1091 int *B, *base_cols;
1092 int rk;
1093
1094 if (f_v) {
1095 cout << "linear_algebra::rank_of_rectangular_matrix" << endl;
1096 }
1097 B = NEW_int(m * n);
1098 base_cols = NEW_int(n);
1099
1101 A, m, n, B, base_cols, verbose_level);
1102
1103 FREE_int(base_cols);
1104 FREE_int(B);
1105 if (f_v) {
1106 cout << "linear_algebra::rank_of_rectangular_matrix done" << endl;
1107 }
1108 return rk;
1109}
1110
1111int linear_algebra::rank_of_rectangular_matrix_memory_given(
1112 int *A, int m, int n, int *B, int *base_cols,
1113 int verbose_level)
1114{
1115 int f_v = (verbose_level >= 1);
1116 int f_vv = (verbose_level >= 2);
1117 int rk;
1118
1119 if (f_v) {
1120 cout << "linear_algebra::rank_of_rectangular_matrix_memory_given" << endl;
1121 }
1122 //B = NEW_int(m * n);
1123 //base_cols = NEW_int(n);
1124 Int_vec_copy(A, B, m * n);
1125 rk = Gauss_int(B, FALSE, FALSE, base_cols, FALSE,
1126 NULL, m, n, n, 0 /* verbose_level */);
1127
1128 if (FALSE) {
1129 cout << "the matrix ";
1130 if (f_vv) {
1131 cout << endl;
1132 Int_vec_print_integer_matrix_width(cout, A, m, n, n, 2);
1133 }
1134 cout << "has rank " << rk << endl;
1135 }
1136
1137 if (f_v) {
1138 cout << "linear_algebra::rank_of_rectangular_matrix_memory_given done" << endl;
1139 }
1140 return rk;
1141}
1142
1143int linear_algebra::rank_and_basecols(int *A, int m,
1144 int *base_cols, int verbose_level)
1145{
1146 int f_v = (verbose_level >= 1);
1147 int f_vv = (verbose_level >= 2);
1148 int *B, rk;
1149
1150 if (f_v) {
1151 cout << "linear_algebra::rank_and_basecols" << endl;
1152 }
1153 B = NEW_int(m * m);
1154 Int_vec_copy(A, B, m * m);
1155 rk = Gauss_int(B, FALSE, FALSE, base_cols, FALSE,
1156 NULL, m, m, m, 0 /* verbose_level */);
1157 if (FALSE) {
1158 cout << "the matrix ";
1159 if (f_vv) {
1160 cout << endl;
1161 Int_vec_print_integer_matrix_width(cout, A, m, m, m, 2);
1162 }
1163 cout << "has rank " << rk << endl;
1164 }
1165 FREE_int(B);
1166 if (f_v) {
1167 cout << "linear_algebra::rank_and_basecols done" << endl;
1168 }
1169 return rk;
1170}
1171
1172void linear_algebra::Gauss_step(int *v1, int *v2,
1173 int len, int idx, int verbose_level)
1174// afterwards: v2[idx] = 0 and v1,v2 span the same space as before
1175// v1 is not changed if v1[idx] is nonzero
1176{
1177 int i, a;
1178 int f_v = (verbose_level >= 1);
1179 int f_vv = FALSE;//(verbose_level >= 2);
1180
1181 if (f_v) {
1182 cout << "linear_algebra::Gauss_step" << endl;
1183 }
1184 if (f_vv) {
1185 cout << "before:" << endl;
1186 Int_vec_print(cout, v1, len);
1187 cout << endl;
1188 Int_vec_print(cout, v2, len);
1189 cout << endl;
1190 cout << "pivot column " << idx << endl;
1191 }
1192 if (v2[idx] == 0) {
1193 goto after;
1194 }
1195 if (v1[idx] == 0) {
1196 // do a swap:
1197 for (i = 0; i < len; i++) {
1198 a = v2[i];
1199 v2[i] = v1[i];
1200 v1[i] = a;
1201 }
1202 goto after;
1203 }
1204 a = F->negate(F->mult(F->inverse(v1[idx]), v2[idx]));
1205 //cout << "Gauss_step a=" << a << endl;
1206 for (i = 0; i < len; i++) {
1207 v2[i] = F->add(F->mult(v1[i], a), v2[i]);
1208 }
1209after:
1210 if (f_vv) {
1211 cout << "linear_algebra::Gauss_step after:" << endl;
1212 Int_vec_print(cout, v1, len);
1213 cout << endl;
1214 Int_vec_print(cout, v2, len);
1215 cout << endl;
1216 }
1217 if (f_v) {
1218 cout << "linear_algebra::Gauss_step done" << endl;
1219 }
1220}
1221
1222void linear_algebra::Gauss_step_make_pivot_one(int *v1, int *v2,
1223 int len, int idx, int verbose_level)
1224// afterwards: v1,v2 span the same space as before
1225// v2[idx] = 0, v1[idx] = 1,
1226{
1227 int i, a, av;
1228 int f_v = (verbose_level >= 1);
1229 int f_vv = FALSE;//(verbose_level >= 2);
1230
1231 if (f_v) {
1232 cout << "linear_algebra::Gauss_step_make_pivot_one" << endl;
1233 }
1234 if (f_vv) {
1235 cout << "before:" << endl;
1236 Int_vec_print(cout, v1, len);
1237 cout << endl;
1238 Int_vec_print(cout, v2, len);
1239 cout << endl;
1240 cout << "pivot column " << idx << endl;
1241 }
1242 if (v2[idx] == 0) {
1243 goto after;
1244 }
1245 if (v1[idx] == 0) {
1246 // do a swap:
1247 for (i = 0; i < len; i++) {
1248 a = v2[i];
1249 v2[i] = v1[i];
1250 v1[i] = a;
1251 }
1252 goto after;
1253 }
1254 a = F->negate(F->mult(F->inverse(v1[idx]), v2[idx]));
1255 //cout << "Gauss_step a=" << a << endl;
1256 for (i = 0; i < len; i++) {
1257 v2[i] = F->add(F->mult(v1[i], a), v2[i]);
1258 }
1259after:
1260 if (v1[idx] == 0) {
1261 cout << "linear_algebra::Gauss_step_make_pivot_one after: v1[idx] == 0" << endl;
1262 exit(1);
1263 }
1264 if (v1[idx] != 1) {
1265 a = v1[idx];
1266 av = F->inverse(a);
1267 for (i = 0; i < len; i++) {
1268 v1[i] = F->mult(av, v1[i]);
1269 }
1270 }
1271 if (f_vv) {
1272 cout << "linear_algebra::Gauss_step_make_pivot_one after:" << endl;
1273 Int_vec_print(cout, v1, len);
1274 cout << endl;
1275 Int_vec_print(cout, v2, len);
1276 cout << endl;
1277 }
1278 if (f_v) {
1279 cout << "linear_algebra::Gauss_step_make_pivot_one done" << endl;
1280 }
1281}
1282
1283void linear_algebra::extend_basis(int m, int n, int *Basis,
1284 int verbose_level)
1285// Assumes that Basis is n x n, with the first m rows filled in.
1286// Assumes that Basis has rank m.
1287// Fills in the bottom n - m rows of Basis to extend to a Basis of F_q^n
1288// Does not change the first m rows of Basis.
1289{
1290 int f_v = (verbose_level >= 1);
1291 int f_vv = FALSE; // (verbose_level >= 2);
1292 int *B;
1293 int *base_cols;
1294 int *embedding;
1295 int i, j, rk;
1296
1297 if (f_v) {
1298 cout << "linear_algebra::extend_basis" << endl;
1299 }
1300 if (f_vv) {
1301 cout << "matrix:" << endl;
1302 Int_vec_print_integer_matrix_width(cout, Basis, m, n, n, F->log10_of_q);
1303 }
1304 Int_vec_zero(Basis + m * n, (n - m) * n);
1305 B = NEW_int(n * n);
1306 base_cols = NEW_int(n);
1307 embedding = NEW_int(n);
1308 Int_vec_zero(B, n * n);
1309 Int_vec_copy(Basis, B, m * n);
1310 rk = base_cols_and_embedding(m, n, B,
1311 base_cols, embedding, verbose_level);
1312 if (rk != m) {
1313 cout << "linear_algebra::extend_basis rk != m" << endl;
1314 exit(1);
1315 }
1316 for (i = rk; i < n; i++) {
1317 j = embedding[i - rk];
1318 Basis[i * n + j] = 1;
1319 }
1320 FREE_int(B);
1321 FREE_int(base_cols);
1322 FREE_int(embedding);
1323
1324 if (f_v) {
1325 cout << "linear_algebra::extend_basis done" << endl;
1326 }
1327}
1328
1329int linear_algebra::base_cols_and_embedding(int m, int n, int *A,
1330 int *base_cols, int *embedding, int verbose_level)
1331// returns the rank rk of the matrix.
1332// It also computes base_cols[rk] and embedding[m - rk]
1333// It leaves A unchanged
1334{
1335 int f_v = (verbose_level >= 1);
1336 int f_vv = FALSE; //(verbose_level >= 2);
1337 int *B;
1338 int i, j, rk, idx;
1340
1341 if (f_v) {
1342 cout << "linear_algebra::base_cols_and_embedding" << endl;
1343 }
1344 if (f_vv) {
1345 cout << "matrix A:" << endl;
1347 }
1348 B = NEW_int(m * n);
1349 Int_vec_copy(A, B, m * n);
1350 rk = Gauss_simple(B, m, n, base_cols, verbose_level - 3);
1351 j = 0;
1352 for (i = 0; i < n; i++) {
1353 if (!Sorting.int_vec_search(base_cols, rk, i, idx)) {
1354 embedding[j++] = i;
1355 }
1356 }
1357 if (j != n - rk) {
1358 cout << "j != n - rk" << endl;
1359 cout << "j=" << j << endl;
1360 cout << "rk=" << rk << endl;
1361 cout << "n=" << n << endl;
1362 exit(1);
1363 }
1364 if (f_vv) {
1365 cout << "linear_algebra::base_cols_and_embedding" << endl;
1366 cout << "rk=" << rk << endl;
1367 cout << "base_cols:" << endl;
1368 Int_vec_print(cout, base_cols, rk);
1369 cout << endl;
1370 cout << "embedding:" << endl;
1371 Int_vec_print(cout, embedding, n - rk);
1372 cout << endl;
1373 }
1374 FREE_int(B);
1375 if (f_v) {
1376 cout << "linear_algebra::base_cols_and_embedding done" << endl;
1377 }
1378 return rk;
1379}
1380
1381int linear_algebra::Gauss_easy(int *A, int m, int n)
1382// returns the rank
1383{
1384 int *base_cols, rk;
1385
1386 base_cols = NEW_int(n);
1387 rk = Gauss_int(A, FALSE, TRUE, base_cols, FALSE, NULL, m, n, n, 0);
1388 FREE_int(base_cols);
1389 return rk;
1390}
1391
1392int linear_algebra::Gauss_easy_memory_given(int *A,
1393 int m, int n, int *base_cols)
1394// returns the rank
1395{
1396 int rk;
1397
1398 //base_cols = NEW_int(n);
1399 rk = Gauss_int(A, FALSE, TRUE, base_cols, FALSE, NULL, m, n, n, 0);
1400 //FREE_int(base_cols);
1401 return rk;
1402}
1403
1404int linear_algebra::Gauss_simple(int *A, int m, int n,
1405 int *base_cols, int verbose_level)
1406// A[m * n], base_cols[n]
1407// returns the rank which is the number of entries in base_cols
1408{
1409 int f_v = (verbose_level >= 1);
1410 int ret;
1411
1412 if (f_v) {
1413 cout << "linear_algebra::Gauss_simple before Gauss_int" << endl;
1414 }
1415 ret = Gauss_int(A, FALSE, TRUE, base_cols,
1416 FALSE, NULL, m, n, n, verbose_level);
1417 if (f_v) {
1418 cout << "linear_algebra::Gauss_simple after Gauss_int" << endl;
1419 }
1420 return ret;
1421}
1422
1423void linear_algebra::kernel_columns(int n, int nb_base_cols,
1424 int *base_cols, int *kernel_cols)
1425{
1426 orbiter_kernel_system::Orbiter->Int_vec->complement(base_cols, kernel_cols, n, nb_base_cols);
1427#if 0
1428 int i, j, k;
1429
1430 j = k = 0;
1431 for (i = 0; i < n; i++) {
1432 if (j < nb_base_cols && i == base_cols[j]) {
1433 j++;
1434 continue;
1435 }
1436 kernel_cols[k++] = i;
1437 }
1438#endif
1439}
1440
1441void linear_algebra::matrix_get_kernel_as_int_matrix(int *M,
1442 int m, int n, int *base_cols, int nb_base_cols,
1443 data_structures::int_matrix *kernel, int verbose_level)
1444{
1445 int f_v = (verbose_level >= 1);
1446 int *K;
1447 int kernel_m, kernel_n;
1448
1449 if (f_v) {
1450 cout << "linear_algebra::matrix_get_kernel_as_int_matrix" << endl;
1451 }
1452 K = NEW_int(n * (n - nb_base_cols));
1453 matrix_get_kernel(M, m, n, base_cols, nb_base_cols,
1454 kernel_m, kernel_n, K, verbose_level);
1455 kernel->allocate_and_init(kernel_m, kernel_n, K);
1456 FREE_int(K);
1457 if (f_v) {
1458 cout << "linear_algebra::matrix_get_kernel_as_int_matrix done" << endl;
1459 }
1460}
1461
1462void linear_algebra::matrix_get_kernel(int *M,
1463 int m, int n, int *base_cols, int nb_base_cols,
1464 int &kernel_m, int &kernel_n, int *kernel, int verbose_level)
1465// kernel[n * (n - nb_base_cols)]
1466// m is not used!
1467{
1468 int f_v = (verbose_level >= 1);
1469 int r, k, i, j, ii, iii, a, b;
1470 int *kcol;
1471 int m_one;
1472
1473 if (f_v) {
1474 cout << "linear_algebra::matrix_get_kernel" << endl;
1475 }
1476 if (kernel == NULL) {
1477 cout << "linear_algebra::matrix_get_kernel kernel == NULL" << endl;
1478 exit(1);
1479 }
1480 m_one = F->negate(1);
1481 r = nb_base_cols;
1482 k = n - r;
1483 kernel_m = n;
1484 kernel_n = k;
1485
1486 kcol = NEW_int(k);
1487
1488 ii = 0;
1489 j = 0;
1490 if (j < r) {
1491 b = base_cols[j];
1492 }
1493 else {
1494 b = -1;
1495 }
1496 for (i = 0; i < n; i++) {
1497 if (i == b) {
1498 j++;
1499 if (j < r) {
1500 b = base_cols[j];
1501 }
1502 else {
1503 b = -1;
1504 }
1505 }
1506 else {
1507 kcol[ii] = i;
1508 ii++;
1509 }
1510 }
1511 if (ii != k) {
1512 cout << "linear_algebra::matrix_get_kernel ii != k" << endl;
1513 exit(1);
1514 }
1515 //cout << "kcol = " << kcol << endl;
1516 ii = 0;
1517 j = 0;
1518 if (j < r) {
1519 b = base_cols[j];
1520 }
1521 else {
1522 b = -1;
1523 }
1524 for (i = 0; i < n; i++) {
1525 if (i == b) {
1526 for (iii = 0; iii < k; iii++) {
1527 a = kcol[iii];
1528 kernel[i * kernel_n + iii] = M[j * n + a];
1529 }
1530 j++;
1531 if (j < r) {
1532 b = base_cols[j];
1533 }
1534 else {
1535 b = -1;
1536 }
1537 }
1538 else {
1539 for (iii = 0; iii < k; iii++) {
1540 if (iii == ii) {
1541 kernel[i * kernel_n + iii] = m_one;
1542 }
1543 else {
1544 kernel[i * kernel_n + iii] = 0;
1545 }
1546 }
1547 ii++;
1548 }
1549 }
1550 if (f_v) {
1551 cout << "linear_algebra::matrix_get_kernel done" << endl;
1552 }
1553 FREE_int(kcol);
1554}
1555
1556int linear_algebra::perp(int n, int k, int *A, int *Gram, int verbose_level)
1557{
1558 int f_v = (verbose_level >= 1);
1559 int *B;
1560 int *K;
1561 int *base_cols;
1562 int nb_base_cols;
1563 int kernel_m, kernel_n, i, j;
1564
1565 if (f_v) {
1566 cout << "linear_algebra::perp" << endl;
1567 }
1568 B = NEW_int(n * n);
1569 K = NEW_int(n * n);
1570 base_cols = NEW_int(n);
1571 mult_matrix_matrix(A, Gram, B, k, n, n, 0 /* verbose_level */);
1572
1573 nb_base_cols = Gauss_int(B,
1574 FALSE /* f_special */, TRUE /* f_complete */, base_cols,
1575 FALSE /* f_P */, NULL /*P*/, k, n, n,
1576 0 /* verbose_level */);
1577
1578 if (nb_base_cols != k) {
1579 cout << "linear_algebra::perp nb_base_cols != k" << endl;
1580 cout << "need to copy B back to A to be safe." << endl;
1581 exit(1);
1582 }
1583
1584 matrix_get_kernel(B, k, n, base_cols, nb_base_cols,
1585 kernel_m, kernel_n, K, 0 /* verbose_level */);
1586
1587 for (j = 0; j < kernel_n; j++) {
1588 for (i = 0; i < n; i++) {
1589 A[(k + j) * n + i] = K[i * kernel_n + j];
1590 }
1591 }
1592 //cout << "perp, kernel is a " << kernel_m
1593 // << " by " << kernel_n << " matrix" << endl;
1594 FREE_int(B);
1595 FREE_int(K);
1596 FREE_int(base_cols);
1597 if (f_v) {
1598 cout << "linear_algebra::perp done" << endl;
1599 }
1600 return nb_base_cols;
1601}
1602
1603int linear_algebra::RREF_and_kernel(int n, int k,
1604 int *A, int verbose_level)
1605{
1606 int f_v = (verbose_level >= 1);
1607 int *B;
1608 int *K;
1609 int *base_cols;
1610 int nb_base_cols;
1611 int kernel_m, kernel_n, i, j, m;
1612
1613 if (f_v) {
1614 cout << "linear_algebra::RREF_and_kernel n=" << n
1615 << " k=" << k << endl;
1616 }
1617#if 0
1618 if (k > n) {
1619 m = k;
1620 }
1621 else {
1622 m = n;
1623 }
1624#endif
1625 m = MAXIMUM(k, n);
1626 B = NEW_int(m * n);
1627 K = NEW_int(n * n);
1628 base_cols = NEW_int(n);
1629 Int_vec_copy(A, B, k * n);
1630 //mult_matrix_matrix(A, Gram, B, k, n, n);
1631 if (f_v) {
1632 cout << "linear_algebra::RREF_and_kernel before Gauss_int" << endl;
1633 }
1634 nb_base_cols = Gauss_int(B,
1635 FALSE /* f_special */, TRUE /* f_complete */, base_cols,
1636 FALSE /* f_P */, NULL /*P*/, k, n, n, 0 /* verbose_level */);
1637 if (f_v) {
1638 cout << "linear_algebra::RREF_and_kernel after Gauss_int, "
1639 "rank = " << nb_base_cols << endl;
1640 }
1641 Int_vec_copy(B, A, nb_base_cols * n);
1642 if (f_v) {
1643 cout << "linear_algebra::RREF_and_kernel "
1644 "before matrix_get_kernel" << endl;
1645 }
1646 matrix_get_kernel(B, k, n, base_cols, nb_base_cols,
1647 kernel_m, kernel_n, K, 0 /* verbose_level */);
1648 for (j = 0; j < kernel_n; j++) {
1649 for (i = 0; i < n; i++) {
1650 A[(nb_base_cols + j) * n + i] = K[i * kernel_n + j];
1651 }
1652 }
1653 //cout << "finite_field::RREF_and_kernel,
1654 // kernel is a " << kernel_m << " by " << kernel_n << " matrix" << endl;
1655 FREE_int(B);
1656 FREE_int(K);
1657 FREE_int(base_cols);
1658 if (f_v) {
1659 cout << "linear_algebra::RREF_and_kernel done" << endl;
1660 }
1661 return nb_base_cols;
1662}
1663
1664int linear_algebra::perp_standard(int n, int k,
1665 int *A, int verbose_level)
1666{
1667 int f_v = (verbose_level >= 1);
1668 int *B;
1669 int *K;
1670 int *base_cols;
1671 int nb_base_cols;
1672
1673 if (f_v) {
1674 cout << "linear_algebra::perp_standard" << endl;
1675 }
1676 B = NEW_int(n * n);
1677 K = NEW_int(n * n);
1678 base_cols = NEW_int(n);
1679 nb_base_cols = perp_standard_with_temporary_data(n, k, A,
1680 B, K, base_cols,
1681 verbose_level - 3);
1682 FREE_int(B);
1683 FREE_int(K);
1684 FREE_int(base_cols);
1685 if (f_v) {
1686 cout << "linear_algebra::perp_standard done" << endl;
1687 }
1688 return nb_base_cols;
1689}
1690
1691int linear_algebra::perp_standard_with_temporary_data(
1692 int n, int k, int *A,
1693 int *B, int *K, int *base_cols,
1694 int verbose_level)
1695{
1696 int f_v = (verbose_level >= 1);
1697 //int *B;
1698 //int *K;
1699 //int *base_cols;
1700 int nb_base_cols;
1701 int kernel_m, kernel_n, i, j;
1702
1703 if (f_v) {
1704 cout << "linear_algebra::perp_standard_temporary_data" << endl;
1705 }
1706 //B = NEW_int(n * n);
1707 //K = NEW_int(n * n);
1708 //base_cols = NEW_int(n);
1709
1710 Int_vec_copy(A, B, k * n);
1711 if (f_v) {
1712 cout << "linear_algebra::perp_standard_temporary_data" << endl;
1713 cout << "B=" << endl;
1714 Int_matrix_print(B, k, n);
1715 cout << "finite_field::perp_standard_temporary_data before Gauss_int" << endl;
1716 }
1717 nb_base_cols = Gauss_int(B,
1718 FALSE /* f_special */, TRUE /* f_complete */, base_cols,
1719 FALSE /* f_P */, NULL /*P*/, k, n, n,
1720 0 /*verbose_level*/);
1721 if (f_v) {
1722 cout << "linear_algebra::perp_standard_temporary_data after Gauss_int" << endl;
1723 }
1724 matrix_get_kernel(B, k, n, base_cols, nb_base_cols,
1725 kernel_m, kernel_n, K, 0 /* verbose_level */);
1726 if (f_v) {
1727 cout << "linear_algebra::perp_standard_temporary_data "
1728 "after matrix_get_kernel" << endl;
1729 cout << "kernel_m = " << kernel_m << endl;
1730 cout << "kernel_n = " << kernel_n << endl;
1731 }
1732
1733 Int_vec_copy(B, A, nb_base_cols * n);
1734
1735 for (j = 0; j < kernel_n; j++) {
1736 for (i = 0; i < n; i++) {
1737 A[(nb_base_cols + j) * n + i] = K[i * kernel_n + j];
1738 }
1739 }
1740 if (f_v) {
1741 cout << "linear_algebra::perp_standard_temporary_data" << endl;
1742 cout << "A=" << endl;
1743 Int_matrix_print(A, n, n);
1744 }
1745 //cout << "perp_standard, kernel is a "
1746 // << kernel_m << " by " << kernel_n << " matrix" << endl;
1747 //FREE_int(B);
1748 //FREE_int(K);
1749 //FREE_int(base_cols);
1750 if (f_v) {
1751 cout << "linear_algebra::perp_standard_temporary_data done" << endl;
1752 }
1753 return nb_base_cols;
1754}
1755
1756int linear_algebra::intersect_subspaces(int n, int k1,
1757 int *A, int k2, int *B,
1758 int &k3, int *intersection, int verbose_level)
1759{
1760 int f_v = (verbose_level >= 1);
1761 int *AA, *BB, *CC, r1, r2, r3;
1762 int *B1;
1763 int *K;
1764 int *base_cols;
1765
1766 AA = NEW_int(n * n);
1767 BB = NEW_int(n * n);
1768 B1 = NEW_int(n * n);
1769 K = NEW_int(n * n);
1770 base_cols = NEW_int(n);
1771 Int_vec_copy(A, AA, k1 * n);
1772 Int_vec_copy(B, BB, k2 * n);
1773 if (f_v) {
1774 cout << "linear_algebra::intersect_subspaces AA=" << endl;
1775 Int_vec_print_integer_matrix_width(cout, AA, k1, n, n, 2);
1776 }
1778 AA, B1, K, base_cols, 0);
1779 if (f_v) {
1780 cout << "linear_algebra::intersect_subspaces AA=" << endl;
1781 Int_vec_print_integer_matrix_width(cout, AA, n, n, n, 2);
1782 }
1783 if (r1 != k1) {
1784 cout << "linear_algebra::intersect_subspaces not a base, "
1785 "rank is too small" << endl;
1786 cout << "k1=" << k1 << endl;
1787 cout << "r1=" << r1 << endl;
1788 exit(1);
1789 }
1790 if (f_v) {
1791 cout << "linear_algebra::intersect_subspaces BB=" << endl;
1792 Int_vec_print_integer_matrix_width(cout, BB, k2, n, n, 2);
1793 }
1794 r2 = perp_standard_with_temporary_data(n, k2, BB, B1, K, base_cols, 0);
1795 if (f_v) {
1796 cout << "linear_algebra::intersect_subspaces BB=" << endl;
1797 Int_vec_print_integer_matrix_width(cout, BB, n, n, n, 2);
1798 }
1799 if (r2 != k2) {
1800 cout << "linear_algebra::intersect_subspaces not a base, "
1801 "rank is too small" << endl;
1802 cout << "k2=" << k2 << endl;
1803 cout << "r2=" << r2 << endl;
1804 exit(1);
1805 }
1806 CC = NEW_int((3 * n) * n);
1807
1808 Int_vec_copy(AA + k1 * n, CC, (n - k1) * n);
1809 Int_vec_copy(BB + k2 * n, CC + (n - k1) * n, (n - k2) * n);
1810 k3 = (n - k1) + (n - k2);
1811 if (f_v) {
1812 cout << "linear_algebra::intersect_subspaces CC=" << endl;
1813 Int_vec_print_integer_matrix_width(cout, CC, k3, n, n, 2);
1814 cout << "k3=" << k3 << endl;
1815 }
1816
1817
1818 k3 = Gauss_easy(CC, k3, n);
1819
1820 r3 = perp_standard_with_temporary_data(n, k3, CC, B1, K, base_cols, 0);
1821 Int_vec_copy(CC + k3 * n, intersection, (n - r3) * n);
1822
1823 FREE_int(AA);
1824 FREE_int(BB);
1825 FREE_int(CC);
1826 FREE_int(B1);
1827 FREE_int(K);
1828 FREE_int(base_cols);
1829 if (f_v) {
1830 cout << "linear_algebra::intersect_subspaces n=" << n
1831 << " dim A =" << r1 << " dim B =" << r2
1832 << " dim intersection =" << n - r3 << endl;
1833 }
1834 k3 = n - r3;
1835 return n - r3;
1836
1837}
1838
1839int linear_algebra::n_choose_k_mod_p(int n, int k, int verbose_level)
1840{
1841 int f_v = (verbose_level >= 1);
1842 int f_vv = (verbose_level >= 2);
1843 int n1, k1, c, cc = 0, cv, c1 = 1, c2 = 1, i;
1844
1845 c = 1;
1846 while (n || k) {
1847 n1 = n % F->p;
1848 k1 = k % F->p;
1849 c1 = 1;
1850 c2 = 1;
1851 for (i = 0; i < k1; i++) {
1852 c1 = F->mult(c1, (n1 - i) % F->p);
1853 c2 = F->mult(c2, (1 + i) % F->p);
1854 }
1855 if (c1 != 0) {
1856 cv = F->inverse(c2);
1857 cc = F->mult(c1, cv);
1858 }
1859 if (f_vv) {
1860 cout << "{" << n1 << "\\atop " << k1 << "} mod "
1861 << F->p << " = " << cc << endl;
1862 }
1863 c = F->mult(c, cc);
1864 n = (n - n1) / F->p;
1865 k = (k - k1) / F->p;
1866 }
1867 if (f_v) {
1868 cout << "{" << n << "\\atop " << k << "} mod "
1869 << F->p << " = " << endl;
1870 cout << c << endl;
1871 }
1872 return c;
1873}
1874
1875void linear_algebra::Dickson_polynomial(int *map, int *coeffs)
1876// compute the coefficients of a degree q-1 polynomial
1877// which interpolates a given map
1878// from F_q to F_q
1879{
1880 int i, x, c, xi, a;
1881
1882 // coeff[0] = map[0]
1883 coeffs[0] = map[0];
1884
1885 // the middle coefficients:
1886 // coeff[i] = - sum_{x \neq 0} g(x) x^{-i}
1887 for (i = 1; i <= F->q - 2; i++) {
1888 c = 0;
1889 for (x = 1; x < F->q; x++) {
1890 xi = F->inverse(x);
1891 xi = F->power(xi, i);
1892 a = F->mult(map[x], xi);
1893 c = F->add(c, a);
1894 }
1895 coeffs[i] = F->negate(c);
1896 }
1897
1898 // coeff[q - 1] = - \sum_x map[x]
1899 c = 0;
1900 for (x = 0; x < F->q; x++) {
1901 c = F->add(c, map[x]);
1902 }
1903 coeffs[F->q - 1] = F->negate(c);
1904}
1905
1906void linear_algebra::projective_action_on_columns_from_the_left(
1907 int *A, int *M, int m, int n, int *perm,
1908 int verbose_level)
1909{
1910 int f_v = (verbose_level >= 1);
1911 int f_vv = (verbose_level >= 2);
1912 int *AM, i, j;
1914
1915 AM = NEW_int(m * n);
1916
1917 if (f_v) {
1918 cout << "linear_algebra::projective_action_on_columns_from_the_left" << endl;
1919 }
1920 if (f_vv) {
1921 cout << "A:" << endl;
1922 Int_vec_print_integer_matrix_width(cout, A, m, m, m, 2);
1923 }
1924 mult_matrix_matrix(A, M, AM, m, m, n, 0 /* verbose_level */);
1925 if (f_vv) {
1926 cout << "M:" << endl;
1927 Int_vec_print_integer_matrix_width(cout, M, m, n, n, 2);
1928 //cout << "A * M:" << endl;
1929 //print_integer_matrix_width(cout, AM, m, n, n, 2);
1930 }
1931
1932 for (j = 0; j < n; j++) {
1934 n /* stride */, m /* length */);
1935 }
1936 if (f_vv) {
1937 cout << "A*M:" << endl;
1938 Int_vec_print_integer_matrix_width(cout, AM, m, n, n, 2);
1939 }
1940
1941 for (i = 0; i < n; i++) {
1942 perm[i] = -1;
1943 for (j = 0; j < n; j++) {
1944 if (Sorting.int_vec_compare_stride(AM + i, M + j,
1945 m /* len */, n /* stride */) == 0) {
1946 perm[i] = j;
1947 break;
1948 }
1949 }
1950 if (j == n) {
1951 cout << "linear_algebra::projective_action_on_columns_"
1952 "from_the_left could not find image" << endl;
1953 cout << "i=" << i << endl;
1954 cout << "M:" << endl;
1955 Int_vec_print_integer_matrix_width(cout, M, m, n, n, 2);
1956 cout << "A * M:" << endl;
1957 Int_vec_print_integer_matrix_width(cout, AM, m, n, n, 2);
1958 exit(1);
1959 }
1960 }
1961 if (f_v) {
1962 //cout << "column permutation: ";
1964
1965 Combi.perm_print_with_cycle_length(cout, perm, n);
1966 cout << endl;
1967 }
1968 FREE_int(AM);
1969}
1970
1971int linear_algebra::evaluate_bilinear_form(int n,
1972 int *v1, int *v2, int *Gram)
1973{
1974 int *v3, a;
1975
1976 v3 = NEW_int(n);
1977 mult_matrix_matrix(v1, Gram, v3, 1, n, n, 0 /* verbose_level */);
1978 a = dot_product(n, v3, v2);
1979 FREE_int(v3);
1980 return a;
1981}
1982
1983int linear_algebra::evaluate_standard_hyperbolic_bilinear_form(
1984 int n, int *v1, int *v2)
1985{
1986 int a, b, c, n2, i;
1987
1988 if (ODD(n)) {
1989 cout << "linear_algebra::evaluate_standard_hyperbolic_bilinear_form "
1990 "n must be even" << endl;
1991 exit(1);
1992 }
1993 n2 = n >> 1;
1994 c = 0;
1995 for (i = 0; i < n2; i++) {
1996 a = F->mult(v1[2 * i + 0], v2[2 * i + 1]);
1997 b = F->mult(v1[2 * i + 1], v2[2 * i + 0]);
1998 c = F->add(c, a);
1999 c = F->add(c, b);
2000 }
2001 return c;
2002}
2003
2004int linear_algebra::evaluate_quadratic_form(int n, int nb_terms,
2005 int *i, int *j, int *coeff, int *x)
2006{
2007 int k, xi, xj, a, c, d;
2008
2009 a = 0;
2010 for (k = 0; k < nb_terms; k++) {
2011 xi = x[i[k]];
2012 xj = x[j[k]];
2013 c = coeff[k];
2014 d = F->mult(F->mult(c, xi), xj);
2015 a = F->add(a, d);
2016 }
2017 return a;
2018}
2019
2020void linear_algebra::find_singular_vector_brute_force(int n,
2021 int form_nb_terms,
2022 int *form_i, int *form_j, int *form_coeff, int *Gram,
2023 int *vec, int verbose_level)
2024{
2025 int f_v = (verbose_level >= 1);
2026 int N, a, i;
2027 int *v1;
2029
2030 if (f_v) {
2031 cout << "linear_algebra::find_singular_vector_brute_force" << endl;
2032 }
2033 v1 = NEW_int(n);
2034 N = Gg.nb_AG_elements(n, F->q);
2035 for (i = 2; i < N; i++) {
2036 Gg.AG_element_unrank(F->q, v1, 1, n, i);
2037 a = evaluate_quadratic_form(n, form_nb_terms,
2038 form_i, form_j, form_coeff, v1);
2039 if (f_v) {
2040 cout << "v1=";
2041 Int_vec_print(cout, v1, n);
2042 cout << endl;
2043 cout << "form value a=" << a << endl;
2044 }
2045 if (a == 0) {
2046 Int_vec_copy(v1, vec, n);
2047 goto finish;
2048 }
2049 }
2050 cout << "linear_algebra::find_singular_vector_brute_force "
2051 "did not find a singular vector" << endl;
2052 exit(1);
2053
2054finish:
2055 FREE_int(v1);
2056}
2057
2058void linear_algebra::find_singular_vector(int n, int form_nb_terms,
2059 int *form_i, int *form_j, int *form_coeff, int *Gram,
2060 int *vec, int verbose_level)
2061{
2062 int f_v = (verbose_level >= 1);
2063 int f_vv = (verbose_level >= 2);
2064 int a, b, c, d, r3, x, y, i, k3;
2065 int *v1, *v2, *v3, *v2_coords, *v3_coords, *intersection;
2067
2068 if (f_v) {
2069 cout << "linear_algebra::find_singular_vector" << endl;
2070 }
2071 if (n < 3) {
2072 cout << "linear_algebra::find_singular_vector n < 3" << endl;
2073 exit(1);
2074 }
2075 v1 = NEW_int(n * n);
2076 v2 = NEW_int(n * n);
2077 v3 = NEW_int(n * n);
2078 v2_coords = NEW_int(n);
2079 v3_coords = NEW_int(n);
2080 intersection = NEW_int(n * n);
2081
2082 //N = nb_AG_elements(n, q);
2083 Gg.AG_element_unrank(F->q, v1, 1, n, 1);
2084 a = evaluate_quadratic_form(n, form_nb_terms,
2085 form_i, form_j, form_coeff, v1);
2086 if (f_vv) {
2087 cout << "v1=";
2088 Int_vec_print(cout, v1, n);
2089 cout << endl;
2090 cout << "form value a=" << a << endl;
2091 }
2092 if (a == 0) {
2093 Int_vec_copy(v1, vec, n);
2094 goto finish;
2095 }
2096 perp(n, 1, v1, Gram, 0 /* verbose_level */);
2097 if (f_vv) {
2098 cout << "v1 perp:" << endl;
2099 Int_vec_print_integer_matrix_width(cout, v1 + n, n - 1, n, n, 2);
2100 }
2101 Gg.AG_element_unrank(F->q, v2_coords, 1, n - 1, 1);
2102 mult_matrix_matrix(v2_coords, v1 + n, v2, 1, n - 1, n,
2103 0 /* verbose_level */);
2104 b = evaluate_quadratic_form(n, form_nb_terms,
2105 form_i, form_j, form_coeff, v2);
2106 if (f_vv) {
2107 cout << "vector v2=";
2108 Int_vec_print(cout, v2, n);
2109 cout << endl;
2110 cout << "form value b=" << b << endl;
2111 }
2112 if (b == 0) {
2113 Int_vec_copy(v2, vec, n);
2114 goto finish;
2115 }
2116 perp(n, 1, v2, Gram, 0 /* verbose_level */);
2117 if (f_vv) {
2118 cout << "v2 perp:" << endl;
2119 Int_vec_print_integer_matrix_width(cout, v2 + n, n - 1, n, n, 2);
2120 }
2121 r3 = intersect_subspaces(n, n - 1, v1 + n, n - 1, v2 + n,
2122 k3, intersection, verbose_level);
2123 if (f_vv) {
2124 cout << "intersection has dimension " << r3 << endl;
2125 Int_vec_print_integer_matrix_width(cout, intersection, r3, n, n, 2);
2126 }
2127 if (r3 != n - 2) {
2128 cout << "r3 = " << r3 << " should be " << n - 2 << endl;
2129 exit(1);
2130 }
2131 Gg.AG_element_unrank(F->q, v3_coords, 1, n - 2, 1);
2132 mult_matrix_matrix(v3_coords, intersection, v3, 1, n - 2, n,
2133 0 /* verbose_level */);
2134 c = evaluate_quadratic_form(n, form_nb_terms,
2135 form_i, form_j, form_coeff, v3);
2136 if (f_vv) {
2137 cout << "v3=";
2138 Int_vec_print(cout, v3, n);
2139 cout << endl;
2140 cout << "form value c=" << c << endl;
2141 }
2142 if (c == 0) {
2143 Int_vec_copy(v3, vec, n);
2144 goto finish;
2145 }
2146 if (f_vv) {
2147 cout << "calling abc2xy" << endl;
2148 cout << "a=" << a << endl;
2149 cout << "b=" << b << endl;
2150 cout << "c=" << F->negate(c) << endl;
2151 }
2152 F->abc2xy(a, b, F->negate(c), x, y, verbose_level);
2153 if (f_v) {
2154 cout << "x=" << x << endl;
2155 cout << "y=" << y << endl;
2156 }
2159 for (i = 0; i < n; i++) {
2160 vec[i] = F->add(F->add(v1[i], v2[i]), v3[i]);
2161 }
2162 if (f_vv) {
2163 cout << "singular vector vec=";
2164 Int_vec_print(cout, vec, n);
2165 cout << endl;
2166 }
2167 d = evaluate_quadratic_form(n, form_nb_terms,
2168 form_i, form_j, form_coeff, vec);
2169 if (d) {
2170 cout << "is non-singular, error! d=" << d << endl;
2171 cout << "singular vector vec=";
2172 Int_vec_print(cout, vec, n);
2173 cout << endl;
2174 exit(1);
2175 }
2176finish:
2177 FREE_int(v1);
2178 FREE_int(v2);
2179 FREE_int(v3);
2180 FREE_int(v2_coords);
2181 FREE_int(v3_coords);
2182 FREE_int(intersection);
2183 if (f_v) {
2184 cout << "linear_algebra::find_singular_vector done" << endl;
2185 }
2186}
2187
2188void linear_algebra::complete_hyperbolic_pair(
2189 int n, int form_nb_terms,
2190 int *form_i, int *form_j, int *form_coeff, int *Gram,
2191 int *vec1, int *vec2, int verbose_level)
2192{
2193 int f_v = (verbose_level >= 1);
2194 int f_vv = (verbose_level >= 2);
2195 int i, a, b, c;
2196 int *v0, *v1;
2197
2198 v0 = NEW_int(n * n);
2199 v1 = NEW_int(n * n);
2200
2201 if (f_v) {
2202 cout << "linear_algebra::complete_hyperbolic_pair" << endl;
2203 }
2204 if (f_vv) {
2205 cout << "vec1=";
2206 Int_vec_print(cout, vec1, n);
2207 cout << endl;
2208 cout << "Gram=" << endl;
2209 Int_vec_print_integer_matrix_width(cout, Gram, 4, 4, 4, 2);
2210 }
2211 mult_matrix_matrix(vec1, Gram, v0, 1, n, n,
2212 0 /* verbose_level */);
2213 if (f_vv) {
2214 cout << "v0=";
2215 Int_vec_print(cout, v0, n);
2216 cout << endl;
2217 }
2218 Int_vec_zero(v1, n);
2219 for (i = n - 1; i >= 0; i--) {
2220 if (v0[i]) {
2221 v1[i] = 1;
2222 break;
2223 }
2224 }
2225 if (i == -1) {
2226 cout << "linear_algebra::complete_hyperbolic_pair i == -1" << endl;
2227 exit(1);
2228 }
2229 a = dot_product(n, v0, v1);
2230#if 0
2231 int N;
2232
2233 N = nb_AG_elements(n, q);
2234 if (f_v) {
2235 cout << "number of elements in AG(" << n << ","
2236 << q << ")=" << N << endl;
2237 }
2238 for (i = 1; i < N; i++) {
2239 if (f_v) {
2240 cout << "unranking vector " << i << " / "
2241 << N << " in the affine geometry" << endl;
2242 }
2243 AG_element_unrank(q, v1, 1, n, i);
2244 if (f_v) {
2245 cout << "v1=";
2246 int_vec_print(cout, v1, n);
2247 cout << endl;
2248 }
2249 a = dot_product(n, v0, v1);
2250 if (f_v) {
2251 cout << "i=" << i << " trying vector ";
2252 int_vec_print(cout, v1, n);
2253 cout << " form value a=" << a << endl;
2254 }
2255 if (a)
2256 break;
2257 }
2258 if (i == N) {
2259 cout << "linear_algebra::complete_hyperbolic_pair "
2260 "did not find a vector whose dot product is non-zero " << endl;
2261 }
2262#endif
2263
2264 if (a != 1) {
2266 }
2267 if (f_vv) {
2268 cout << "normalized ";
2269 Int_vec_print(cout, v1, n);
2270 cout << endl;
2271 }
2272 b = evaluate_quadratic_form(n, form_nb_terms,
2273 form_i, form_j, form_coeff, v1);
2274 b = F->negate(b);
2275 for (i = 0; i < n; i++) {
2276 vec2[i] = F->add(F->mult(b, vec1[i]), v1[i]);
2277 }
2278 if (f_vv) {
2279 cout << "linear_algebra::complete_hyperbolic_pair" << endl;
2280 cout << "vec2=";
2281 Int_vec_print(cout, vec2, n);
2282 cout << endl;
2283 }
2284 c = dot_product(n, v0, vec2);
2285 if (c != 1) {
2286 cout << "dot product is not 1, error" << endl;
2287 cout << "c=" << c << endl;
2288 cout << "vec1=";
2289 Int_vec_print(cout, vec1, n);
2290 cout << endl;
2291 cout << "vec2=";
2292 Int_vec_print(cout, vec2, n);
2293 cout << endl;
2294 }
2295 FREE_int(v0);
2296 FREE_int(v1);
2297 if (f_v) {
2298 cout << "linear_algebra::complete_hyperbolic_pair done" << endl;
2299 }
2300
2301}
2302
2303void linear_algebra::find_hyperbolic_pair(int n, int form_nb_terms,
2304 int *form_i, int *form_j, int *form_coeff, int *Gram,
2305 int *vec1, int *vec2, int verbose_level)
2306{
2307 int f_v = (verbose_level >= 1);
2308 int f_vv = (verbose_level >= 2);
2309
2310 if (f_v) {
2311 cout << "linear_algebra::find_hyperbolic_pair" << endl;
2312 }
2313 if (n >= 3) {
2314 find_singular_vector(n, form_nb_terms,
2315 form_i, form_j, form_coeff, Gram,
2316 vec1, verbose_level);
2317 }
2318 else {
2319 find_singular_vector_brute_force(n, form_nb_terms,
2320 form_i, form_j, form_coeff, Gram,
2321 vec1, verbose_level);
2322 }
2323 if (f_vv) {
2324 cout << "linear_algebra::find_hyperbolic_pair, "
2325 "found singular vector" << endl;
2326 Int_vec_print(cout, vec1, n);
2327 cout << endl;
2328 cout << "calling complete_hyperbolic_pair" << endl;
2329 }
2330 complete_hyperbolic_pair(n, form_nb_terms,
2331 form_i, form_j, form_coeff, Gram,
2332 vec1, vec2, verbose_level);
2333 if (f_v) {
2334 cout << "linear_algebra::find_hyperbolic_pair done" << endl;
2335 }
2336}
2337
2338void linear_algebra::restrict_quadratic_form_list_coding(
2339 int k, int n, int *basis,
2340 int form_nb_terms, int *form_i, int *form_j, int *form_coeff,
2341 int &restricted_form_nb_terms, int *&restricted_form_i,
2342 int *&restricted_form_j, int *&restricted_form_coeff,
2343 int verbose_level)
2344{
2345 int f_v = (verbose_level >= 1);
2346 int f_vv = (verbose_level >= 2);
2347 int *C, *D, h, i, j, c;
2348
2349 if (f_v) {
2350 cout << "linear_algebra::restrict_quadratic_form_list_coding" << endl;
2351 }
2352 C = NEW_int(n * n);
2353 D = NEW_int(k * k);
2354 Int_vec_zero(C, n * n);
2355 for (h = 0; h < form_nb_terms; h++) {
2356 i = form_i[h];
2357 j = form_j[h];
2358 c = form_coeff[h];
2359 C[i * n + j] = c;
2360 }
2361 if (f_vv) {
2362 cout << "linear_algebra::restrict_quadratic_form_list_coding "
2363 "C=" << endl;
2364 Int_vec_print_integer_matrix_width(cout, C, n, n, n, 2);
2365 }
2366 restrict_quadratic_form(k, n, basis, C, D, verbose_level - 1);
2367 if (f_vv) {
2368 cout << "linear_algebra::restrict_quadratic_form_list_coding "
2369 "D=" << endl;
2370 Int_vec_print_integer_matrix_width(cout, D, k, k, k, 2);
2371 }
2372 restricted_form_nb_terms = 0;
2373 restricted_form_i = NEW_int(k * k);
2374 restricted_form_j = NEW_int(k * k);
2375 restricted_form_coeff = NEW_int(k * k);
2376 for (i = 0; i < k; i++) {
2377 for (j = 0; j < k; j++) {
2378 c = D[i * k + j];
2379 if (c == 0) {
2380 continue;
2381 }
2382 restricted_form_i[restricted_form_nb_terms] = i;
2383 restricted_form_j[restricted_form_nb_terms] = j;
2384 restricted_form_coeff[restricted_form_nb_terms] = c;
2385 restricted_form_nb_terms++;
2386 }
2387 }
2388 FREE_int(C);
2389 FREE_int(D);
2390 if (f_v) {
2391 cout << "linear_algebra::restrict_quadratic_form_list_coding done" << endl;
2392 }
2393}
2394
2395void linear_algebra::restrict_quadratic_form(int k, int n,
2396 int *basis, int *C, int *D,
2397 int verbose_level)
2398{
2399 int f_v = (verbose_level >= 1);
2400 int f_vv = (verbose_level >= 2);
2401 int i, j, lambda, mu, a1, a2, d, c;
2402
2403 if (f_v) {
2404 cout << "linear_algebra::restrict_quadratic_form" << endl;
2405 }
2406 if (f_vv) {
2407 cout << "linear_algebra::restrict_quadratic_form" << endl;
2408 Int_vec_print_integer_matrix_width(cout, C, n, n, n, 2);
2409 }
2410 Int_vec_zero(D, k * k);
2411 for (lambda = 0; lambda < k; lambda++) {
2412 for (mu = 0; mu < k; mu++) {
2413 d = 0;
2414 for (i = 0; i < n; i++) {
2415 for (j = i; j < n; j++) {
2416 a1 = basis[lambda * n + i];
2417 a2 = basis[mu * n + j];
2418 c = C[i * n + j];
2419 d = F->add(d, F->mult(c, F->mult(a1, a2)));
2420 }
2421 }
2422 if (mu < lambda) {
2423 D[mu * k + lambda] = F->add(D[mu * k + lambda], d);
2424 }
2425 else {
2426 D[lambda * k + mu] = F->add(D[lambda * k + mu], d);
2427 }
2428 }
2429 }
2430 if (f_vv) {
2431 Int_vec_print_integer_matrix_width(cout, D, k, k, k, 2);
2432 }
2433 if (f_v) {
2434 cout << "linear_algebra::restrict_quadratic_form" << endl;
2435 }
2436}
2437
2438int linear_algebra::compare_subspaces_ranked(
2439 int *set1, int *set2, int size,
2440 int vector_space_dimension, int verbose_level)
2441// Compares the span of two sets of vectors.
2442// returns 0 if equal, 1 if not
2443// (this is so that it matches to the result of a compare function)
2444{
2445 int f_v = (verbose_level >= 1);
2446 int f_vv = (verbose_level >= 2);
2447 int *M1;
2448 int *M2;
2449 int *base_cols1;
2450 int *base_cols2;
2451 int i;
2452 int rk1, rk2, r;
2453
2454 if (f_v) {
2455 cout << "linear_algebra::compare_subspaces_ranked" << endl;
2456 }
2457 if (f_vv) {
2458 cout << "linear_algebra::compare_subspaces_ranked" << endl;
2459 cout << "set1: ";
2460 Int_vec_print(cout, set1, size);
2461 cout << endl;
2462 cout << "set2: ";
2463 Int_vec_print(cout, set2, size);
2464 cout << endl;
2465 }
2466 M1 = NEW_int(size * vector_space_dimension);
2467 M2 = NEW_int(size * vector_space_dimension);
2468 base_cols1 = NEW_int(vector_space_dimension);
2469 base_cols2 = NEW_int(vector_space_dimension);
2470 for (i = 0; i < size; i++) {
2472 M1 + i * vector_space_dimension,
2473 1, vector_space_dimension, set1[i]);
2475 M2 + i * vector_space_dimension,
2476 1, vector_space_dimension, set2[i]);
2477 }
2478 if (f_vv) {
2479 cout << "matrix1:" << endl;
2481 vector_space_dimension, vector_space_dimension, F->log10_of_q);
2482 cout << "matrix2:" << endl;
2484 vector_space_dimension, vector_space_dimension, F->log10_of_q);
2485 }
2486 rk1 = Gauss_simple(M1, size, vector_space_dimension,
2487 base_cols1, 0/*int verbose_level*/);
2488 rk2 = Gauss_simple(M2, size, vector_space_dimension,
2489 base_cols2, 0/*int verbose_level*/);
2490 if (f_vv) {
2491 cout << "after Gauss" << endl;
2492 cout << "matrix1:" << endl;
2494 vector_space_dimension, vector_space_dimension, F->log10_of_q);
2495 cout << "rank1=" << rk1 << endl;
2496 cout << "base_cols1: ";
2497 Int_vec_print(cout, base_cols1, rk1);
2498 cout << endl;
2499 cout << "matrix2:" << endl;
2501 vector_space_dimension, vector_space_dimension, F->log10_of_q);
2502 cout << "rank2=" << rk2 << endl;
2503 cout << "base_cols2: ";
2504 Int_vec_print(cout, base_cols2, rk2);
2505 cout << endl;
2506 }
2507 if (rk1 != rk2) {
2508 if (f_vv) {
2509 cout << "the ranks differ, so the subspaces are not equal, "
2510 "we return 1" << endl;
2511 }
2512 r = 1;
2513 goto ret;
2514 }
2515 for (i = 0; i < rk1; i++) {
2516 if (base_cols1[i] != base_cols2[i]) {
2517 if (f_vv) {
2518 cout << "the base_cols differ in entry " << i
2519 << ", so the subspaces are not equal, "
2520 "we return 1" << endl;
2521 }
2522 r = 1;
2523 goto ret;
2524 }
2525 }
2526 for (i = 0; i < size * vector_space_dimension; i++) {
2527 if (M1[i] != M2[i]) {
2528 if (f_vv) {
2529 cout << "the matrices differ in entry " << i
2530 << ", so the subspaces are not equal, "
2531 "we return 1" << endl;
2532 }
2533 r = 1;
2534 goto ret;
2535 }
2536 }
2537 if (f_vv) {
2538 cout << "the subspaces are equal, we return 0" << endl;
2539 }
2540 r = 0;
2541ret:
2542 FREE_int(M1);
2543 FREE_int(M2);
2544 FREE_int(base_cols1);
2545 FREE_int(base_cols2);
2546 if (f_v) {
2547 cout << "linear_algebra::compare_subspaces_ranked done" << endl;
2548 }
2549 return r;
2550}
2551
2552int linear_algebra::compare_subspaces_ranked_with_unrank_function(
2553 int *set1, int *set2, int size,
2554 int vector_space_dimension,
2555 void (*unrank_point_func)(int *v, int rk, void *data),
2556 void *rank_point_data,
2557 int verbose_level)
2558// Compares the span of two sets of vectors.
2559// returns 0 if equal, 1 if not
2560// (this is so that it matches to the result of a compare function)
2561{
2562 int f_v = (verbose_level >= 1);
2563 int f_vv = (verbose_level >= 2);
2564 int *M1;
2565 int *M2;
2566 int *base_cols1;
2567 int *base_cols2;
2568 int i;
2569 int rk1, rk2, r;
2570
2571 if (f_v) {
2572 cout << "linear_algebra::compare_subspaces_ranked_with_unrank_function" << endl;
2573 }
2574 if (f_vv) {
2575 cout << "linear_algebra::compare_subspaces_ranked_with_unrank_function" << endl;
2576 cout << "set1: ";
2577 Int_vec_print(cout, set1, size);
2578 cout << endl;
2579 cout << "set2: ";
2580 Int_vec_print(cout, set2, size);
2581 cout << endl;
2582 }
2583 M1 = NEW_int(size * vector_space_dimension);
2584 M2 = NEW_int(size * vector_space_dimension);
2585 base_cols1 = NEW_int(vector_space_dimension);
2586 base_cols2 = NEW_int(vector_space_dimension);
2587 for (i = 0; i < size; i++) {
2588 (*unrank_point_func)(M1 + i * vector_space_dimension,
2589 set1[i], rank_point_data);
2590 (*unrank_point_func)(M2 + i * vector_space_dimension,
2591 set2[i], rank_point_data);
2592#if 0
2593 PG_element_unrank_modified(*this, M1 + i * vector_space_dimension,
2594 1, vector_space_dimension, set1[i]);
2595 PG_element_unrank_modified(*this, M2 + i * vector_space_dimension,
2596 1, vector_space_dimension, set2[i]);
2597#endif
2598 }
2599 if (f_vv) {
2600 cout << "matrix1:" << endl;
2602 vector_space_dimension, vector_space_dimension,
2603 F->log10_of_q);
2604 cout << "matrix2:" << endl;
2606 vector_space_dimension, vector_space_dimension,
2607 F->log10_of_q);
2608 }
2609 rk1 = Gauss_simple(M1, size,
2610 vector_space_dimension, base_cols1,
2611 0/*int verbose_level*/);
2612 rk2 = Gauss_simple(M2, size,
2613 vector_space_dimension, base_cols2,
2614 0/*int verbose_level*/);
2615 if (f_vv) {
2616 cout << "after Gauss" << endl;
2617 cout << "matrix1:" << endl;
2619 vector_space_dimension, vector_space_dimension,
2620 F->log10_of_q);
2621 cout << "rank1=" << rk1 << endl;
2622 cout << "base_cols1: ";
2623 Int_vec_print(cout, base_cols1, rk1);
2624 cout << endl;
2625 cout << "matrix2:" << endl;
2627 vector_space_dimension, vector_space_dimension,
2628 F->log10_of_q);
2629 cout << "rank2=" << rk2 << endl;
2630 cout << "base_cols2: ";
2631 Int_vec_print(cout, base_cols2, rk2);
2632 cout << endl;
2633 }
2634 if (rk1 != rk2) {
2635 if (f_vv) {
2636 cout << "the ranks differ, so the subspaces are not equal, "
2637 "we return 1" << endl;
2638 }
2639 r = 1;
2640 goto ret;
2641 }
2642 for (i = 0; i < rk1; i++) {
2643 if (base_cols1[i] != base_cols2[i]) {
2644 if (f_vv) {
2645 cout << "the base_cols differ in entry " << i
2646 << ", so the subspaces are not equal, "
2647 "we return 1" << endl;
2648 }
2649 r = 1;
2650 goto ret;
2651 }
2652 }
2653 for (i = 0; i < size * vector_space_dimension; i++) {
2654 if (M1[i] != M2[i]) {
2655 if (f_vv) {
2656 cout << "the matrices differ in entry " << i
2657 << ", so the subspaces are not equal, "
2658 "we return 1" << endl;
2659 }
2660 r = 1;
2661 goto ret;
2662 }
2663 }
2664 if (f_vv) {
2665 cout << "the subspaces are equal, we return 0" << endl;
2666 }
2667 r = 0;
2668ret:
2669 FREE_int(M1);
2670 FREE_int(M2);
2671 FREE_int(base_cols1);
2672 FREE_int(base_cols2);
2673 if (f_v) {
2674 cout << "linear_algebra::compare_subspaces_ranked_with_unrank_function done" << endl;
2675 }
2676 return r;
2677}
2678
2679int linear_algebra::Gauss_canonical_form_ranked(
2680 int *set1, int *set2, int size,
2681 int vector_space_dimension, int verbose_level)
2682// Computes the Gauss canonical form for the generating set in set1.
2683// The result is written to set2.
2684// Returns the rank of the span of the elements in set1.
2685{
2686 int f_v = (verbose_level >= 1);
2687 int f_vv = (verbose_level >= 2);
2688 int *M;
2689 int *base_cols;
2690 int i;
2691 int rk;
2692
2693 if (f_v) {
2694 cout << "linear_algebra::Gauss_canonical_form_ranked" << endl;
2695 }
2696 if (f_vv) {
2697 cout << "linear_algebra::Gauss_canonical_form_ranked" << endl;
2698 cout << "set1: ";
2699 Int_vec_print(cout, set1, size);
2700 cout << endl;
2701 }
2702 M = NEW_int(size * vector_space_dimension);
2703 base_cols = NEW_int(vector_space_dimension);
2704 for (i = 0; i < size; i++) {
2706 M + i * vector_space_dimension,
2707 1, vector_space_dimension,
2708 set1[i]);
2709 }
2710 if (f_vv) {
2711 cout << "matrix:" << endl;
2713 vector_space_dimension, vector_space_dimension,
2714 F->log10_of_q);
2715 }
2716 rk = Gauss_simple(M, size,
2717 vector_space_dimension, base_cols,
2718 0/*int verbose_level*/);
2719 if (f_vv) {
2720 cout << "after Gauss" << endl;
2721 cout << "matrix:" << endl;
2723 vector_space_dimension, vector_space_dimension,
2724 F->log10_of_q);
2725 cout << "rank=" << rk << endl;
2726 cout << "base_cols: ";
2727 Int_vec_print(cout, base_cols, rk);
2728 cout << endl;
2729 }
2730
2731 for (i = 0; i < rk; i++) {
2733 M + i * vector_space_dimension,
2734 1, vector_space_dimension,
2735 set2[i]);
2736 }
2737
2738
2739 FREE_int(M);
2740 FREE_int(base_cols);
2741 if (f_v) {
2742 cout << "linear_algebra::Gauss_canonical_form_ranked done" << endl;
2743 }
2744 return rk;
2745
2746}
2747
2748int linear_algebra::lexleast_canonical_form_ranked(
2749 int *set1, int *set2, int size,
2750 int vector_space_dimension, int verbose_level)
2751// Computes the lexleast generating set the
2752// subspace spanned by the elements in set1.
2753// The result is written to set2.
2754// Returns the rank of the span of the elements in set1.
2755{
2756 int f_v = (verbose_level >= 1);
2757 int f_vv = (verbose_level >= 2);
2758 int *M1, *M2;
2759 int *v;
2760 int *w;
2761 int *base_cols;
2762 int *f_allowed;
2763 int *basis_vectors;
2764 int *list_of_ranks;
2765 int *list_of_ranks_PG;
2766 int *list_of_ranks_PG_sorted;
2767 int size_list, idx;
2768 int *tmp;
2769 int i, j, h, N, a, sz, Sz;
2770 int rk;
2774
2775 if (f_v) {
2776 cout << "linear_algebra::lexleast_canonical_form_ranked" << endl;
2777 }
2778 if (f_vv) {
2779 cout << "linear_algebra::lexleast_canonical_form_ranked" << endl;
2780 cout << "set1: ";
2781 Int_vec_print(cout, set1, size);
2782 cout << endl;
2783 }
2784 tmp = NEW_int(vector_space_dimension);
2785 M1 = NEW_int(size * vector_space_dimension);
2786 base_cols = NEW_int(vector_space_dimension);
2787 for (i = 0; i < size; i++) {
2788 F->PG_element_unrank_modified(M1 + i * vector_space_dimension,
2789 1, vector_space_dimension, set1[i]);
2790 }
2791 if (f_vv) {
2792 cout << "matrix:" << endl;
2794 vector_space_dimension, vector_space_dimension,
2795 F->log10_of_q);
2796 }
2797
2798 rk = Gauss_simple(M1, size, vector_space_dimension,
2799 base_cols, 0/*int verbose_level*/);
2800 v = NEW_int(rk);
2801 w = NEW_int(rk);
2802 if (f_vv) {
2803 cout << "after Gauss" << endl;
2804 cout << "matrix:" << endl;
2806 vector_space_dimension, vector_space_dimension,
2807 F->log10_of_q);
2808 cout << "rank=" << rk << endl;
2809 cout << "base_cols: ";
2810 Int_vec_print(cout, base_cols, rk);
2811 cout << endl;
2812 }
2813 N = NT.i_power_j(F->q, rk);
2814 M2 = NEW_int(N * vector_space_dimension);
2815 list_of_ranks = NEW_int(N);
2816 list_of_ranks_PG = NEW_int(N);
2817 list_of_ranks_PG_sorted = NEW_int(N);
2818 basis_vectors = NEW_int(rk);
2819 size_list = 0;
2820 list_of_ranks_PG[0] = -1;
2821 for (a = 0; a < N; a++) {
2822 Gg.AG_element_unrank(F->q, v, 1, rk, a);
2823 mult_matrix_matrix(v, M1, M2 + a * vector_space_dimension,
2824 1, rk, vector_space_dimension,
2825 0 /* verbose_level */);
2826 list_of_ranks[a] = Gg.AG_element_rank(F->q, M2 + a * vector_space_dimension, 1,
2827 vector_space_dimension);
2828 if (a == 0) {
2829 continue;
2830 }
2832 M2 + a * vector_space_dimension, 1,
2833 vector_space_dimension, list_of_ranks_PG[a]);
2834 if (!Sorting.int_vec_search(list_of_ranks_PG_sorted,
2835 size_list, list_of_ranks_PG[a], idx)) {
2836 for (h = size_list; h > idx; h--) {
2837 list_of_ranks_PG_sorted[h] = list_of_ranks_PG_sorted[h - 1];
2838 }
2839 list_of_ranks_PG_sorted[idx] = list_of_ranks_PG[a];
2840 size_list++;
2841 }
2842 }
2843 if (f_vv) {
2844 cout << "expanded matrix with all elements in the space:" << endl;
2846 vector_space_dimension, vector_space_dimension,
2847 F->log10_of_q);
2848 cout << "list_of_ranks:" << endl;
2849 Int_vec_print(cout, list_of_ranks, N);
2850 cout << endl;
2851 cout << "list_of_ranks_PG:" << endl;
2852 Int_vec_print(cout, list_of_ranks_PG, N);
2853 cout << endl;
2854 cout << "list_of_ranks_PG_sorted:" << endl;
2855 Int_vec_print(cout, list_of_ranks_PG_sorted, size_list);
2856 cout << endl;
2857 }
2858 f_allowed = NEW_int(size_list);
2859 for (i = 0; i < size_list; i++) {
2860 f_allowed[i] = TRUE;
2861 }
2862
2863 sz = 1;
2864 for (i = 0; i < rk; i++) {
2865 if (f_vv) {
2866 cout << "step " << i << " ";
2867 cout << " list_of_ranks_PG_sorted=";
2868 Int_vec_print(cout, list_of_ranks_PG_sorted, size_list);
2869 cout << " ";
2870 cout << "f_allowed=";
2871 Int_vec_print(cout, f_allowed, size_list);
2872 cout << endl;
2873 }
2874 for (a = 0; a < size_list; a++) {
2875 if (f_allowed[a]) {
2876 break;
2877 }
2878 }
2879 if (f_vv) {
2880 cout << "choosing a=" << a << " list_of_ranks_PG_sorted[a]="
2881 << list_of_ranks_PG_sorted[a] << endl;
2882 }
2883 basis_vectors[i] = list_of_ranks_PG_sorted[a];
2884 F->PG_element_unrank_modified(M1 + i * vector_space_dimension,
2885 1, vector_space_dimension, basis_vectors[i]);
2886 Sz = F->q * sz;
2887 if (f_vv) {
2888 cout << "step " << i
2889 << " basis_vector=" << basis_vectors[i] << " : ";
2890 Int_vec_print(cout, M1 + i * vector_space_dimension,
2891 vector_space_dimension);
2892 cout << " sz=" << sz << " Sz=" << Sz << endl;
2893 }
2894 for (h = 0; h < size_list; h++) {
2895 if (list_of_ranks_PG_sorted[h] == basis_vectors[i]) {
2896 if (f_vv) {
2897 cout << "disallowing " << h << endl;
2898 }
2899 f_allowed[h] = FALSE;
2900 break;
2901 }
2902 }
2903 for (j = sz; j < Sz; j++) {
2904 Gg.AG_element_unrank(F->q, v, 1, i + 1, j);
2905 if (f_vv) {
2906 cout << "j=" << j << " v=";
2907 Int_vec_print(cout, v, i + 1);
2908 cout << endl;
2909 }
2910#if 0
2911 for (h = 0; h < i + 1; h++) {
2912 w[i - h] = v[h];
2913 }
2914 if (f_v) {
2915 cout << " w=";
2916 int_vec_print(cout, w, i + 1);
2917 cout << endl;
2918 }
2919#endif
2920 mult_matrix_matrix(v/*w*/, M1, tmp, 1, i + 1,
2921 vector_space_dimension,
2922 0 /* verbose_level */);
2923 if (f_vv) {
2924 cout << " tmp=";
2925 Int_vec_print(cout, tmp, vector_space_dimension);
2926 cout << endl;
2927 }
2929 vector_space_dimension, a);
2930 if (f_vv) {
2931 cout << "has rank " << a << endl;
2932 }
2933 for (h = 0; h < size_list; h++) {
2934 if (list_of_ranks_PG_sorted[h] == a) {
2935 if (f_vv) {
2936 cout << "disallowing " << h << endl;
2937 }
2938 f_allowed[h] = FALSE;
2939 break;
2940 }
2941 }
2942 }
2943 sz = Sz;
2944 }
2945 if (f_vv) {
2946 cout << "basis_vectors by rank: ";
2947 Int_vec_print(cout, basis_vectors, rk);
2948 cout << endl;
2949 }
2950 if (f_vv) {
2951 cout << "basis_vectors by coordinates: " << endl;
2953 vector_space_dimension, vector_space_dimension,
2954 F->log10_of_q);
2955 cout << endl;
2956 }
2957
2958 for (i = 0; i < rk; i++) {
2959 F->PG_element_rank_modified(M1 + i * vector_space_dimension,
2960 1, vector_space_dimension, set2[i]);
2961 }
2962 if (f_vv) {
2963 cout << "basis_vectors by rank again (double check): ";
2964 Int_vec_print(cout, set2, rk);
2965 cout << endl;
2966 }
2967
2968
2969 FREE_int(tmp);
2970 FREE_int(M1);
2971 FREE_int(M2);
2972 FREE_int(v);
2973 FREE_int(w);
2974 FREE_int(base_cols);
2975 FREE_int(f_allowed);
2976 FREE_int(list_of_ranks);
2977 FREE_int(list_of_ranks_PG);
2978 FREE_int(list_of_ranks_PG_sorted);
2979 FREE_int(basis_vectors);
2980 if (f_v) {
2981 cout << "linear_algebra::lexleast_canonical_form_ranked done" << endl;
2982 }
2983 return rk;
2984
2985}
2986
2987void linear_algebra::exterior_square(int *An, int *An2, int n, int verbose_level)
2988{
2989 int f_v = (verbose_level >= 1);
2990
2991
2992 if (f_v) {
2993 cout << "linear_algebra::exterior_square" << endl;
2994 }
2995 int i, j, k, l, ij, kl;
2996 int aki, alj, akj, ali;
2997 int u, v, w;
2998 int n2;
3000
3001 if (f_v) {
3002 cout << "linear_algebra::exterior_square input matrix:" << endl;
3003 Int_matrix_print(An, n, n);
3004 }
3005
3006
3007 n2 = (n * (n - 1)) >> 1;
3008 // (i,j) = row index
3009 for (i = 0; i < n; i++) {
3010 for (j = i + 1; j < n; j++) {
3011 ij = Combi.ij2k(i, j, n);
3012
3013 // (k,l) = column index
3014 for (k = 0; k < n; k++) {
3015 for (l = k + 1; l < n; l++) {
3016 kl = Combi.ij2k(k, l, n);
3017
3018
3019 // a_{k,i}a_{l,j} - a_{k,j}a_{l,i}
3020 // = matrix entry at position (ij,kl)
3021#if 0
3022 aki = An[k * n + i];
3023 alj = An[l * n + j];
3024 akj = An[k * n + j];
3025 ali = An[l * n + i];
3026#else
3027 // transposed:
3028 aki = An[i * n + k];
3029 alj = An[j * n + l];
3030 akj = An[j * n + k];
3031 ali = An[i * n + l];
3032#endif
3033 u = F->mult(aki, alj);
3034 v = F->mult(akj, ali);
3035 w = F->add(u, F->negate(v));
3036
3037 // now w is the matrix entry
3038
3039 An2[ij * n2 + kl] = w;
3040 } // next l
3041 } // next k
3042 } // next j
3043 } // next i
3044
3045 if (f_v) {
3046 cout << "linear_algebra::exterior_square output matrix:" << endl;
3047 Int_matrix_print(An2, n2, n2);
3048 }
3049
3050 if (f_v) {
3051 cout << "linear_algebra::exterior_square done" << endl;
3052 }
3053}
3054
3055void linear_algebra::lift_to_Klein_quadric(int *A4, int *A6, int verbose_level)
3056{
3057 int f_v = (verbose_level >= 1);
3058
3059
3060 if (f_v) {
3061 cout << "linear_algebra::lift_to_Klein_quadric" << endl;
3062 }
3063 int E[36];
3064
3065 exterior_square(A4, E, 4, verbose_level);
3066
3067 int Basis1[] = {
3068 1,0,0,0,0,0,
3069 0,1,0,0,0,0,
3070 0,0,1,0,0,0,
3071 0,0,0,1,0,0,
3072 0,0,0,0,1,0,
3073 0,0,0,0,0,1,
3074 };
3075 int Basis2[36];
3076 int Image[36];
3077 int i;
3078
3079 for (i = 0; i < 6; i++) {
3080 F->klein_to_wedge(Basis1 + i * 6, Basis2 + i * 6);
3081 }
3082
3083 mult_matrix_matrix(Basis2, E, Image, 6, 6, 6, 0 /* verbose_level*/);
3084 for (i = 0; i < 6; i++) {
3085 F->wedge_to_klein(Image + i * 6, A6 + i * 6);
3086 }
3087 if (f_v) {
3088 cout << "linear_algebra::lift_to_Klein_quadric" << endl;
3089 }
3090
3091}
3092
3093
3094
3095}}}
3096
3097
global functions related to finite fields, irreducible polynomials and such
Definition: algebra.h:130
a collection of functions related to sorted vectors
int int_vec_compare_stride(int *p, int *q, int len, int stride)
Definition: sorting.cpp:2891
int int_vec_search(int *v, int len, int a, int &idx)
Definition: sorting.cpp:1094
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)
void abc2xy(int a, int b, int c, int &x, int &y, int verbose_level)
various functions related to geometries
Definition: geometry.h:721
void AG_element_unrank(int q, int *v, int stride, int len, long int a)
long int AG_element_rank(int q, int *v, int stride, int len)
void mult_vector_from_the_left(int *v, int *A, int *vA, int m, int n)
void find_singular_vector_brute_force(int n, int form_nb_terms, int *form_i, int *form_j, int *form_coeff, int *Gram, int *vec, int verbose_level)
void find_singular_vector(int n, int form_nb_terms, int *form_i, int *form_j, int *form_coeff, int *Gram, int *vec, int verbose_level)
int rank_of_rectangular_matrix_memory_given(int *A, int m, int n, int *B, int *base_cols, int verbose_level)
void exterior_square(int *An, int *An2, int n, int verbose_level)
int rank_of_matrix_memory_given(int *A, int m, int *B, int *base_cols, 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)
void support(int *A, int m, int *&support, int &size)
int matrix_determinant(int *A, int n, int verbose_level)
void complete_hyperbolic_pair(int n, int form_nb_terms, int *form_i, int *form_j, int *form_coeff, int *Gram, int *vec1, int *vec2, int verbose_level)
int base_cols_and_embedding(int m, int n, int *A, int *base_cols, int *embedding, int verbose_level)
void transpose_matrix(int *A, int *At, int ma, int na)
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)
void invert_matrix_memory_given(int *A, int *A_inv, int n, int *tmp_A, int *tmp_basecols, int verbose_level)
int perp_standard_with_temporary_data(int n, int k, int *A, int *B, int *K, int *base_cols, int verbose_level)
int perp(int n, int k, int *A, int *Gram, int verbose_level)
int evaluate_quadratic_form(int n, int nb_terms, int *i, int *j, int *coeff, int *x)
void Gauss_step(int *v1, int *v2, int len, int idx, int verbose_level)
void semilinear_action_from_the_right(int *v, int *A, int *vA, int n)
void restrict_quadratic_form(int k, int n, int *basis, int *C, int *D, int verbose_level)
int Gauss_simple(int *A, int m, int n, int *base_cols, int verbose_level)
void matrix_get_kernel(int *M, int m, int n, int *base_cols, int nb_base_cols, int &kernel_m, int &kernel_n, int *kernel, int verbose_level)
int intersect_subspaces(int n, int k1, int *A, int k2, int *B, int &k3, int *intersection, int verbose_level)
void matrix_invert(int *A, int *Tmp, int *Tmp_basecols, 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 ODD(x)
Definition: foundations.h:222
#define Int_vec_copy(A, B, C)
Definition: foundations.h:693
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
#define MAXIMUM(x, y)
Definition: foundations.h:217
orbiter_kernel_system::orbiter_session * Orbiter
global Orbiter session
the orbiter library for the classification of combinatorial objects