Orbiter 2022
Combinatorial Objects
direct_product.cpp
Go to the documentation of this file.
1// direct_product.cpp
2//
3// Anton Betten
4//
5// started: August 12, 2018
6
7
8
9
11#include "group_actions.h"
12
13using namespace std;
14
15
16namespace orbiter {
17namespace layer3_group_actions {
18namespace groups {
19
20
22{
23 null();
24}
25
27{
28 freeself();
29}
30
32{
33 M1 = NULL;
34 M2 = NULL;
35 F1 = NULL;
36 F2 = NULL;
37 q1 = 0;
38 q2 = 0;
39 perm_offset_i = NULL;
40 tmp_Elt1 = NULL;
41 elt1 = NULL;
42 Elts = NULL;
44 tl_for_component1 = NULL;
46 tl_for_component2 = NULL;
47 the_base = NULL;
49}
50
52{
53 int verbose_level = 0;
54 int f_v = (verbose_level >= 1);
55
56 if (f_v) {
57 cout << "direct_product::freeself" << endl;
58 }
59 if (perm_offset_i) {
61 }
62 if (tmp_Elt1) {
64 }
65 if (elt1) {
67 }
68 if (Elts) {
70 }
73 }
76 }
79 }
82 }
83 if (the_base) {
85 }
88 }
89 null();
90 if (f_v) {
91 cout << "direct_product::freeself finished" << endl;
92 }
93}
94
96 int verbose_level)
97{
98 int f_v = (verbose_level >= 1);
99
100 if (f_v) {
101 cout << "direct_product::init" << endl;
102 }
105 F1 = M1->GFq;
106 F2 = M2->GFq;
107 q1 = F1->q;
108 q2 = F2->q;
109
110 label.assign(M1->label);
111 label.append("_");
112 label.append(M2->label);
113 label.append("_product");
114 label_tex.assign(M1->label_tex);
115 label_tex.append(" \\times ");
116 label_tex.append(M2->label_tex);
117 //sprintf(label, "%s_cross_%s", M1->label, M2->label);
118 //sprintf(label_tex, "%s \\times %s", M1->label_tex, M2->label_tex);
119
133 if (f_v) {
134 cout << "direct_product::init "
135 "degree_of_product_action = "
136 << degree_of_product_action << endl;
137 cout << "direct_product::init "
138 "degree_overall = " << degree_overall << endl;
139 }
141 // one more so it can also be used to indicated
142 // the start of the product action.
143 perm_offset_i[0] = 0;
147 if (f_v) {
148 cout << "direct_product::init "
149 "elt_size_int = " << elt_size_int << endl;
150 }
152
157 char_per_elt = ((bits_per_elt + 7) >> 3);
159 if (f_v) {
160 cout << "direct_product::init "
161 "bits_per_digit1 = " << bits_per_digit1 << endl;
162 cout << "direct_product::init "
163 "bits_per_digit2 = " << bits_per_digit2 << endl;
164 cout << "direct_product::init "
165 "bits_per_elt = " << bits_per_elt << endl;
166 cout << "direct_product::init "
167 "char_per_elt = " << char_per_elt << endl;
168 }
169 base_len_in_component1 = M1->base_len(verbose_level);
170 if (f_v) {
171 cout << "direct_product::init "
172 "base_len_in_component1 = "
173 << base_len_in_component1 << endl;
174 }
175 base_len_in_component2 = M2->base_len(verbose_level);
176 if (f_v) {
177 cout << "direct_product::init "
178 "base_len_in_component1 = "
179 << base_len_in_component1 << endl;
180 cout << "direct_product::init "
181 "base_len_in_component2 = "
182 << base_len_in_component2 << endl;
183 }
186
190 verbose_level - 1);
191 if (f_v) {
192 cout << "direct_product::init "
193 "base_for_component1 = ";
196 cout << endl;
197 cout << "direct_product::init "
198 "tl_for_component1 = ";
201 cout << endl;
202 }
203
204
210 verbose_level - 1);
211
212 if (f_v) {
213 cout << "direct_product::init base_for_component2 = ";
215 cout << endl;
216 cout << "direct_product::init tl_for_component2 = ";
218 cout << endl;
219 }
220
222 Elts->init(char_per_elt /* entry_size */,
223 10 /* page_length_log */, verbose_level);
224
225 if (f_v) {
226 cout << "direct_product::init "
227 "before compute_base_and_transversals" << endl;
228 }
229 compute_base_and_transversals(verbose_level);
230 if (f_v) {
231 cout << "direct_product::init "
232 "after compute_base_and_transversals" << endl;
233 }
234 if (f_v) {
235 cout << "direct_product::init the_base = ";
237 cout << endl;
238 cout << "direct_product::init the_transversal_length = ";
240 cout << endl;
241 }
242
243 if (f_v) {
244 cout << "direct_product::init done" << endl;
245 }
246}
247
249 long int a, int verbose_level)
250{
251 int f_v = (verbose_level >= 1);
252 long int a0, b, c, c1, c2, i, j;
253
254 if (f_v) {
255 cout << "direct_product::element_image_of" << endl;
256 }
257 a0 = a;
258 b = 0;
259 if (a < M1->degree) {
260 if (f_v) {
261 cout << "direct_product::element_image_of "
262 "we are in component " << 0
263 << " reduced input a=" << a << endl;
264 }
265 c = M1->image_of_element(Elt + offset_i(0), a, 0 /* verbose_level */);
266 if (f_v) {
267 cout << "direct_product::element_image_of "
268 "we are in component " << 0
269 << " reduced output c=" << c << endl;
270 }
271 b += c;
272 }
273 else {
274 a -= M1->degree;
275 b += M1->degree;
276 if (a < M2->degree) {
277 if (f_v) {
278 cout << "direct_product::element_image_of "
279 "we are in component " << 1
280 << " reduced input a=" << a << endl;
281 }
282 c = M2->image_of_element(Elt + offset_i(1), a, 0 /* verbose_level */);
283 if (f_v) {
284 cout << "direct_product::element_image_of "
285 "we are in component " << 1
286 << " reduced output c=" << c << endl;
287 }
288 b += c;
289 }
290 else {
291 a -= M2->degree;
292 b += M2->degree;
293
294 j = a % M2->degree;
295 i = a / M2->degree;
296 if (f_v) {
297 cout << "direct_product::element_image_of "
298 "we are in the product component "
299 "reduced input a = " << a
300 << " i=" << i << " j=" << j << endl;
301 }
302 c1 = M1->image_of_element(Elt + offset_i(0), i, 0 /* verbose_level */);
303 c2 = M2->image_of_element(Elt + offset_i(1), j, 0 /* verbose_level */);
304 c = c1 * M2->degree + c2;
305 if (f_v) {
306 cout << "direct_product::element_image_of "
307 "we are in the product component "
308 " reduced output c=" << c << endl;
309 }
310 b += c;
311 if (f_v) {
312 cout << "direct_product::element_image_of "
313 "we are in the product component "
314 " output b=" << b << endl;
315 }
316 }
317 }
318 if (f_v) {
319 cout << "direct_product::element_image_of " << a0 << " maps to " << b << endl;
320 }
321 return b;
322}
323
325{
326 M1->GL_one(Elt + offset_i(0));
327 M2->GL_one(Elt + offset_i(1));
328}
329
331{
332 if (!M1->GL_is_one(Elt + offset_i(0))) {
333 return FALSE;
334 }
335 if (!M2->GL_is_one(Elt + offset_i(1))) {
336 return FALSE;
337 }
338 return TRUE;
339}
340
341void direct_product::element_mult(int *A, int *B, int *AB,
342 int verbose_level)
343{
344 int f_v = (verbose_level >= 1);
345
346 if (f_v) {
347 cout << "direct_product::element_mult" << endl;
348 }
349 M1->GL_mult(A + offset_i(0),
350 B + offset_i(0),
351 AB + offset_i(0),
352 0 /* verbose_level */);
353 M2->GL_mult(A + offset_i(1),
354 B + offset_i(1),
355 AB + offset_i(1),
356 0 /* verbose_level */);
357
358 if (f_v) {
359 cout << "direct_product::element_mult done" << endl;
360 }
361}
362
363void direct_product::element_move(int *A, int *B, int verbose_level)
364{
365 int f_v = (verbose_level >= 1);
366
367 if (f_v) {
368 cout << "direct_product::element_move" << endl;
369 }
371 if (f_v) {
372 cout << "direct_product::element_move done" << endl;
373 }
374}
375
376void direct_product::element_invert(int *A, int *Av, int verbose_level)
377{
378 int f_v = (verbose_level >= 1);
379
380 if (f_v) {
381 cout << "direct_product::element_invert" << endl;
382 }
383 M1->GL_invert(A + offset_i(0), Av + offset_i(0));
384 M2->GL_invert(A + offset_i(1), Av + offset_i(1));
385 if (f_v) {
386 cout << "direct_product::element_invert done" << endl;
387 }
388}
389
390
392{
393 if (f == 0) {
394 return 0;
395 }
396 else if (f == 1) {
397 return M1->elt_size_int;
398 }
399 else {
400 cout << "direct_product::offset_i illegal value of f" << endl;
401 exit(1);
402 }
403}
404
406{
407 int i;
408
409 for (i = 0; i < M1->make_element_size; i++) {
410 put_digit(elt, 0, i, (Elt + offset_i(0))[i]);
411 }
412 for (i = 0; i < M2->make_element_size; i++) {
413 put_digit(elt, 1, i, (Elt + offset_i(1))[i]);
414 }
415}
416
418{
419 int i;
420 int *m;
421
422 //cout << "direct_product::element_unpack" << endl;
423 m = Elt + offset_i(0);
424 for (i = 0; i < M1->make_element_size; i++) {
425 m[i] = get_digit(elt, 0, i);
426 }
428 0 /*verbose_level - 2*/);
429 m = Elt + offset_i(1);
430 for (i = 0; i < M2->make_element_size; i++) {
431 m[i] = get_digit(elt, 1, i);
432 }
434 0 /*verbose_level - 2*/);
435 //cout << "after direct_product::element_unpack: " << endl;
436 //element_print_easy(Elt, cout);
437}
438
439void direct_product::put_digit(uchar *elt, int f, int i, int d)
440{
441 int h0 = 0;
442 int h, h1, a;
443 int nb_bits = 0;
445
446 if (f == 0) {
447 nb_bits = bits_per_digit1;
448 }
449 else if (f == 1) {
451 nb_bits = bits_per_digit2;
452 }
453 h0 += i * nb_bits;
454 for (h = 0; h < nb_bits; h++) {
455 h1 = h0 + h;
456
457 if (d & 1) {
458 a = 1;
459 }
460 else {
461 a = 0;
462 }
463 D.bitvector_m_ii(elt, h1, a);
464 d >>= 1;
465 }
466}
467
468int direct_product::get_digit(uchar *elt, int f, int i)
469{
470 int h0 = 0;
471 int h, h1, a, d;
472 int nb_bits = 0;
474
475 if (f == 0) {
476 nb_bits = bits_per_digit1;
477 }
478 else if (f == 1) {
480 nb_bits = bits_per_digit2;
481 }
482 h0 += i * nb_bits;
483 d = 0;
484 for (h = nb_bits - 1; h >= 0; h--) {
485 h1 = h0 + h;
486
487 a = D.bitvector_s_i(elt, h1);
488 d <<= 1;
489 if (a) {
490 d |= 1;
491 }
492 }
493 return d;
494}
495
496void direct_product::make_element(int *Elt, int *data, int verbose_level)
497{
498 int f_v = (verbose_level >= 1);
499
500 if (f_v) {
501 cout << "direct_product::make_element" << endl;
502 }
503 if (f_v) {
504 cout << "direct_product::make_element data:" << endl;
505 Int_vec_print(cout, data, make_element_size);
506 cout << endl;
507 }
508 M1->make_element(Elt + offset_i(0),
509 data,
510 0 /* verbose_level */);
511 M2->make_element(Elt + offset_i(1),
512 data + M1->make_element_size,
513 0 /* verbose_level */);
514 if (f_v) {
515 cout << "direct_product::make_element "
516 "created this element:" << endl;
517 element_print_easy(Elt, cout);
518 }
519 if (f_v) {
520 cout << "direct_product::make_element done" << endl;
521 }
522}
523
524void direct_product::element_print_easy(int *Elt, ostream &ost)
525{
526 int f;
527
528 ost << "begin element of direct product: " << endl;
529 if (M1->n == 1 && M2->n == 1) {
530 cout << "(" << Elt[0] << "," << Elt[1] << ","
531 << Elt[4] << "," << Elt[5] << ")" << endl;
532 }
533 else {
534 for (f = 0; f < 2; f++) {
535 ost << "component " << f << ":" << endl;
536 if (f == 0) {
537 M1->GL_print_easy(Elt + offset_i(f), ost);
538 cout << endl;
539 }
540 else {
541 M2->GL_print_easy(Elt + offset_i(f), ost);
542 cout << endl;
543 }
544 }
545 }
546 ost << "end element of direct product" << endl;
547}
548
550{
551 int f_v = (verbose_level >= 1);
552 int i, h;
553
554 if (f_v) {
555 cout << "direct_product::compute_base_and_transversals" << endl;
556 }
557 base_length = 0;
561
562 h = 0;
563 for (i = 0; i < base_len_in_component1; i++, h++) {
565 }
566 for (i = 0; i < base_len_in_component2; i++, h++) {
568 }
569 if (h != base_length) {
570 cout << "direct_product::compute_base_and_transversals "
571 "h != base_length (1)" << endl;
572 exit(1);
573 }
575 h = 0;
576 for (i = 0; i < base_len_in_component1; i++, h++) {
578 }
579 for (i = 0; i < base_len_in_component2; i++, h++) {
581 }
582 if (h != base_length) {
583 cout << "direct_product::compute_base_and_transversals "
584 "h != base_length (2)" << endl;
585 exit(1);
586 }
587 if (f_v) {
588 cout << "direct_product::compute_base_and_transversals done" << endl;
589 }
590}
591
593 int &size, int &nb_gens, int verbose_level)
594{
595 int f_v = (verbose_level >= 1);
596 int *GL1_data;
597 int GL1_size;
598 int GL1_nb_gens;
599 int *GL2_data;
600 int GL2_size;
601 int GL2_nb_gens;
602 int h, g;
603 int *dat;
604
605 if (f_v) {
606 cout << "direct_product::make_strong_generators_data" << endl;
607 }
608 if (f_v) {
609 cout << "direct_product::make_strong_generators_data "
610 "before strong_generators_for_general_linear_group" << endl;
611 }
613 GL1_data, GL1_size, GL1_nb_gens,
614 verbose_level - 1);
616 GL2_data, GL2_size, GL2_nb_gens,
617 verbose_level - 1);
618
619 if (f_v) {
620 cout << "direct_product::make_strong_generators_data "
621 "after strong_generators_for_general_linear_group" << endl;
622 }
623 nb_gens = GL1_nb_gens + GL2_nb_gens;
624 size = make_element_size;
625 data = NEW_int(nb_gens * size);
626 dat = NEW_int(size);
627
628 h = 0;
629 // generators for the second component:
630 for (g = 0; g < GL2_nb_gens; g++) {
631 Int_vec_zero(dat, size);
633 dat,
635 Int_vec_copy(GL2_data + g * GL2_size,
636 dat + M1->make_element_size,
637 GL2_size);
638 Int_vec_copy(dat, data + h * size, size);
639 h++;
640 }
641 // generators for the first component:
642 for (g = 0; g < GL1_nb_gens; g++) {
643 Int_vec_zero(dat, size);
644 Int_vec_copy(GL1_data + g * GL1_size,
645 dat + 0,
646 GL1_size);
648 dat + M1->make_element_size,
650 Int_vec_copy(dat, data + h * size, size);
651 h++;
652 }
653 if (h != nb_gens) {
654 cout << "h != nb_gens" << endl;
655 exit(1);
656 }
657 FREE_int(GL1_data);
658 FREE_int(GL2_data);
659 FREE_int(dat);
660 if (f_v) {
661 cout << "direct_product::make_strong_generators_data done" << endl;
662 }
663}
664
669 int verbose_level)
670{
671 int f_v = (verbose_level >= 1);
672 actions::action *A1;
673 actions::action *A2;
674 int *Elt1;
675 int *Elt2;
676 int *Elt3;
678 int i, len1, len2, len3;
681
682 if (f_v) {
683 cout << "direct_product::lift_generators" << endl;
684 }
685 A1 = SG1->A;
686 A2 = SG2->A;
687 len1 = SG1->gens->len;
688 len2 = SG2->gens->len;
689 len3 = len1 + len2;
690
692 gens->init(A, verbose_level - 2);
693 gens->allocate(len3, verbose_level - 2);
694 Elt1 = NEW_int(A1->elt_size_in_int);
695 Elt2 = NEW_int(A2->elt_size_in_int);
696 Elt3 = NEW_int(A->elt_size_in_int);
697
698 A1->element_one(Elt1, 0 /* verbose_level */);
699 A2->element_one(Elt2, 0 /* verbose_level */);
700 for (i = 0; i < len1; i++) {
701 A1->element_move(SG1->gens->ith(i),
702 Elt3, 0 /* verbose_level */);
703 A2->element_move(Elt2,
704 Elt3 + A1->elt_size_in_int,
705 0 /* verbose_level */);
706 A->element_move(Elt3, gens->ith(i), 0);
707 }
708 for (i = 0; i < len2; i++) {
709 A1->element_move(Elt1, Elt3,
710 0 /* verbose_level */);
711 A2->element_move(SG2->gens->ith(i),
712 Elt3 + A1->elt_size_in_int,
713 0 /* verbose_level */);
714 A->element_move(Elt3, gens->ith(len1 + i), 0);
715 }
716 if (f_v) {
717 cout << "direct_product::lift_generators "
718 "the generators are:" << endl;
719 gens->print_quick(cout);
720 }
721 SG1->group_order(go1);
722 SG2->group_order(go2);
723 D.mult(go1, go2, go3);
725 TRUE /* f_target_go */, go3,
726 gens, SG3,
727 verbose_level);
728 FREE_OBJECT(gens);
729 if (f_v) {
730 cout << "direct_product::lift_generators done" << endl;
731 }
732}
733
734}}}
a catch-all container class for everything related to data structures
bulk storage of group elements in compressed form
void init(int entry_size, int page_length_log, int verbose_level)
domain to compute with objects of type longinteger
Definition: ring_theory.h:240
void mult(longinteger_object &a, longinteger_object &b, longinteger_object &c)
a class to represent arbitrary precision integers
Definition: ring_theory.h:366
a permutation group in a fixed action.
Definition: actions.h:99
void element_one(void *elt, int verbose_level)
Definition: action_cb.cpp:224
void element_move(void *a, void *b, int verbose_level)
Definition: action_cb.cpp:335
void generators_to_strong_generators(int f_target_go, ring_theory::longinteger_object &target_go, data_structures_groups::vector_ge *gens, groups::strong_generators *&Strong_gens, int verbose_level)
void init(actions::action *A, int verbose_level)
Definition: vector_ge.cpp:55
data_structures::page_storage * Elts
Definition: groups.h:73
void init(matrix_group *M1, matrix_group *M2, int verbose_level)
void make_strong_generators_data(int *&data, int &size, int &nb_gens, int verbose_level)
void put_digit(uchar *elt, int f, int i, int d)
void lift_generators(strong_generators *SG1, strong_generators *SG2, actions::action *A, strong_generators *&SG3, int verbose_level)
void element_print_easy(int *Elt, std::ostream &ost)
void make_element(int *Elt, int *data, int verbose_level)
void element_invert(int *A, int *Av, int verbose_level)
void element_mult(int *A, int *B, int *AB, int verbose_level)
void element_move(int *A, int *B, int verbose_level)
long int element_image_of(int *Elt, long int a, int verbose_level)
a matrix group over a finite field in projective, vector space or affine action
Definition: groups.h:318
void GL_print_easy(int *Elt, std::ostream &ost)
void base_and_transversal_length(int base_len, long int *base, int *transversal_length, int verbose_level)
void GL_invert_internal(int *A, int *Ainv, int verbose_level)
void GL_mult(int *A, int *B, int *AB, int verbose_level)
void make_element(int *Elt, int *data, int verbose_level)
void strong_generators_low_level(int *&data, int &size, int &nb_gens, int verbose_level)
long int image_of_element(int *Elt, long int a, int verbose_level)
a strong generating set for a permutation group with respect to a fixed action
Definition: groups.h:1703
data_structures_groups::vector_ge * gens
Definition: groups.h:1708
void group_order(ring_theory::longinteger_object &go)
#define NEW_uchar(n)
Definition: foundations.h:634
#define FREE_uchar(p)
Definition: foundations.h:647
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
unsigned char uchar
Definition: foundations.h:204
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define Lint_vec_print(A, B, C)
Definition: foundations.h:686
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define NEW_int(n)
Definition: foundations.h:625
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define Int_vec_copy(A, B, C)
Definition: foundations.h:693
#define FREE_lint(p)
Definition: foundations.h:642
#define NEW_lint(n)
Definition: foundations.h:628
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
the orbiter library for the classification of combinatorial objects