Orbiter 2022
Combinatorial Objects
orthogonal_indexing.cpp
Go to the documentation of this file.
1/*
2 * orthogonal_indexing.cpp
3 *
4 * Created on: Jan 12, 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 orthogonal_geometry {
21
22
24{
25 F = NULL;
26}
27
29{
30}
31
33{
34 int f_v = (verbose_level >= 1);
35
36 if (f_v) {
37 cout << "orthogonal_indexing::init" << endl;
38 }
40 if (f_v) {
41 cout << "orthogonal_indexing::init done" << endl;
42 }
43}
44
46 int *v, int stride, int epsilon, int k,
47 int c1, int c2, int c3, long int a, int verbose_level)
48{
49 int f_v = (verbose_level >= 1);
50
51 if (f_v) {
52 cout << "orthogonal_indexing::Q_epsilon_unrank" << endl;
53 }
54 if (epsilon == 0) {
55 if (f_v) {
56 cout << "orthogonal_indexing::Q_epsilon_unrank before Q_unrank" << endl;
57 }
58 Q_unrank(v, stride, k, a, verbose_level);
59 if (f_v) {
60 cout << "orthogonal_indexing::Q_epsilon_unrank after Q_unrank" << endl;
61 }
62 }
63 else if (epsilon == 1) {
64 if (f_v) {
65 cout << "orthogonal_indexing::Q_epsilon_unrank before Qplus_unrank" << endl;
66 }
67 Qplus_unrank(v, stride, k, a, verbose_level);
68 if (f_v) {
69 cout << "orthogonal_indexing::Q_epsilon_unrank after Qplus_unrank" << endl;
70 }
71 }
72 else if (epsilon == -1) {
73 if (f_v) {
74 cout << "orthogonal_indexing::Q_epsilon_unrank before Qminus_unrank" << endl;
75 }
76 Qminus_unrank(v, stride, k, a, c1, c2, c3, verbose_level);
77 if (f_v) {
78 cout << "finite_field::Q_epsilon_unrank after Qminus_unrank" << endl;
79 }
80 }
81 else {
82 cout << "orthogonal_indexing epsilon is wrong" << endl;
83 exit(1);
84 }
85 if (f_v) {
86 cout << "orthogonal_indexing::Q_epsilon_unrank done" << endl;
87 }
88}
89
91 int *v, int stride, int epsilon, int k,
92 int c1, int c2, int c3, int verbose_level)
93{
94 int f_v = (verbose_level >= 1);
95 long int a;
96
97 if (f_v) {
98 cout << "orthogonal_indexing::Q_epsilon_rank" << endl;
99 }
100 if (epsilon == 0) {
101 if (f_v) {
102 cout << "orthogonal_indexing::Q_epsilon_rank before Q_rank" << endl;
103 }
104 a = Q_rank(v, stride, k, verbose_level);
105 if (f_v) {
106 cout << "orthogonal_indexing::Q_epsilon_rank after Q_rank" << endl;
107 }
108 }
109 else if (epsilon == 1) {
110 if (f_v) {
111 cout << "orthogonal_indexing::Q_epsilon_rank before Qplus_rank" << endl;
112 }
113 a = Qplus_rank(v, stride, k, verbose_level);
114 if (f_v) {
115 cout << "orthogonal_indexing::Q_epsilon_rank after Qplus_rank" << endl;
116 }
117 }
118 else if (epsilon == -1) {
119 if (f_v) {
120 cout << "orthogonal_indexing::Q_epsilon_rank before Qminus_rank" << endl;
121 }
122 a = Qminus_rank(v, stride, k, c1, c2, c3, verbose_level);
123 if (f_v) {
124 cout << "orthogonal_indexing::Q_epsilon_rank after Qminus_rank" << endl;
125 }
126 }
127 else {
128 cout << "orthogonal_indexing::Q_epsilon_unrank epsilon is wrong" << endl;
129 exit(1);
130 }
131 if (f_v) {
132 cout << "orthogonal_indexing::Q_epsilon_rank done" << endl;
133 }
134 return a;
135}
136
137
138
139
140void orthogonal_indexing::Q_unrank(int *v, int stride, int k, long int a, int verbose_level)
141{
142
143 Q_unrank_directly(v, stride, k, a, verbose_level);
144}
145
146long int orthogonal_indexing::Q_rank(int *v, int stride, int k, int verbose_level)
147{
148 return Q_rank_directly(v, stride, k, verbose_level);
149}
150
151void orthogonal_indexing::Q_unrank_directly(int *v, int stride, int k, long int a, int verbose_level)
152// parabolic quadric
153// k = projective dimension, must be even
154{
155 int n, i, minusone;
156 long int x;
158
159 n = Gg.Witt_index(0, k);
160 x = Gg.nb_pts_Sbar(n, F->q);
161 if (a < x) {
162 v[0] = 0;
163 Sbar_unrank(v + stride, stride, n, a, verbose_level);
164 F->PG_element_normalize_from_front(v + stride, stride, k);
165 return;
166 }
167 a -= x;
168 v[0] = 1;
169 N1_unrank(v + stride, stride, n, a);
170 minusone = F->negate(1);
171 if (minusone != 1) {
172 for (i = 0; i < n; i++) {
173 v[(1 + 2 * i) * stride] =
174 F->mult(v[(1 + 2 * i) * stride], minusone);
175 }
176 }
177}
178
179long int orthogonal_indexing::Q_rank_directly(int *v, int stride, int k, int verbose_level)
180// parabolic quadric
181// k = projective dimension, must be even
182{
183 int n, i;
184 long int x, a, b;
185 int minusone;
187
188 n = Gg.Witt_index(0, k);
189 x = Gg.nb_pts_Sbar(n, F->q);
190 if (v[0] == 0) {
191 Sbar_rank(v + stride, stride, n, a, verbose_level);
192 return a;
193 }
194 a = x;
195 if (v[0] != 1) {
196 F->PG_element_normalize_from_front(v, stride, k + 1);
197 }
198 minusone = F->negate(1);
199 if (minusone != 1) {
200 for (i = 0; i < n; i++) {
201 v[(1 + 2 * i) * stride] =
202 F->mult(v[(1 + 2 * i) * stride], minusone);
203 }
204 }
205 N1_rank(v + stride, stride, n, b);
206 return a + b;
207}
208
209void orthogonal_indexing::Qplus_unrank(int *v, int stride, int k, long int a, int verbose_level)
210// hyperbolic quadric
211// k = projective dimension, must be odd
212{
213 int n;
215
216 n = Gg.Witt_index(1, k);
217 Sbar_unrank(v, stride, n, a, verbose_level);
218}
219
220long int orthogonal_indexing::Qplus_rank(int *v, int stride, int k, int verbose_level)
221// hyperbolic quadric
222// k = projective dimension, must be odd
223{
224 int f_v = (verbose_level >= 1);
225 int n;
226 long int a;
228
229 if (f_v) {
230 cout << "orthogonal_indexing::Qplus_rank" << endl;
231 }
232 n = Gg.Witt_index(1, k);
233 Sbar_rank(v, stride, n, a, verbose_level);
234 return a;
235}
236
238 int stride, int k, long int a,
239 int c1, int c2, int c3, int verbose_level)
240// elliptic quadric
241// k = projective dimension, must be odd
242// the form is
243// \sum_{i=0}^n x_{2i}x_{2i+1} + c1 x_{2n}^2 +
244// c2 x_{2n} x_{2n+1} + c3 x_{2n+1}^2
245{
246 int n, z, minusz, u, vv, w, i;
247 long int x, b, c, x1, x2;
249
250 n = Gg.Witt_index(-1, k);
251 x = Gg.nb_pts_Sbar(n, F->q);
252 if (a < x) {
253 v[2 * n * stride] = 0;
254 v[(2 * n + 1) * stride] = 0;
255 Sbar_unrank(v, stride, n, a, verbose_level);
256 return;
257 }
258 a -= x;
259 x = Gg.nb_pts_N1(n, F->q);
260 b = a / x;
261 c = a % x;
262 // b determines an element on the projective line
263 if (b == 0) {
264 x1 = 1;
265 x2 = 0;
266 }
267 else {
268 b--;
269 x1 = b;
270 x2 = 1;
271 if (b >= F->q) {
272 cout << "orthogonal_indexing::Qminus_unrank "
273 "b >= q, the rank was too big" << endl;
274 exit(1);
275 }
276 }
277 v[2 * n * stride] = x1;
278 v[(2 * n + 1) * stride] = x2;
279 u = F->product3(c1, x1, x1);
280 vv = F->product3(c2, x1, x2);
281 w = F->product3(c3, x2, x2);
282 z = F->add3(u, vv, w);
283 if (z == 0) {
284 cout << "Qminus_unrank z = 0" << endl;
285 cout << "b=" << b << endl;
286 cout << "c1=" << c1 << endl;
287 cout << "c2=" << c2 << endl;
288 cout << "c3=" << c3 << endl;
289 cout << "x1=" << x1 << endl;
290 cout << "x2=" << x2 << endl;
291 cout << "u=c1*x1*x1=" << u << endl;
292 cout << "vv=c2*x1*x2=" << vv << endl;
293 cout << "w=c3*x2*x2=" << w << endl;
294 exit(1);
295 }
296 N1_unrank(v, stride, n, c);
297 minusz = F->negate(z);
298 if (minusz != 1) {
299 for (i = 0; i < n; i++) {
300 v[2 * i * stride] = F->mult(v[2 * i * stride], minusz);
301 }
302 }
303}
304
306 int stride, int k, int c1, int c2, int c3, int verbose_level)
307// elliptic quadric
308// k = projective dimension, must be odd
309// the form is
310// \sum_{i=0}^n x_{2i}x_{2i+1} + c1 x_{2n}^2 +
311// c2 x_{2n} x_{2n+1} + c3 x_{2n+1}^2
312{
313 int n, minusz, minuszv;
314 long int a, b, c, x, x1, x2, u, vv, w, z, i;
316
317 n = Gg.Witt_index(-1, k);
318
319 {
320 int aa;
321 aa = F->Linear_algebra->evaluate_quadratic_form(v, stride, -1, k, c1, c2, c3);
322 if (aa) {
323 cout << "Qminus_rank fatal: the vector "
324 "is not zero under the quadratic form" << endl;
325 cout << "value=" << aa << endl;
326 cout << "stride=" << stride << endl;
327 cout << "k=" << k << endl;
328 cout << "c1=" << c1 << endl;
329 cout << "c2=" << c2 << endl;
330 cout << "c3=" << c3 << endl;
331 Int_vec_print(cout, v, k + 1);
332 cout << endl;
333 exit(1);
334 }
335 }
336 F->PG_element_normalize(v, stride, k + 1);
337 x1 = v[2 * n * stride];
338 x2 = v[(2 * n + 1) * stride];
339 if (x1 == 0 && x2 == 0) {
340 Sbar_rank(v, stride, n, a, verbose_level);
341 return a;
342 }
343 a = Gg.nb_pts_Sbar(n, F->q);
344 // determine b from an element on the projective line
345 if (x1 == 1 && x2 == 0) {
346 b = 0;
347 }
348 else {
349 if (x2 != 1) {
350 cout << "Qminus_rank x2 != 1" << endl;
351 exit(1);
352 }
353 b = x1 + 1;
354 }
355
356 x = Gg.nb_pts_N1(n, F->q);
357 //b = a / x;
358 //c = a % x;
359 u = F->product3(c1, x1, x1);
360 vv = F->product3(c2, x1, x2);
361 w = F->product3(c3, x2, x2);
362 z = F->add3(u, vv, w);
363 if (z == 0) {
364 cout << "Qminus_rank z = 0" << endl;
365 cout << "b=" << b << endl;
366 exit(1);
367 }
368
369 minusz = F->negate(z);
370 minuszv = F->inverse(minusz);
371 if (minuszv != 1) {
372 for (i = 0; i < n; i++) {
373 v[2 * i * stride] = F->mult(v[2 * i * stride], minuszv);
374 }
375 }
376
377 N1_rank(v, stride, n, c);
378 a += b * x + c;
379 return a;
380}
381
382
383
384
385
386// #############################################################################
387// unrank functions for the hyperbolic quadric:
388// #############################################################################
389
390
391
392void orthogonal_indexing::S_unrank(int *v, int stride, int n, long int a)
393{
394 long int l, i, j, x, y, u;
395 int alpha, beta;
397
398 if (n == 1) {
399 if (a < F->q) {
400 v[0 * stride] = a;
401 v[1 * stride] = 0;
402 return;
403 }
404 a -= (F->q - 1);
405 if (a < F->q) {
406 v[0 * stride] = 0;
407 v[1 * stride] = a;
408 return;
409 }
410 else {
411 cout << "orthogonal_indexing::S_unrank "
412 "error in S_unrank n = 1 a = " << a << endl;
413 exit(1);
414 }
415 }
416 else {
417 x = Gg.nb_pts_S(1, F->q);
418 y = Gg.nb_pts_S(n - 1, F->q);
419 l = x * y;
420 if (a < l) {
421 i = a / y;
422 j = a % y;
423 S_unrank(v + (n - 1) * 2 * stride, stride, 1, i);
424 S_unrank(v, stride, n - 1, j);
425 return;
426 }
427 a -= l;
428 //cout << "S_unrank subtracting " << l
429 //<< " to bring a down to " << a << endl;
430 x = Gg.nb_pts_N(1, F->q);
431 y = Gg.nb_pts_N1(n - 1, F->q);
432 l = x * y;
433 if (a < l) {
434 i = a / y;
435 j = a % y;
436 N_unrank(v + (n - 1) * 2 * stride, stride, 1, i);
437 N1_unrank(v, stride, n - 1, j);
438
439 alpha = F->mult(v[2 * (n - 1) * stride],
440 v[(2 * (n - 1) + 1) * stride]);
441 beta = F->negate(alpha);
442 for (u = 0; u < n - 1; u++) {
443 v[2 * u * stride] = F->mult(v[2 * u * stride], beta);
444 }
445 return;
446 }
447 else {
448 cout << "orthogonal_indexing::S_unrank "
449 "error in S_unrank n = " << n << ", a = " << a << endl;
450 exit(1);
451 }
452 }
453}
454
455void orthogonal_indexing::S_rank(int *v, int stride, int n, long int &a)
456{
457 long int l, i, j, x, y, u;
458 int alpha, beta, gamma, delta, epsilon;
460
461 if (n == 1) {
462 if (v[1 * stride] == 0) {
463 a = v[0 * stride];
464 return;
465 }
466 if (v[0 * stride]) {
467 cout << "orthogonal_indexing::S_rank "
468 "error in S_rank v[0] not null" << endl;
469 exit(1);
470 }
471 a = F->q - 1;
472 a += v[1 * stride];
473 }
474 else {
475 x = Gg.nb_pts_S(1, F->q);
476 y = Gg.nb_pts_S(n - 1, F->q);
477 l = x * y;
478 alpha = F->mult(v[2 * (n - 1) * stride],
479 v[(2 * (n - 1) + 1) * stride]);
480 if (alpha == 0) {
481 S_rank(v + (n - 1) * 2 * stride, stride, 1, i);
482 S_rank(v, stride, n - 1, j);
483 a = i * y + j;
484 return;
485 }
486 a = l;
487 x = Gg.nb_pts_N(1, F->q);
488 y = Gg.nb_pts_N1(n - 1, F->q);
489
490 N_rank(v + (n - 1) * 2 * stride, stride, 1, i);
491
492
493 beta = F->negate(alpha);
495 v, stride, n - 1);
496 if (gamma != beta) {
497 cout << "orthogonal_indexing::S_rank "
498 "error in S_rank gamma != beta" << endl;
499 exit(1);
500 }
501 delta = F->inverse(beta);
502 for (u = 0; u < n - 1; u++) {
503 v[2 * u * stride] = F->mult(v[2 * u * stride], delta);
504 }
506 v, stride, n - 1);
507 if (epsilon != 1) {
508 cout << "orthogonal_indexing::S_rank "
509 "error in S_rank epsilon != 1" << endl;
510 exit(1);
511 }
512 N1_rank(v, stride, n - 1, j);
513 a += i * y + j;
514 }
515}
516
517void orthogonal_indexing::N_unrank(int *v, int stride, int n, long int a)
518{
519 long int l, i, j, k, j1, x, y, z, yz, u;
520 int alpha, beta, gamma, delta, epsilon;
522
523 if (n == 1) {
524 x = F->q - 1;
525 y = F->q - 1;
526 l = x * y;
527 if (a < l) {
528 i = a / y;
529 j = a % y;
530 v[0 * stride] = 1 + j;
531 v[1 * stride] = 1 + i;
532 return;
533 }
534 else {
535 cout << "orthogonal_indexing::N_unrank "
536 "error in N_unrank n = 1 a = " << a << endl;
537 exit(1);
538 }
539 }
540 else {
541 x = Gg.nb_pts_S(1, F->q);
542 y = Gg.nb_pts_N(n - 1, F->q);
543 l = x * y;
544 if (a < l) {
545 i = a / y;
546 j = a % y;
547 S_unrank(v + (n - 1) * 2 * stride, stride, 1, i);
548 N_unrank(v, stride, n - 1, j);
549 return;
550 }
551 a -= l;
552 x = Gg.nb_pts_N(1, F->q);
553 y = Gg.nb_pts_S(n - 1, F->q);
554 l = x * y;
555 if (a < l) {
556 i = a / y;
557 j = a % y;
558 N_unrank(v + (n - 1) * 2 * stride, stride, 1, i);
559 S_unrank(v, stride, n - 1, j);
560 return;
561 }
562 a -= l;
563 x = Gg.nb_pts_N(1, F->q);
564 y = (F->q - 2);
565 z = Gg.nb_pts_N1(n - 1, F->q);
566 yz = y * z;
567 l = x * yz;
568 if (a < l) {
569 i = a / yz;
570 j1 = a % yz;
571 j = j1 / z;
572 k = j1 % z;
573 N_unrank(v + (n - 1) * 2 * stride, stride, 1, i);
574 N1_unrank(v, stride, n - 1, k);
575 alpha = F->primitive_element();
576
577 beta = F->power(alpha, j + 1);
578 gamma = F->mult(v[(n - 1) * 2 * stride],
579 v[((n - 1) * 2 + 1) * stride]);
580 delta = F->negate(gamma);
581 epsilon = F->mult(delta, beta);
582 for (u = 0; u < n - 1; u++) {
583 v[2 * u * stride] = F->mult(v[2 * u * stride], epsilon);
584 }
585 return;
586 }
587 else {
588 cout << "orthogonal_indexing::N_unrank "
589 "error in N_unrank n = " << n << ", a = " << a << endl;
590 exit(1);
591 }
592 }
593}
594
595void orthogonal_indexing::N_rank(int *v, int stride, int n, long int &a)
596{
597 long int l, i, j, k, x, y, z, yz, u;
598 int alpha, beta, gamma, delta;
599 int epsilon, gamma2, epsilon_inv;
601
602 if (n == 1) {
603 x = F->q - 1;
604 y = F->q - 1;
605 if (v[0 * stride] == 0 || v[1 * stride] == 0) {
606 cout << "orthogonal_indexing::N_rank "
607 "v[0 * stride] == 0 || "
608 "v[1 * stride] == 0" << endl;
609 exit(1);
610 }
611 j = v[0 * stride] - 1;
612 i = v[1 * stride] - 1;
613 a = i * y + j;
614 }
615 else {
616 gamma = F->mult(v[(n - 1) * 2 * stride],
617 v[((n - 1) * 2 + 1) * stride]);
618 x = Gg.nb_pts_S(1, F->q);
619 y = Gg.nb_pts_N(n - 1, F->q);
620 l = x * y;
621 if (gamma == 0) {
622 S_rank(v + (n - 1) * 2 * stride, stride, 1, i);
623 N_rank(v, stride, n - 1, j);
624 a = i * y + j;
625 return;
626 }
627 a = l;
628 x = Gg.nb_pts_N(1, F->q);
629 y = Gg.nb_pts_S(n - 1, F->q);
630 l = x * y;
632 v, stride, n - 1);
633 if (gamma2 == 0) {
634 N_rank(v + (n - 1) * 2, stride, 1, i);
635 S_rank(v, stride, n - 1, j);
636 a += i * y + j;
637 }
638 a += l;
639
640 x = Gg.nb_pts_N(1, F->q);
641 y = (F->q - 2);
642 z = Gg.nb_pts_N1(n - 1, F->q);
643 yz = y * z;
644 l = x * yz;
645
646 N_rank(v + (n - 1) * 2 * stride, stride, 1, i);
647 alpha = F->primitive_element();
648 delta = F->negate(gamma);
649 for (j = 0; j < F->q - 2; j++) {
650 beta = F->power(alpha, j + 1);
651 epsilon = F->mult(delta, beta);
652 if (epsilon == gamma2) {
653 epsilon_inv = F->inverse(epsilon);
654 for (u = 0; u < n - 1; u++) {
655 v[2 * u * stride] = F->mult(
656 v[2 * u * stride], epsilon_inv);
657 }
658 N1_rank(v, stride, n - 1, k);
659 a += i * yz + j * z + k;
660 return;
661 }
662 }
663 cout << "orthogonal_indexing::N_rank "
664 "error, gamma2 not found" << endl;
665 exit(1);
666 }
667}
668
669void orthogonal_indexing::N1_unrank(int *v, int stride, int n, long int a)
670{
671 long int l, i, j, k, j1, x, y, z, yz, u;
672 int alpha, beta, gamma;
674
675 if (n == 1) {
676 l = F->q - 1;
677 if (a < l) {
678 alpha = a + 1;
679 beta = F->inverse(alpha);
680 //cout << "finite_field::N1_unrank n == 1, a = " << a
681 // << " alpha = " << alpha << " beta = " << beta << endl;
682 v[0 * stride] = alpha;
683 v[1 * stride] = beta;
684 return;
685 }
686 else {
687 cout << "orthogonal_indexing::N1_unrank "
688 "error in N1_unrank n = 1 a = " << a << endl;
689 exit(1);
690 }
691 }
692 else {
693 x = Gg.nb_pts_S(1, F->q);
694 y = Gg.nb_pts_N1(n - 1, F->q);
695 l = x * y;
696 if (a < l) {
697 i = a / y;
698 j = a % y;
699 S_unrank(v + (n - 1) * 2 * stride, stride, 1, i);
700 N1_unrank(v, stride, n - 1, j);
701 return;
702 }
703 a -= l;
704 //cout << "finite_field::N1_unrank subtracting " << l
705 // << " to bring a down to " << a << endl;
706 x = Gg.nb_pts_N1(1, F->q);
707 y = Gg.nb_pts_S(n - 1, F->q);
708 l = x * y;
709 if (a < l) {
710 i = a / y;
711 j = a % y;
712 N1_unrank(v + (n - 1) * 2 * stride, stride, 1, i);
713 S_unrank(v, stride, n - 1, j);
714 return;
715 }
716 a -= l;
717 //cout << "N1_unrank subtracting " << l
718 // << " to bring a down to " << a << endl;
719 x = Gg.nb_pts_N1(1, F->q);
720 y = (F->q - 2); // zero for q = 2
721 z = Gg.nb_pts_N1(n - 1, F->q);
722 yz = y * z;
723 l = x * yz; // zero for q = 2
724 if (a < l) {
725 // the case q = 2 does not appear here any more
726 i = a / yz;
727 j1 = a % yz;
728 j = j1 / z;
729 k = j1 % z;
730
731 //cout << "a = " << a << endl;
732 //cout << "y = " << y << endl;
733 //cout << "z = " << z << endl;
734 //cout << "i = a / yz = " << i << endl;
735 //cout << "j1 = a % yz = " << j1 << endl;
736 //cout << "j = j1 / z = " << j << endl;
737 //cout << "k = j1 % z = " << k << endl;
738
739 N1_unrank(v + (n - 1) * 2 * stride, stride, 1, i);
740
741 //cout << "(" << v[2 * (n - 1) * stride] << ","
742 // << v[(2 * (n - 1) + 1) * stride] << ")" << endl;
743
744 alpha = 2 + j;
745 v[2 * (n - 1) * stride] = F->mult(
746 v[2 * (n - 1) * stride], alpha);
747
748 N1_unrank(v, stride, n - 1, k);
749
750 //int_set_print(v, 2 * (n - 1));
751 //cout << endl;
752
753 beta = F->negate(alpha);
754 gamma = F->add(beta, 1);
755
756 //cout << "alpha = j + 2 = " << alpha << endl;
757 //cout << "beta = - alpha = " << beta << endl;
758 //cout << "gamma = beta + 1 = " << gamma << endl;
759
760 for (u = 0; u < n - 1; u++) {
761 v[2 * u * stride] = F->mult(v[2 * u * stride], gamma);
762 }
763
764 //int_set_print(v, 2 * n);
765 //cout << endl;
766 return;
767 }
768 else {
769 cout << "orthogonal_indexing::N1_unrank "
770 "error in N1_unrank n = " << n << ", a = " << a << endl;
771 exit(1);
772 }
773 }
774}
775
776void orthogonal_indexing::N1_rank(int *v, int stride, int n, long int &a)
777{
778 long int l, i, j, k, x, y, z, yz, u;
779 int alpha, alpha_inv, beta, gamma, gamma2, gamma_inv;
781
782 if (n == 1) {
783 alpha = v[0 * stride];
784 beta = v[1 * stride];
785 if (alpha == 0 || beta == 0) {
786 cout << "orthogonal_indexing::N1_rank "
787 "alpha == 0 || beta == 0" << endl;
788 exit(1);
789 }
790 gamma = F->inverse(alpha);
791 if (gamma != beta) {
792 cout << "orthogonal_indexing::N1_rank "
793 "error in N1_rank gamma = " << gamma
794 << " != beta = " << beta << endl;
795 exit(1);
796 }
797 a = alpha - 1;
798 }
799 else {
800 a = 0;
801 alpha = F->mult(v[2 * (n - 1) * stride],
802 v[(2 * (n - 1) + 1) * stride]);
803 x = Gg.nb_pts_S(1, F->q);
804 y = Gg.nb_pts_N1(n - 1, F->q);
805 l = x * y;
806 if (alpha == 0) {
807 S_rank(v + (n - 1) * 2 * stride, stride, 1, i);
808 N1_rank(v, stride, n - 1, j);
809 a = i * y + j;
810 return;
811 }
812 a += l;
814 v, stride, n - 1);
815 x = Gg.nb_pts_N1(1, F->q);
816 y = Gg.nb_pts_S(n - 1, F->q);
817 l = x * y;
818 if (gamma2 == 0) {
819 N1_rank(v + (n - 1) * 2 * stride, stride, 1, i);
820 S_rank(v, stride, n - 1, j);
821 a += i * y + j;
822 return;
823 }
824 a += l;
825 // the case q = 2 does not appear here any more
826 if (F->q == 2) {
827 cout << "orthogonal_indexing::N1_rank "
828 "the case q=2 should not appear here" << endl;
829 exit(1);
830 }
831
832
833 x = Gg.nb_pts_N1(1, F->q);
834 y = (F->q - 2); // zero for q = 2
835 z = Gg.nb_pts_N1(n - 1, F->q);
836 yz = y * z;
837 l = x * yz; // zero for q = 2
838
839 alpha = F->mult(v[2 * (n - 1) * stride],
840 v[(2 * (n - 1) + 1) * stride]);
841 if (alpha == 0) {
842 cout << "N1_rank alpha == 0" << endl;
843 exit(1);
844 }
845 if (alpha == 1) {
846 cout << "N1_rank alpha == 1" << endl;
847 exit(1);
848 }
849 j = alpha - 2;
850 alpha_inv = F->inverse(alpha);
851 v[2 * (n - 1) * stride] = F->mult(
852 v[2 * (n - 1) * stride], alpha_inv);
853
854 N1_rank(v + (n - 1) * 2 * stride, stride, 1, i);
855
857 v, stride, n - 1);
858 if (gamma2 == 0) {
859 cout << "orthogonal_indexing::N1_rank "
860 "gamma2 == 0" << endl;
861 exit(1);
862 }
863 if (gamma2 == 1) {
864 cout << "orthogonal_indexing::N1_rank "
865 "gamma2 == 1" << endl;
866 exit(1);
867 }
868 gamma_inv = F->inverse(gamma2);
869 for (u = 0; u < n - 1; u++) {
870 v[2 * u * stride] = F->mult(v[2 * u * stride], gamma_inv);
871 }
872 N1_rank(v, stride, n - 1, k);
873
874 a += i * yz + j * z + k;
875
876 }
877}
878
879void orthogonal_indexing::Sbar_unrank(int *v, int stride, int n, long int a, int verbose_level)
880{
881 int f_v = (verbose_level >= 1);
882 long int l, i, j, x, y, u;
883 int alpha, beta;
885
886 if (f_v) {
887 cout << "orthogonal_indexing::Sbar_unrank" << endl;
888 }
889 if (n == 1) {
890 if (a == 0) {
891 v[0 * stride] = 1;
892 v[1 * stride] = 0;
893 return;
894 }
895 if (a == 1) {
896 v[0 * stride] = 0;
897 v[1 * stride] = 1;
898 return;
899 }
900 else {
901 cout << "orthogonal_indexing::Sbar_unrank "
902 "error in Sbar_unrank n = 1 a = " << a << endl;
903 exit(1);
904 }
905 }
906 else {
907 y = Gg.nb_pts_Sbar(n - 1, F->q);
908 l = y;
909 if (a < l) {
910 u = n - 1;
911 v[2 * u * stride] = 0;
912 v[(2 * u + 1) * stride] = 0;
913 Sbar_unrank(v, stride, n - 1, a, verbose_level);
914 return;
915 }
916 if (f_v) {
917 cout << "orthogonal_indexing::Sbar_unrank a = " << a << endl;
918 cout << "orthogonal_indexing::Sbar_unrank l = " << l << endl;
919 }
920 a -= l;
921 if (f_v) {
922 cout << "orthogonal_indexing::Sbar_unrank a = " << a << endl;
923 }
924 //cout << "subtracting " << l << " to bring a to " << a << endl;
925 x = Gg.nb_pts_Sbar(1, F->q);
926 y = Gg.nb_pts_S(n - 1, F->q);
927 //cout << "nb_pts_S(" << n - 1 << ") = " << y << endl;
928 l = x * y;
929 if (a < l) {
930 i = a / y;
931 j = a % y;
932 Sbar_unrank(v + (n - 1) * 2 * stride, stride, 1, i, verbose_level);
933 S_unrank(v, stride, n - 1, j);
934 return;
935 }
936 if (f_v) {
937 cout << "orthogonal_indexing::Sbar_unrank a = " << a << endl;
938 cout << "orthogonal_indexing::Sbar_unrank l = " << l << endl;
939 }
940 a -= l;
941 if (f_v) {
942 cout << "orthogonal_indexing::Sbar_unrank a = " << a << endl;
943 }
944 //cout << "subtracting " << l << " to bring a to " << a << endl;
945 x = Gg.nb_pts_Nbar(1, F->q);
946 y = Gg.nb_pts_N1(n - 1, F->q);
947 //cout << "nb_pts_N1(" << n - 1 << ") = " << y << endl;
948 l = x * y;
949 if (f_v) {
950 cout << "orthogonal_indexing::Sbar_unrank x = " << x << endl;
951 cout << "orthogonal_indexing::Sbar_unrank y = " << y << endl;
952 cout << "orthogonal_indexing::Sbar_unrank l = " << l << endl;
953 }
954 if (a < l) {
955 i = a / y;
956 j = a % y;
957 //cout << "i=" << i << " j=" << j << endl;
958 Nbar_unrank(v + (n - 1) * 2 * stride, stride, 1, i);
959 //cout << "(" << v[2 * (n - 1) * stride] << ","
960 //<< v[(2 * (n - 1) + 1) * stride] << ")" << endl;
961 N1_unrank(v, stride, n - 1, j);
962
963 alpha = F->mult(v[2 * (n - 1) * stride],
964 v[(2 * (n - 1) + 1) * stride]);
965 beta = F->negate(alpha);
966 for (u = 0; u < n - 1; u++) {
967 v[2 * u * stride] = F->mult(v[2 * u * stride], beta);
968 }
969 //int_set_print(v, 2 * n);
970 //cout << endl;
971 return;
972 }
973 else {
974 cout << "orthogonal_indexing::Sbar_unrank "
975 "error in Sbar_unrank n = " << n
976 << ", a = " << a << endl;
977 exit(1);
978 }
979 }
980}
981
982void orthogonal_indexing::Sbar_rank(int *v, int stride, int n, long int &a, int verbose_level)
983{
984 int f_v = (verbose_level >= 1);
985 long int l, i, j, x, y, u;
986 int alpha, beta, beta2, beta_inv;
988
989 if (f_v) {
990 cout << "orthogonal_indexing::Sbar_rank" << endl;
991 }
992 F->PG_element_normalize(v, stride, 2 * n);
993 if (f_v) {
994 cout << "orthogonal_indexing::Sbar_rank: ";
995 if (stride == 1) {
996 Int_vec_print(cout, v, 2 * n);
997 cout << endl;
998 }
999 }
1000 if (n == 1) {
1001 // test for (1,0) or (0,1):
1002 if (v[0 * stride] == 1 && v[1 * stride] == 0) {
1003 a = 0;
1004 return;
1005 }
1006 if (v[0 * stride] == 0 && v[1 * stride] == 1) {
1007 a = 1;
1008 return;
1009 }
1010 else {
1011 cout << "orthogonal_indexing::Sbar_rank "
1012 "error in Sbar_rank n = 1 bad vector" << endl;
1013 if (stride == 1) {
1014 Int_vec_print(cout, v, 2);
1015 }
1016 exit(1);
1017 }
1018 }
1019 else {
1020 a = 0;
1021 // test for leading (0,0):
1022 if (v[2 * (n - 1) * stride] == 0 &&
1023 v[(2 * (n - 1) + 1) * stride] == 0) {
1024 // rank Sbar for the rest:
1025 Sbar_rank(v, stride, n - 1, a, verbose_level);
1026 return;
1027 }
1028 l = Gg.nb_pts_Sbar(n - 1, F->q);
1029 if (f_v) {
1030 cout << "orthogonal_indexing::Sbar_rank not a leading zero, l = " << l << endl;
1031 }
1032 a += l;
1033
1034 // alpha = form value for the top two coefficients:
1035 alpha = F->mult(v[2 * (n - 1) * stride],
1036 v[(2 * (n - 1) + 1) * stride]);
1037 x = Gg.nb_pts_Sbar(1, F->q); // = 2
1038 y = Gg.nb_pts_S(n - 1, F->q);
1039
1040 if (f_v) {
1041 cout << "orthogonal_indexing::Sbar_rank alpha = " << alpha << endl;
1042 cout << "orthogonal_indexing::Sbar_rank x = " << x << endl;
1043 cout << "orthogonal_indexing::Sbar_rank y = " << y << endl;
1044 }
1045
1046 // test for 0 + 0
1047 // (i.e. 0 = alpha = value of the form on
1048 // the top two coefficients
1049 // and 0 for value of the form on the rest):
1050 if (alpha == 0) {
1051 Sbar_rank(v + (n - 1) * 2 * stride, stride, 1, i, verbose_level);
1052 S_rank(v, stride, n - 1, j);
1053 a += i * y + j;
1054 //cout << "i*y+j=" << i << "*" << y << "+" << j << endl;
1055 return;
1056 }
1057
1058 l = x * y;
1059 a += l;
1060 if (f_v) {
1061 cout << "orthogonal_indexing::Sbar_rank l = " << l << endl;
1062 cout << "orthogonal_indexing::Sbar_rank a = " << a << endl;
1063 }
1064
1065 // now it must be n + (-n) for some n \neq 0
1066 // (i.e. n = alpha = value of the form on
1067 // the top two coefficients and
1068 // -n for the value of the form on the rest):
1069 x = Gg.nb_pts_Nbar(1, F->q);
1070 y = Gg.nb_pts_N1(n - 1, F->q);
1071 Nbar_rank(v + (n - 1) * 2 * stride, stride, 1, i);
1072 if (f_v) {
1073 cout << "orthogonal_indexing::Sbar_rank x = " << x << endl;
1074 cout << "orthogonal_indexing::Sbar_rank y = " << y << endl;
1075 cout << "orthogonal_indexing::Sbar_rank i = " << i << endl;
1076 }
1077
1078 beta = F->negate(alpha);
1079 // beta = - alpha
1081 v, stride, n - 1);
1082 // beta2 = value of the quadratic form on the rest
1083 // must be - alpha (otherwise the vector does
1084 // not represent a point in Sbar)
1085 if (beta2 != beta) {
1086 cout << "orthogonal_indexing::Sbar_rank "
1087 "error in Sbar_rank beta2 != beta" << endl;
1088 exit(1);
1089 }
1090 beta_inv = F->inverse(beta);
1091 // divide by beta so that the quadratic form
1092 // on the rest is equal to 1.
1093 for (u = 0; u < n - 1; u++) {
1094 v[2 * u * stride] = F->mult(
1095 v[2 * u * stride], beta_inv);
1096 }
1097 // rank the N1 part:
1098 N1_rank(v, stride, n - 1, j);
1099 if (f_v) {
1100 cout << "orthogonal_indexing::Sbar_rank j = " << j << endl;
1101 }
1102 a += i * y + j;
1103 if (f_v) {
1104 cout << "orthogonal_indexing::Sbar_rank a = " << a << endl;
1105 }
1106 }
1107}
1108
1109void orthogonal_indexing::Nbar_unrank(int *v, int stride, int n, long int a)
1110{
1111 int y, l;
1112
1113 if (n == 1) {
1114 y = F->q - 1;
1115 l = y;
1116 if (a < l) {
1117 v[0 * stride] = 1 + a;
1118 v[1 * stride] = 1;
1119 return;
1120 }
1121 else {
1122 cout << "orthogonal_indexing::Nbar_unrank "
1123 "error in Nbar_unrank n = 1 a = " << a << endl;
1124 exit(1);
1125 }
1126 }
1127 else {
1128 cout << "orthogonal_indexing::Nbar_unrank "
1129 "only defined for n = 1" << endl;
1130 exit(1);
1131 }
1132}
1133
1134void orthogonal_indexing::Nbar_rank(int *v, int stride, int n, long int &a)
1135{
1136 if (n == 1) {
1137 if (v[1 * stride] != 1) {
1138 cout << "error in Nbar_rank n = 1 v[1 * stride] != 1" << endl;
1139 exit(1);
1140 }
1141 if (v[0 * stride] == 0) {
1142 cout << "error in Nbar_rank n = 1 v[0 * stride] == 0" << endl;
1143 exit(1);
1144 }
1145 a = v[0 * stride] - 1;
1146 return;
1147 }
1148 else {
1149 cout << "orthogonal_indexing::Nbar_rank only defined for n = 1" << endl;
1150 exit(1);
1151 }
1152}
1153
1154
1155
1156
1157
1158}}}
1159
1160
1161
1162
various functions related to geometries
Definition: geometry.h:721
int evaluate_quadratic_form(int n, int nb_terms, int *i, int *j, int *coeff, int *x)
long int Q_rank_directly(int *v, int stride, int k, int verbose_level)
void Q_epsilon_unrank(int *v, int stride, int epsilon, int k, int c1, int c2, int c3, long int a, int verbose_level)
void Sbar_rank(int *v, int stride, int n, long int &a, int verbose_level)
void Q_unrank(int *v, int stride, int k, long int a, int verbose_level)
long int Qplus_rank(int *v, int stride, int k, int verbose_level)
void init(field_theory::finite_field *F, int verbose_level)
long int Q_epsilon_rank(int *v, int stride, int epsilon, int k, int c1, int c2, int c3, int verbose_level)
void Qminus_unrank(int *v, int stride, int k, long int a, int c1, int c2, int c3, int verbose_level)
void Qplus_unrank(int *v, int stride, int k, long int a, int verbose_level)
long int Qminus_rank(int *v, int stride, int k, int c1, int c2, int c3, int verbose_level)
long int Q_rank(int *v, int stride, int k, int verbose_level)
void Sbar_unrank(int *v, int stride, int n, long int a, int verbose_level)
void Q_unrank_directly(int *v, int stride, int k, long int a, int verbose_level)
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
the orbiter library for the classification of combinatorial objects