Orbiter 2022
Combinatorial Objects
numerics.cpp
Go to the documentation of this file.
1// numerics.cpp
2//
3// Anton Betten
4//
5// started: February 11, 2018
6
7
8
9
10#include "foundations.h"
11
12
13using namespace std;
14
15
16#define EPSILON 0.01
17
18namespace orbiter {
19namespace layer1_foundations {
20
21
22
23
24
26{
27
28}
29
31{
32
33}
34
35void numerics::vec_print(double *a, int len)
36{
37 int i;
38
39 cout << "(";
40 for (i = 0; i < len; i++) {
41 cout << a[i];
42 if (i < len - 1) {
43 cout << ", ";
44 }
45 }
46 cout << ")";
47}
48
49void numerics::vec_linear_combination1(double c1, double *v1,
50 double *w, int len)
51{
52 int i;
53
54 for (i = 0; i < len; i++) {
55 w[i] = c1 * v1[i];
56 }
57}
58
59void numerics::vec_linear_combination(double c1, double *v1,
60 double c2, double *v2, double *v3, int len)
61{
62 int i;
63
64 for (i = 0; i < len; i++) {
65 v3[i] = c1 * v1[i] + c2 * v2[i];
66 }
67}
68
70 double c1, double *v1,
71 double c2, double *v2,
72 double c3, double *v3,
73 double *w, int len)
74{
75 int i;
76
77 for (i = 0; i < len; i++) {
78 w[i] = c1 * v1[i] + c2 * v2[i] + c3 * v3[i];
79 }
80}
81
82void numerics::vec_add(double *a, double *b, double *c, int len)
83{
84 int i;
85
86 for (i = 0; i < len; i++) {
87 c[i] = a[i] + b[i];
88 }
89}
90
91void numerics::vec_subtract(double *a, double *b, double *c, int len)
92{
93 int i;
94
95 for (i = 0; i < len; i++) {
96 c[i] = a[i] - b[i];
97 }
98}
99
100void numerics::vec_scalar_multiple(double *a, double lambda, int len)
101{
102 int i;
103
104 for (i = 0; i < len; i++) {
105 a[i] *= lambda;
106 }
107}
108
109int numerics::Gauss_elimination(double *A, int m, int n,
110 int *base_cols, int f_complete,
111 int verbose_level)
112{
113 int f_v = (verbose_level >= 1);
114 int f_vv = (verbose_level >= 2);
115 int i, j, k, jj, rank;
116 double a, b, c, f, z;
117 double pivot, pivot_inv;
118
119 if (f_v) {
120 cout << "Gauss_elimination" << endl;
121 }
122
123
124 if (f_vv) {
125 print_system(A, m, n);
126 }
127
128
129
130 i = 0;
131 for (j = 0; j < n; j++) {
132 if (f_vv) {
133 cout << "j=" << j << endl;
134 }
135 /* search for pivot element: */
136 for (k = i; k < m; k++) {
137 if (ABS(A[k * n + j]) > EPSILON) {
138 if (f_vv) {
139 cout << "i=" << i << " pivot found in "
140 << k << "," << j << endl;
141 }
142 // pivot element found:
143 if (k != i) {
144 for (jj = j; jj < n; jj++) {
145 a = A[i * n + jj];
146 A[i * n + jj] = A[k * n + jj];
147 A[k * n + jj] = a;
148 }
149 }
150 break;
151 } // if != 0
152 } // next k
153
154 if (k == m) { // no pivot found
155 if (f_vv) {
156 cout << "no pivot found" << endl;
157 }
158 continue; // increase j, leave i constant
159 }
160
161 if (f_vv) {
162 cout << "row " << i << " pivot in row " << k
163 << " colum " << j << endl;
164 }
165
166 base_cols[i] = j;
167 //if (FALSE) {
168 // cout << "."; cout.flush();
169 // }
170
171 pivot = A[i * n + j];
172 if (f_vv) {
173 cout << "pivot=" << pivot << endl;
174 }
175 pivot_inv = 1. / pivot;
176 if (f_vv) {
177 cout << "pivot=" << pivot << " pivot_inv="
178 << pivot_inv << endl;
179 }
180 // make pivot to 1:
181 for (jj = j; jj < n; jj++) {
182 A[i * n + jj] *= pivot_inv;
183 }
184 if (f_vv) {
185 cout << "pivot=" << pivot << " pivot_inv=" << pivot_inv
186 << " made to one: " << A[i * n + j] << endl;
187 }
188
189 // do the gaussian elimination:
190
191 if (f_vv) {
192 cout << "doing elimination in column " << j
193 << " from row " << i + 1 << " to row "
194 << m - 1 << ":" << endl;
195 }
196 for (k = i + 1; k < m; k++) {
197 if (f_vv) {
198 cout << "k=" << k << endl;
199 }
200 z = A[k * n + j];
201 if (ABS(z) < 0.00000001) {
202 continue;
203 }
204 f = z;
205 f = -1. * f;
206 A[k * n + j] = 0;
207 if (f_vv) {
208 cout << "eliminating row " << k << endl;
209 }
210 for (jj = j + 1; jj < n; jj++) {
211 a = A[i * n + jj];
212 b = A[k * n + jj];
213 // c := b + f * a
214 // = b - z * a if !f_special
215 // b - z * pivot_inv * a if f_special
216 c = f * a;
217 c += b;
218 A[k * n + jj] = c;
219 if (f_vv) {
220 cout << A[k * n + jj] << " ";
221 }
222 }
223 if (f_vv) {
224 print_system(A, m, n);
225 }
226 }
227 i++;
228 } // next j
229 rank = i;
230
231 if (f_vv) {
232 print_system(A, m, n);
233 }
234
235
236 if (f_complete) {
237 if (f_v) {
238 cout << "completing" << endl;
239 }
240 //if (FALSE) {
241 // cout << ";"; cout.flush();
242 // }
243 for (i = rank - 1; i >= 0; i--) {
244 j = base_cols[i];
245 a = A[i * n + j];
246 // do the gaussian elimination in the upper part:
247 for (k = i - 1; k >= 0; k--) {
248 z = A[k * n + j];
249 if (z == 0) {
250 continue;
251 }
252 A[k * n + j] = 0;
253 for (jj = j + 1; jj < n; jj++) {
254 a = A[i * n + jj];
255 b = A[k * n + jj];
256 c = z * a;
257 c = -1. * c;
258 c += b;
259 A[k * n + jj] = c;
260 }
261 } // next k
262 if (f_vv) {
263 print_system(A, m, n);
264 }
265 } // next i
266 }
267 return rank;
268}
269
270void numerics::print_system(double *A, int m, int n)
271{
272 int i, j;
273
274 for (i = 0; i < m; i++) {
275 for (j = 0; j < n; j++) {
276 cout << A[i * n + j] << "\t";
277 }
278 cout << endl;
279 }
280}
281
282void numerics::get_kernel(double *M, int m, int n,
283 int *base_cols, int nb_base_cols,
284 int &kernel_m, int &kernel_n,
285 double *kernel)
286// kernel must point to the appropriate amount of memory!
287// (at least n * (n - nb_base_cols) doubles)
288// m is not used!
289{
290 int r, k, i, j, ii, iii, a, b;
291 int *kcol;
292 double m_one;
293
294 if (kernel == NULL) {
295 cout << "get_kernel kernel == NULL" << endl;
296 exit(1);
297 }
298 m_one = -1.;
299 r = nb_base_cols;
300 k = n - r;
301 kernel_m = n;
302 kernel_n = k;
303
304 kcol = NEW_int(k);
305
306 ii = 0;
307 j = 0;
308 if (j < r) {
309 b = base_cols[j];
310 }
311 else {
312 b = -1;
313 }
314 for (i = 0; i < n; i++) {
315 if (i == b) {
316 j++;
317 if (j < r) {
318 b = base_cols[j];
319 }
320 else {
321 b = -1;
322 }
323 }
324 else {
325 kcol[ii] = i;
326 ii++;
327 }
328 }
329 if (ii != k) {
330 cout << "get_kernel ii != k" << endl;
331 exit(1);
332 }
333 //cout << "kcol = " << kcol << endl;
334 ii = 0;
335 j = 0;
336 if (j < r) {
337 b = base_cols[j];
338 }
339 else {
340 b = -1;
341 }
342 for (i = 0; i < n; i++) {
343 if (i == b) {
344 for (iii = 0; iii < k; iii++) {
345 a = kcol[iii];
346 kernel[i * kernel_n + iii] = M[j * n + a];
347 }
348 j++;
349 if (j < r) {
350 b = base_cols[j];
351 }
352 else {
353 b = -1;
354 }
355 }
356 else {
357 for (iii = 0; iii < k; iii++) {
358 if (iii == ii) {
359 kernel[i * kernel_n + iii] = m_one;
360 }
361 else {
362 kernel[i * kernel_n + iii] = 0.;
363 }
364 }
365 ii++;
366 }
367 }
368 FREE_int(kcol);
369}
370
371int numerics::Null_space(double *M, int m, int n, double *K,
372 int verbose_level)
373// K will be k x n
374// where k is the return value.
375{
376 int f_v = (verbose_level >= 1);
377 int *base_cols;
378 int rk, i, j;
379 int kernel_m, kernel_n;
380 double *Ker;
381
382 if (f_v) {
383 cout << "Null_space" << endl;
384 }
385 Ker = new double [n * n];
386
387 base_cols = NEW_int(n);
388
389 rk = Gauss_elimination(M, m, n, base_cols,
390 TRUE /* f_complete */, 0 /* verbose_level */);
391
392 get_kernel(M, m, n, base_cols, rk /* nb_base_cols */,
393 kernel_m, kernel_n, Ker);
394
395 if (kernel_m != n) {
396 cout << "kernel_m != n" << endl;
397 exit(1);
398 }
399
400 for (i = 0; i < kernel_n; i++) {
401 for (j = 0; j < kernel_m; j++) {
402 K[i * n + j] = Ker[j * kernel_n + i];
403 }
404 }
405
406 FREE_int(base_cols);
407 delete [] Ker;
408
409 if (f_v) {
410 cout << "Null_space done" << endl;
411 }
412 return kernel_n;
413}
414
415void numerics::vec_normalize_from_back(double *v, int len)
416{
417 int i, j;
418 double av;
419
420 for (i = len - 1; i >= 0; i--) {
421 if (ABS(v[i]) > 0.01) {
422 break;
423 }
424 }
425 if (i < 0) {
426 cout << "numerics::vec_normalize_from_back i < 0" << endl;
427 exit(1);
428 }
429 av = 1. / v[i];
430 for (j = 0; j <= i; j++) {
431 v[j] = v[j] * av;
432 }
433}
434
436{
437 int i, j;
438 double av;
439
440 for (i = len - 1; i >= 0; i--) {
441 if (ABS(v[i]) > 0.01) {
442 break;
443 }
444 }
445 if (i < 0) {
446 cout << "numerics::vec_normalize_to_minus_one_from_back i < 0" << endl;
447 exit(1);
448 }
449 av = -1. / v[i];
450 for (j = 0; j <= i; j++) {
451 v[j] = v[j] * av;
452 }
453}
454
455#define EPS 0.001
456
457
458int numerics::triangular_prism(double *P1, double *P2, double *P3,
459 double *abc3, double *angles3, double *T3,
460 int verbose_level)
461{
462 int f_v = (verbose_level >= 1);
463 int f_vv = (verbose_level >= 2);
464 int i;
465 double P4[3];
466 double P5[3];
467 double P6[3];
468 double P7[3];
469 double P8[3];
470 double P9[3];
471 double T[3]; // translation vector
472 double phi;
473 double Rz[9];
474 double psi;
475 double Ry[9];
476 double chi;
477 double Rx[9];
478
479 if (f_v) {
480 cout << "numerics::triangular_prism" << endl;
481 }
482
483
484 if (f_vv) {
485 cout << "P1=";
486 vec_print(cout, P1, 3);
487 cout << endl;
488 cout << "P2=";
489 vec_print(cout, P2, 3);
490 cout << endl;
491 cout << "P3=";
492 vec_print(cout, P3, 3);
493 cout << endl;
494 }
495
496 vec_copy(P1, T, 3);
497 for (i = 0; i < 3; i++) {
498 P2[i] -= T[i];
499 }
500 for (i = 0; i < 3; i++) {
501 P3[i] -= T[i];
502 }
503
504 if (f_vv) {
505 cout << "after translation:" << endl;
506 cout << "P2=";
507 vec_print(cout, P2, 3);
508 cout << endl;
509 cout << "P3=";
510 vec_print(cout, P3, 3);
511 cout << endl;
512 }
513
514
515 if (f_vv) {
516 cout << "next, we make the y-coordinate of the first point "
517 "disappear by turning around the z-axis:" << endl;
518 }
519 phi = atan_xy(P2[0], P2[1]); // (x, y)
520 if (f_vv) {
521 cout << "phi=" << rad2deg(phi) << endl;
522 }
523 make_Rz(Rz, -1 * phi);
524 if (f_vv) {
525 cout << "Rz=" << endl;
526 print_matrix(Rz);
527 }
528
529 mult_matrix(P2, Rz, P4);
530 mult_matrix(P3, Rz, P5);
531 if (f_vv) {
532 cout << "after rotation Rz by an angle of -1 * "
533 << rad2deg(phi) << ":" << endl;
534 cout << "P4=";
535 vec_print(cout, P4, 3);
536 cout << endl;
537 cout << "P5=";
538 vec_print(cout, P5, 3);
539 cout << endl;
540 }
541 if (ABS(P4[1]) > EPS) {
542 cout << "something is wrong in step 1, "
543 "the y-coordinate is too big" << endl;
544 return FALSE;
545 }
546
547
548 if (f_vv) {
549 cout << "next, we make the z-coordinate of the "
550 "first point disappear by turning around the y-axis:" << endl;
551 }
552 psi = atan_xy(P4[0], P4[2]); // (x,z)
553 if (f_vv) {
554 cout << "psi=" << rad2deg(psi) << endl;
555 }
556
557 make_Ry(Ry, psi);
558 if (f_vv) {
559 cout << "Ry=" << endl;
560 print_matrix(Ry);
561 }
562
563 mult_matrix(P4, Ry, P6);
564 mult_matrix(P5, Ry, P7);
565 if (f_vv) {
566 cout << "after rotation Ry by an angle of "
567 << rad2deg(psi) << ":" << endl;
568 cout << "P6=";
569 vec_print(cout, P6, 3);
570 cout << endl;
571 cout << "P7=";
572 vec_print(cout, P7, 3);
573 cout << endl;
574 }
575 if (ABS(P6[2]) > EPS) {
576 cout << "something is wrong in step 2, "
577 "the z-coordinate is too big" << endl;
578 return FALSE;
579 }
580
581 if (f_vv) {
582 cout << "next, we move the plane determined by the second "
583 "point into the xz plane by turning around the x-axis:"
584 << endl;
585 }
586 chi = atan_xy(P7[2], P7[1]); // (z,y)
587 if (f_vv) {
588 cout << "chi=" << rad2deg(chi) << endl;
589 }
590
591 make_Rx(Rx, chi);
592 if (f_vv) {
593 cout << "Rx=" << endl;
594 print_matrix(Rx);
595 }
596
597 mult_matrix(P6, Rx, P8);
598 mult_matrix(P7, Rx, P9);
599 if (f_vv) {
600 cout << "after rotation Rx by an angle of "
601 << rad2deg(chi) << ":" << endl;
602 cout << "P8=";
603 vec_print(cout, P8, 3);
604 cout << endl;
605 cout << "P9=";
606 vec_print(cout, P9, 3);
607 cout << endl;
608 }
609 if (ABS(P9[1]) > EPS) {
610 cout << "something is wrong in step 3, "
611 "the y-coordinate is too big" << endl;
612 return FALSE;
613 }
614
615
616 for (i = 0; i < 3; i++) {
617 T3[i] = T[i];
618 }
619 angles3[0] = -chi;
620 angles3[1] = -psi;
621 angles3[2] = phi;
622 abc3[0] = P8[0];
623 abc3[1] = P9[0];
624 abc3[2] = P9[2];
625 if (f_v) {
626 cout << "numerics::triangular_prism done" << endl;
627 }
628 return TRUE;
629}
630
631int numerics::general_prism(double *Pts, int nb_pts, double *Pts_xy,
632 double *abc3, double *angles3, double *T3,
633 int verbose_level)
634{
635 int f_v = (verbose_level >= 1);
636 int f_vv = (verbose_level >= 2);
637 int i, h;
638 double *Moved_pts1;
639 double *Moved_pts2;
640 double *Moved_pts3;
641 double *Moved_pts4;
642 double *P1, *P2, *P3;
643 double P4[3];
644 double P5[3];
645 double P6[3];
646 double P7[3];
647 double P8[3];
648 double P9[3];
649 double T[3]; // translation vector
650 double phi;
651 double Rz[9];
652 double psi;
653 double Ry[9];
654 double chi;
655 double Rx[9];
656
657 if (f_v) {
658 cout << "general_prism" << endl;
659 }
660
661 P1 = Pts;
662 P2 = Pts + 3;
663 P3 = Pts + 6;
664 Moved_pts1 = new double[nb_pts * 3];
665 Moved_pts2 = new double[nb_pts * 3];
666 Moved_pts3 = new double[nb_pts * 3];
667 Moved_pts4 = new double[nb_pts * 3];
668
669 if (f_vv) {
670 cout << "P1=";
671 vec_print(cout, P1, 3);
672 cout << endl;
673 cout << "P2=";
674 vec_print(cout, P2, 3);
675 cout << endl;
676 cout << "P3=";
677 vec_print(cout, P3, 3);
678 cout << endl;
679 }
680
681 vec_copy(P1, T, 3);
682 for (h = 0; h < nb_pts; h++) {
683 for (i = 0; i < 3; i++) {
684 Moved_pts1[h * 3 + i] = Pts[h * 3 + i] - T[i];
685 }
686 }
687 // this must come after:
688 for (i = 0; i < 3; i++) {
689 P2[i] -= T[i];
690 }
691 for (i = 0; i < 3; i++) {
692 P3[i] -= T[i];
693 }
694
695 if (f_vv) {
696 cout << "after translation:" << endl;
697 cout << "P2=";
698 vec_print(cout, P2, 3);
699 cout << endl;
700 cout << "P3=";
701 vec_print(cout, P3, 3);
702 cout << endl;
703 }
704
705
706 if (f_vv) {
707 cout << "next, we make the y-coordinate of the first point "
708 "disappear by turning around the z-axis:" << endl;
709 }
710 phi = atan_xy(P2[0], P2[1]); // (x, y)
711 if (f_vv) {
712 cout << "phi=" << rad2deg(phi) << endl;
713 }
714 make_Rz(Rz, -1 * phi);
715 if (f_vv) {
716 cout << "Rz=" << endl;
717 print_matrix(Rz);
718 }
719
720 mult_matrix(P2, Rz, P4);
721 mult_matrix(P3, Rz, P5);
722 for (h = 0; h < nb_pts; h++) {
723 mult_matrix(Moved_pts1 + h * 3, Rz, Moved_pts2 + h * 3);
724 }
725 if (f_vv) {
726 cout << "after rotation Rz by an angle of -1 * "
727 << rad2deg(phi) << ":" << endl;
728 cout << "P4=";
729 vec_print(cout, P4, 3);
730 cout << endl;
731 cout << "P5=";
732 vec_print(cout, P5, 3);
733 cout << endl;
734 }
735 if (ABS(P4[1]) > EPS) {
736 cout << "something is wrong in step 1, the y-coordinate "
737 "is too big" << endl;
738 return FALSE;
739 }
740
741
742 if (f_vv) {
743 cout << "next, we make the z-coordinate of the first "
744 "point disappear by turning around the y-axis:" << endl;
745 }
746 psi = atan_xy(P4[0], P4[2]); // (x,z)
747 if (f_vv) {
748 cout << "psi=" << rad2deg(psi) << endl;
749 }
750
751 make_Ry(Ry, psi);
752 if (f_vv) {
753 cout << "Ry=" << endl;
754 print_matrix(Ry);
755 }
756
757 mult_matrix(P4, Ry, P6);
758 mult_matrix(P5, Ry, P7);
759 for (h = 0; h < nb_pts; h++) {
760 mult_matrix(Moved_pts2 + h * 3, Ry, Moved_pts3 + h * 3);
761 }
762 if (f_vv) {
763 cout << "after rotation Ry by an angle of "
764 << rad2deg(psi) << ":" << endl;
765 cout << "P6=";
766 vec_print(cout, P6, 3);
767 cout << endl;
768 cout << "P7=";
769 vec_print(cout, P7, 3);
770 cout << endl;
771 }
772 if (ABS(P6[2]) > EPS) {
773 cout << "something is wrong in step 2, the z-coordinate "
774 "is too big" << endl;
775 return FALSE;
776 }
777
778 if (f_vv) {
779 cout << "next, we move the plane determined by the second "
780 "point into the xz plane by turning around the x-axis:"
781 << endl;
782 }
783 chi = atan_xy(P7[2], P7[1]); // (z,y)
784 if (f_vv) {
785 cout << "chi=" << rad2deg(chi) << endl;
786 }
787
788 make_Rx(Rx, chi);
789 if (f_vv) {
790 cout << "Rx=" << endl;
791 print_matrix(Rx);
792 }
793
794 mult_matrix(P6, Rx, P8);
795 mult_matrix(P7, Rx, P9);
796 for (h = 0; h < nb_pts; h++) {
797 mult_matrix(Moved_pts3 + h * 3, Rx, Moved_pts4 + h * 3);
798 }
799 if (f_vv) {
800 cout << "after rotation Rx by an angle of "
801 << rad2deg(chi) << ":" << endl;
802 cout << "P8=";
803 vec_print(cout, P8, 3);
804 cout << endl;
805 cout << "P9=";
806 vec_print(cout, P9, 3);
807 cout << endl;
808 }
809 if (ABS(P9[1]) > EPS) {
810 cout << "something is wrong in step 3, the y-coordinate "
811 "is too big" << endl;
812 return FALSE;
813 }
814
815
816 for (i = 0; i < 3; i++) {
817 T3[i] = T[i];
818 }
819 angles3[0] = -chi;
820 angles3[1] = -psi;
821 angles3[2] = phi;
822 abc3[0] = P8[0];
823 abc3[1] = P9[0];
824 abc3[2] = P9[2];
825 for (h = 0; h < nb_pts; h++) {
826 Pts_xy[2 * h + 0] = Moved_pts4[h * 3 + 0];
827 Pts_xy[2 * h + 1] = Moved_pts4[h * 3 + 2];
828 }
829
830 delete [] Moved_pts1;
831 delete [] Moved_pts2;
832 delete [] Moved_pts3;
833 delete [] Moved_pts4;
834
835 if (f_v) {
836 cout << "numerics::general_prism done" << endl;
837 }
838 return TRUE;
839}
840
841void numerics::mult_matrix(double *v, double *R, double *vR)
842{
843 int i, j;
844 double c;
845
846 for (j = 0; j < 3; j++) {
847 c = 0;
848 for (i = 0; i < 3; i++) {
849 c += v[i] * R[i * 3 + j];
850 }
851 vR[j] = c;
852 }
853}
854
856 double *A, double *B, double *C, int m, int n, int o)
857// A is m x n, B is n x o, C is m x o
858{
859 int i, j, h;
860 double c;
861
862 for (i = 0; i < m; i++) {
863 for (j = 0; j < o; j++) {
864 c = 0;
865 for (h = 0; h < n; h++) {
866 c += A[i * n + h] * B[h * o + j];
867 }
868 C[i * o + j] = c;
869 }
870 }
871}
872
874{
875 int i, j;
876
877 for (i = 0; i < 3; i++) {
878 for (j = 0; j < 3; j++) {
879 cout << R[i * 3 + j] << " ";
880 }
881 cout << endl;
882 }
883}
884
885void numerics::make_Rz(double *R, double phi)
886{
887 double c, s;
888 int i;
889
890 c = cos(phi);
891 s = sin(phi);
892 for (i = 0; i < 9; i++) {
893 R[i] = 0.;
894 }
895 R[2 * 3 + 2] = 1.;
896 R[0 * 3 + 0] = c;
897 R[0 * 3 + 1] = s;
898 R[1 * 3 + 0] = -1. * s;
899 R[1 * 3 + 1] = c;
900}
901
902void numerics::make_Ry(double *R, double psi)
903{
904 double c, s;
905 int i;
906
907 c = cos(psi);
908 s = sin(psi);
909 for (i = 0; i < 9; i++) {
910 R[i] = 0.;
911 }
912 R[1 * 3 + 1] = 1;
913
914 R[0 * 3 + 0] = c;
915 R[0 * 3 + 2] = -1 * s;
916 R[2 * 3 + 0] = s;
917 R[2 * 3 + 2] = c;
918}
919
920void numerics::make_Rx(double *R, double chi)
921{
922 double c, s;
923 int i;
924
925 c = cos(chi);
926 s = sin(chi);
927 for (i = 0; i < 9; i++) {
928 R[i] = 0.;
929 }
930 R[0 * 3 + 0] = 1;
931
932 R[1 * 3 + 1] = c;
933 R[1 * 3 + 2] = s;
934 R[2 * 3 + 1] = -1 * s;
935 R[2 * 3 + 2] = c;
936}
937
938double numerics::atan_xy(double x, double y)
939{
940 double phi;
941
942 //cout << "atan x=" << x << " y=" << y << endl;
943 if (ABS(x) < 0.00001) {
944 if (y > 0) {
945 phi = M_PI * 0.5;
946 }
947 else {
948 phi = M_PI * -0.5;
949 }
950 }
951 else {
952 if (x < 0) {
953 x = -x;
954 y = -y;
955 phi = atan(y / x) + M_PI;
956 }
957 else {
958 phi = atan(y / x);
959 }
960 }
961 //cout << "angle = " << rad2deg(phi) << " degrees" << endl;
962 return phi;
963}
964
965double numerics::dot_product(double *u, double *v, int len)
966{
967 double d;
968 int i;
969
970 d = 0;
971 for (i = 0; i < len; i++) {
972 d += u[i] * v[i];
973 }
974 return d;
975}
976
977void numerics::cross_product(double *u, double *v, double *n)
978{
979 n[0] = u[1] * v[2] - v[1] * u[2];
980 n[1] = u[2] * v[0] - u[0] * v[2];
981 n[2] = u[0] * v[1] - u[1] * v[0];
982}
983
984double numerics::distance_euclidean(double *x, double *y, int len)
985{
986 double d, a;
987 int i;
988
989 d = 0;
990 for (i = 0; i < len; i++) {
991 a = y[i] - x[i];
992 d += a * a;
993 }
994 d = sqrt(d);
995 return d;
996}
997
998double numerics::distance_from_origin(double x1, double x2, double x3)
999{
1000 double d;
1001
1002 d = sqrt(x1 * x1 + x2 * x2 + x3 * x3);
1003 return d;
1004}
1005
1006double numerics::distance_from_origin(double *x, int len)
1007{
1008 double d;
1009 int i;
1010
1011 d = 0;
1012 for (i = 0; i < len; i++) {
1013 d += x[i] * x[i];
1014 }
1015 d = sqrt(d);
1016 return d;
1017}
1018
1019void numerics::make_unit_vector(double *v, int len)
1020{
1021 double d, dv;
1022
1023 d = distance_from_origin(v, len);
1024 if (ABS(d) < 0.00001) {
1025 cout << "make_unit_vector ABS(d) < 0.00001" << endl;
1026 exit(1);
1027 }
1028 dv = 1. / d;
1029 vec_scalar_multiple(v, dv, len);
1030}
1031
1032void numerics::center_of_mass(double *Pts, int len,
1033 int *Pt_idx, int nb_pts, double *c)
1034{
1035 int i, h, idx;
1036 double a;
1037
1038 for (i = 0; i < len; i++) {
1039 c[i] = 0.;
1040 }
1041 for (h = 0; h < nb_pts; h++) {
1042 idx = Pt_idx[h];
1043 for (i = 0; i < len; i++) {
1044 c[i] += Pts[idx * len + i];
1045 }
1046 }
1047 a = 1. / nb_pts;
1048 vec_scalar_multiple(c, a, len);
1049}
1050
1052 double *p1, double *p2, double *p3,
1053 double *n, double &d)
1054{
1055 int i;
1056 double a, b;
1057 double u[3];
1058 double v[3];
1059
1060 vec_subtract(p2, p1, u, 3); // u = p2 - p1
1061 vec_subtract(p3, p1, v, 3); // v = p3 - p1
1062
1063#if 0
1064 cout << "u=" << endl;
1065 print_system(u, 1, 3);
1066 cout << endl;
1067 cout << "v=" << endl;
1068 print_system(v, 1, 3);
1069 cout << endl;
1070#endif
1071
1072 cross_product(u, v, n);
1073
1074#if 0
1075 cout << "n=" << endl;
1076 print_system(n, 1, 3);
1077 cout << endl;
1078#endif
1079
1080 a = distance_from_origin(n[0], n[1], n[2]);
1081 if (ABS(a) < 0.00001) {
1082 cout << "plane_through_three_points ABS(a) < 0.00001" << endl;
1083 exit(1);
1084 }
1085 b = 1. / a;
1086 for (i = 0; i < 3; i++) {
1087 n[i] *= b;
1088 }
1089
1090#if 0
1091 cout << "n unit=" << endl;
1092 print_system(n, 1, 3);
1093 cout << endl;
1094#endif
1095
1096 d = dot_product(p1, n, 3);
1097}
1098
1100 double *from,
1101 double *A, double *Av, int verbose_level)
1102{
1103 int f_v = (verbose_level >= 1);
1104 int i, i0, i1, j;
1105 double d, a;
1106
1107 if (f_v) {
1108 cout << "numerics::orthogonal_transformation_from_point_"
1109 "to_basis_vector" << endl;
1110 }
1111 vec_copy(from, Av, 3);
1112 a = 0.;
1113 i0 = -1;
1114 for (i = 0; i < 3; i++) {
1115 if (ABS(Av[i]) > a) {
1116 i0 = i;
1117 a = ABS(Av[i]);
1118 }
1119 }
1120 if (i0 == -1) {
1121 cout << "i0 == -1" << endl;
1122 exit(1);
1123 }
1124 if (i0 == 0) {
1125 i1 = 1;
1126 }
1127 else if (i0 == 1) {
1128 i1 = 2;
1129 }
1130 else {
1131 i1 = 0;
1132 }
1133 for (i = 0; i < 3; i++) {
1134 Av[3 + i] = 0.;
1135 }
1136 Av[3 + i1] = -Av[i0];
1137 Av[3 + i0] = Av[i1];
1138 // now the dot product of the first row and
1139 // the secon row is zero.
1140 d = dot_product(Av, Av + 3, 3);
1141 if (ABS(d) > 0.01) {
1142 cout << "dot product between first and second "
1143 "row of Av is not zero" << endl;
1144 exit(1);
1145 }
1146 cross_product(Av, Av + 3, Av + 6);
1147 d = dot_product(Av, Av + 6, 3);
1148 if (ABS(d) > 0.01) {
1149 cout << "dot product between first and third "
1150 "row of Av is not zero" << endl;
1151 exit(1);
1152 }
1153 d = dot_product(Av + 3, Av + 6, 3);
1154 if (ABS(d) > 0.01) {
1155 cout << "dot product between second and third "
1156 "row of Av is not zero" << endl;
1157 exit(1);
1158 }
1159 make_unit_vector(Av, 3);
1160 make_unit_vector(Av + 3, 3);
1161 make_unit_vector(Av + 6, 3);
1162
1163 // make A the transpose of Av.
1164 // for orthonormal matrices, the inverse is the transpose.
1165 for (i = 0; i < 3; i++) {
1166 for (j = 0; j < 3; j++) {
1167 A[j * 3 + i] = Av[i * 3 + j];
1168 }
1169 }
1170
1171 if (f_v) {
1172 cout << "numerics::orthogonal_transformation_from_point_"
1173 "to_basis_vector done" << endl;
1174 }
1175}
1176
1177void numerics::output_double(double a, ostream &ost)
1178{
1179 if (ABS(a) < 0.0001) {
1180 ost << 0;
1181 }
1182 else {
1183 ost << a;
1184 }
1185}
1186
1187void numerics::mult_matrix_4x4(double *v, double *R, double *vR)
1188{
1189 int i, j;
1190 double c;
1191
1192 for (j = 0; j < 4; j++) {
1193 c = 0;
1194 for (i = 0; i < 4; i++) {
1195 c += v[i] * R[i * 4 + j];
1196 }
1197 vR[j] = c;
1198 }
1199}
1200
1201
1202void numerics::transpose_matrix_4x4(double *A, double *At)
1203{
1204 int i, j;
1205
1206 for (i = 0; i < 4; i++) {
1207 for (j = 0; j < 4; j++) {
1208 At[i * 4 + j] = A[j * 4 + i];
1209 }
1210 }
1211}
1212
1213void numerics::transpose_matrix_nxn(double *A, double *At, int n)
1214{
1215 int i, j;
1216
1217 for (i = 0; i < n; i++) {
1218 for (j = 0; j < n; j++) {
1219 At[i * n + j] = A[j * n + i];
1220 }
1221 }
1222}
1223
1225 double *coeff_in, double *coeff_out,
1226 double *A4_inv, int verbose_level)
1227// uses povray ordering of monomials
1228// 1: x^2
1229// 2: xy
1230// 3: xz
1231// 4: x
1232// 5: y^2
1233// 6: yz
1234// 7: y
1235// 8: z^2
1236// 9: z
1237// 10: 1
1238{
1239 int f_v = (verbose_level >= 1);
1240 int Variables[] = {
1241 0,0,
1242 0,1,
1243 0,2,
1244 0,3,
1245 1,1,
1246 1,2,
1247 1,3,
1248 2,2,
1249 2,3,
1250 3,3
1251 };
1252 int Affine_to_monomial[16];
1253 int *V;
1254 int nb_monomials = 10;
1255 int degree = 2;
1256 int n = 4;
1257 double coeff2[10];
1258 double coeff3[10];
1259 double b, c;
1260 int h, i, j, a, nb_affine, idx;
1261 int A[2];
1262 int v[4];
1266
1267 if (f_v) {
1268 cout << "substitute_quadric_linear" << endl;
1269 }
1270
1271 nb_affine = NT.i_power_j(n, degree);
1272
1273 for (i = 0; i < nb_affine; i++) {
1274 Gg.AG_element_unrank(n /* q */, A, 1, degree, i);
1275 Int_vec_zero(v, n);
1276 for (j = 0; j < degree; j++) {
1277 a = A[j];
1278 v[a]++;
1279 }
1280 for (idx = 0; idx < 10; idx++) {
1281 if (Sorting.int_vec_compare(v, Variables + idx * 2, 2) == 0) {
1282 break;
1283 }
1284 }
1285 if (idx == 10) {
1286 cout << "could not determine Affine_to_monomial" << endl;
1287 exit(1);
1288 }
1289 Affine_to_monomial[i] = idx;
1290 }
1291
1292
1293 for (i = 0; i < nb_monomials; i++) {
1294 coeff3[i] = 0.;
1295 }
1296 for (h = 0; h < nb_monomials; h++) {
1297 c = coeff_in[h];
1298 if (c == 0) {
1299 continue;
1300 }
1301
1302 V = Variables + h * degree;
1303 // a list of the indices of the variables
1304 // which appear in the monomial
1305 // (possibly with repeats)
1306 // Example: the monomial x_0^3 becomes 0,0,0
1307
1308
1309 for (i = 0; i < nb_monomials; i++) {
1310 coeff2[i] = 0.;
1311 }
1312 for (a = 0; a < nb_affine; a++) {
1313
1314 Gg.AG_element_unrank(n /* q */, A, 1, degree, a);
1315 // sequence of length degree
1316 // over the alphabet 0,...,n-1.
1317 b = 1.;
1318 for (j = 0; j < degree; j++) {
1319 //factors[j] = Mtx_inv[V[j] * n + A[j]];
1320 b *= A4_inv[A[j] * n + V[j]];
1321 }
1322 idx = Affine_to_monomial[a];
1323
1324 coeff2[idx] += b;
1325 }
1326 for (j = 0; j < nb_monomials; j++) {
1327 coeff2[j] *= c;
1328 }
1329
1330 for (j = 0; j < nb_monomials; j++) {
1331 coeff3[j] += coeff2[j];
1332 }
1333 }
1334
1335 for (j = 0; j < nb_monomials; j++) {
1336 coeff_out[j] = coeff3[j];
1337 }
1338
1339
1340 if (f_v) {
1341 cout << "substitute_quadric_linear done" << endl;
1342 }
1343}
1344
1346 double *coeff_in, double *coeff_out,
1347 double *A4_inv, int verbose_level)
1348// uses povray ordering of monomials
1349// http://www.povray.org/documentation/view/3.6.1/298/
1350// 1: x^3
1351// 2: x^2y
1352// 3: x^2z
1353// 4: x^2
1354// 5: xy^2
1355// 6: xyz
1356// 7: xy
1357// 8: xz^2
1358// 9: xz
1359// 10: x
1360// 11: y^3
1361// 12: y^2z
1362// 13: y^2
1363// 14: yz^2
1364// 15: yz
1365// 16: y
1366// 17: z^3
1367// 18: z^2
1368// 19: z
1369// 20: 1
1370{
1371 int f_v = (verbose_level >= 1);
1372 int Variables[] = {
1373 0,0,0,
1374 0,0,1,
1375 0,0,2,
1376 0,0,3,
1377 0,1,1,
1378 0,1,2,
1379 0,1,3,
1380 0,2,2,
1381 0,2,3,
1382 0,3,3,
1383 1,1,1,
1384 1,1,2,
1385 1,1,3,
1386 1,2,2,
1387 1,2,3,
1388 1,3,3,
1389 2,2,2,
1390 2,2,3,
1391 2,3,3,
1392 3,3,3,
1393 };
1394 int *Monomials;
1395 int Affine_to_monomial[64]; // n^degree
1396 int *V;
1397 int nb_monomials = 20;
1398 int degree = 3;
1399 int n = 4; // number of variables
1400 double coeff2[20];
1401 double coeff3[20];
1402 double b, c;
1403 int h, i, j, a, nb_affine, idx;
1404 int A[3];
1405 int v[4];
1409
1410 if (f_v) {
1411 cout << "numerics::substitute_cubic_linear_using_povray_ordering" << endl;
1412 }
1413
1414 nb_affine = NT.i_power_j(n, degree);
1415
1416
1417 if (FALSE) {
1418 cout << "Variables:" << endl;
1420 }
1421 Monomials = NEW_int(nb_monomials * n);
1422 Int_vec_zero(Monomials, nb_monomials * n);
1423 for (i = 0; i < nb_monomials; i++) {
1424 for (j = 0; j < degree; j++) {
1425 a = Variables[i * degree + j];
1426 Monomials[i * n + a]++;
1427 }
1428 }
1429 if (FALSE) {
1430 cout << "Monomials:" << endl;
1431 orbiter_kernel_system::Orbiter->Int_vec->matrix_print(Monomials, nb_monomials, n);
1432 }
1433
1434 for (i = 0; i < nb_affine; i++) {
1435 Gg.AG_element_unrank(n /* q */, A, 1, degree, i);
1436 Int_vec_zero(v, n);
1437 for (j = 0; j < degree; j++) {
1438 a = A[j];
1439 v[a]++;
1440 }
1441 for (idx = 0; idx < nb_monomials; idx++) {
1442 if (Sorting.int_vec_compare(v, Monomials + idx * n, n) == 0) {
1443 break;
1444 }
1445 }
1446 if (idx == nb_monomials) {
1447 cout << "could not determine Affine_to_monomial" << endl;
1448 cout << "Monomials:" << endl;
1449 orbiter_kernel_system::Orbiter->Int_vec->matrix_print(Monomials, nb_monomials, n);
1450 cout << "v=";
1451 Int_vec_print(cout, v, n);
1452 exit(1);
1453 }
1454 Affine_to_monomial[i] = idx;
1455 }
1456
1457 if (FALSE) {
1458 cout << "Affine_to_monomial:";
1459 Int_vec_print(cout, Affine_to_monomial, nb_affine);
1460 cout << endl;
1461 }
1462
1463
1464 for (i = 0; i < nb_monomials; i++) {
1465 coeff3[i] = 0.;
1466 }
1467 for (h = 0; h < nb_monomials; h++) {
1468 c = coeff_in[h];
1469 if (c == 0) {
1470 continue;
1471 }
1472
1473 V = Variables + h * degree;
1474 // a list of the indices of the variables
1475 // which appear in the monomial
1476 // (possibly with repeats)
1477 // Example: the monomial x_0^3 becomes 0,0,0
1478
1479
1480 for (i = 0; i < nb_monomials; i++) {
1481 coeff2[i] = 0.;
1482 }
1483 for (a = 0; a < nb_affine; a++) {
1484
1485 Gg.AG_element_unrank(n /* q */, A, 1, degree, a);
1486 // sequence of length degree
1487 // over the alphabet 0,...,n-1.
1488 b = 1.;
1489 for (j = 0; j < degree; j++) {
1490 //factors[j] = Mtx_inv[V[j] * n + A[j]];
1491 b *= A4_inv[A[j] * n + V[j]];
1492 }
1493 idx = Affine_to_monomial[a];
1494
1495 coeff2[idx] += b;
1496 }
1497 for (j = 0; j < nb_monomials; j++) {
1498 coeff2[j] *= c;
1499 }
1500
1501 for (j = 0; j < nb_monomials; j++) {
1502 coeff3[j] += coeff2[j];
1503 }
1504 }
1505
1506 for (j = 0; j < nb_monomials; j++) {
1507 coeff_out[j] = coeff3[j];
1508 }
1509
1510 FREE_int(Monomials);
1511
1512 if (f_v) {
1513 cout << "numerics::substitute_cubic_linear_using_povray_ordering done" << endl;
1514 }
1515}
1516
1518 double *coeff_in, double *coeff_out,
1519 double *A4_inv, int verbose_level)
1520// uses povray ordering of monomials
1521// http://www.povray.org/documentation/view/3.6.1/298/
1522// 1: x^4
1523// 2: x^3y
1524// 3: x^3z
1525// 4: x^3
1526// 5: x^2y^2
1527// 6: x^2yz
1528// 7: x^2y
1529// 8: x^2z^2
1530// 9: x^2z
1531// 10: x^2
1532// 11: xy^3
1533// 12: xy^2z
1534// 13: xy^2
1535// 14: xyz^2
1536// 15: xyz
1537// 16: xy
1538// 17: xz^3
1539// 18: xz^2
1540// 19: xz
1541// 20: x
1542// 21: y^4
1543// 22: y^3z
1544// 23: y^3
1545// 24: y^2z^2
1546// 25: y^2z
1547// 26: y^2
1548// 27: yz^3
1549// 28: yz^2
1550// 29: yz
1551// 30: y
1552// 31: z^4
1553// 32: z^3
1554// 33: z^2
1555// 34: z
1556// 35: 1
1557{
1558 int f_v = (verbose_level >= 1);
1559 int Variables[] = {
1560 // 1:
1561 0,0,0,0,
1562 0,0,0,1,
1563 0,0,0,2,
1564 0,0,0,3,
1565 0,0,1,1,
1566 0,0,1,2,
1567 0,0,1,3,
1568 0,0,2,2,
1569 0,0,2,3,
1570 0,0,3,3,
1571 //11:
1572 0,1,1,1,
1573 0,1,1,2,
1574 0,1,1,3,
1575 0,1,2,2,
1576 0,1,2,3,
1577 0,1,3,3,
1578 0,2,2,2,
1579 0,2,2,3,
1580 0,2,3,3,
1581 0,3,3,3,
1582 // 21:
1583 1,1,1,1,
1584 1,1,1,2,
1585 1,1,1,3,
1586 1,1,2,2,
1587 1,1,2,3,
1588 1,1,3,3,
1589 1,2,2,2,
1590 1,2,2,3,
1591 1,2,3,3,
1592 1,3,3,3,
1593 // 31:
1594 2,2,2,2,
1595 2,2,2,3,
1596 2,2,3,3,
1597 2,3,3,3,
1598 3,3,3,3,
1599 };
1600 int *Monomials; // [nb_monomials * n]
1601 int Affine_to_monomial[256]; // 4^4
1602 int *V;
1603 int nb_monomials = 35;
1604 int degree = 4;
1605 int n = 4;
1606 double coeff2[35];
1607 double coeff3[35];
1608 double b, c;
1609 int h, i, j, a, nb_affine, idx;
1610 int A[4];
1611 int v[4];
1615
1616 if (f_v) {
1617 cout << "numerics::substitute_quartic_linear_using_povray_ordering" << endl;
1618 }
1619
1620 nb_affine = NT.i_power_j(n, degree);
1621
1622
1623 if (FALSE) {
1624 cout << "Variables:" << endl;
1626 }
1627 Monomials = NEW_int(nb_monomials * n);
1628 Int_vec_zero(Monomials, nb_monomials * n);
1629 for (i = 0; i < nb_monomials; i++) {
1630 for (j = 0; j < degree; j++) {
1631 a = Variables[i * degree + j];
1632 Monomials[i * n + a]++;
1633 }
1634 }
1635 if (FALSE) {
1636 cout << "Monomials:" << endl;
1637 orbiter_kernel_system::Orbiter->Int_vec->matrix_print(Monomials, nb_monomials, n);
1638 }
1639
1640 for (i = 0; i < nb_affine; i++) {
1641 Gg.AG_element_unrank(n /* q */, A, 1, degree, i);
1642 Int_vec_zero(v, n);
1643 for (j = 0; j < degree; j++) {
1644 a = A[j];
1645 v[a]++;
1646 }
1647 for (idx = 0; idx < nb_monomials; idx++) {
1648 if (Sorting.int_vec_compare(v, Monomials + idx * n, n) == 0) {
1649 break;
1650 }
1651 }
1652 if (idx == nb_monomials) {
1653 cout << "could not determine Affine_to_monomial" << endl;
1654 cout << "Monomials:" << endl;
1655 orbiter_kernel_system::Orbiter->Int_vec->matrix_print(Monomials, nb_monomials, n);
1656 cout << "v=";
1657 Int_vec_print(cout, v, n);
1658 exit(1);
1659 }
1660 Affine_to_monomial[i] = idx;
1661 }
1662
1663 if (FALSE) {
1664 cout << "Affine_to_monomial:";
1665 Int_vec_print(cout, Affine_to_monomial, nb_affine);
1666 cout << endl;
1667 }
1668
1669
1670 for (i = 0; i < nb_monomials; i++) {
1671 coeff3[i] = 0.;
1672 }
1673 for (h = 0; h < nb_monomials; h++) {
1674 c = coeff_in[h];
1675 if (c == 0) {
1676 continue;
1677 }
1678
1679 V = Variables + h * degree;
1680 // a list of the indices of the variables
1681 // which appear in the monomial
1682 // (possibly with repeats)
1683 // Example: the monomial x_0^3 becomes 0,0,0
1684
1685
1686 for (i = 0; i < nb_monomials; i++) {
1687 coeff2[i] = 0.;
1688 }
1689 for (a = 0; a < nb_affine; a++) {
1690
1691 Gg.AG_element_unrank(n /* q */, A, 1, degree, a);
1692 // sequence of length degree
1693 // over the alphabet 0,...,n-1.
1694 b = 1.;
1695 for (j = 0; j < degree; j++) {
1696 //factors[j] = Mtx_inv[V[j] * n + A[j]];
1697 b *= A4_inv[A[j] * n + V[j]];
1698 }
1699 idx = Affine_to_monomial[a];
1700
1701 coeff2[idx] += b;
1702 }
1703 for (j = 0; j < nb_monomials; j++) {
1704 coeff2[j] *= c;
1705 }
1706
1707 for (j = 0; j < nb_monomials; j++) {
1708 coeff3[j] += coeff2[j];
1709 }
1710 }
1711
1712 for (j = 0; j < nb_monomials; j++) {
1713 coeff_out[j] = coeff3[j];
1714 }
1715
1716 FREE_int(Monomials);
1717
1718 if (f_v) {
1719 cout << "numerics::substitute_quartic_linear_using_povray_ordering done" << endl;
1720 }
1721}
1723 double *varphi,
1724 double *u, double *A, double *Av,
1725 int verbose_level)
1726// varphi are the dual coordinates of a plane.
1727// u is a vector such that varphi(u) \neq -1.
1728// A = I + varphi * u.
1729{
1730 int f_v = (verbose_level >= 1);
1731 int i, j;
1732
1733 if (f_v) {
1734 cout << "make_transform_t_varphi_u_double" << endl;
1735 }
1736 for (i = 0; i < n; i++) {
1737 for (j = 0; j < n; j++) {
1738 if (i == j) {
1739 A[i * n + j] = 1. + varphi[i] * u[j];
1740 }
1741 else {
1742 A[i * n + j] = varphi[i] * u[j];
1743 }
1744 }
1745 }
1746 matrix_double_inverse(A, Av, n, 0 /* verbose_level */);
1747 if (f_v) {
1748 cout << "make_transform_t_varphi_u_double done" << endl;
1749 }
1750}
1751
1752void numerics::matrix_double_inverse(double *A, double *Av, int n,
1753 int verbose_level)
1754{
1755 int f_v = (verbose_level >= 1);
1756 double *M;
1757 int *base_cols;
1758 int i, j, two_n, rk;
1759
1760 if (f_v) {
1761 cout << "matrix_double_inverse" << endl;
1762 }
1763 two_n = n * 2;
1764 M = new double [n * n * 2];
1765 base_cols = NEW_int(two_n);
1766
1767 for (i = 0; i < n; i++) {
1768 for (j = 0; j < n; j++) {
1769 M[i * two_n + j] = A[i * n + j];
1770 if (i == j) {
1771 M[i * two_n + n + j] = 1.;
1772 }
1773 else {
1774 M[i * two_n + n + j] = 0.;
1775 }
1776 }
1777 }
1778 rk = Gauss_elimination(M, n, two_n, base_cols,
1779 TRUE /* f_complete */, 0 /* verbose_level */);
1780 if (rk < n) {
1781 cout << "matrix_double_inverse the matrix "
1782 "is not invertible" << endl;
1783 exit(1);
1784 }
1785 if (base_cols[n - 1] != n - 1) {
1786 cout << "matrix_double_inverse the matrix "
1787 "is not invertible" << endl;
1788 exit(1);
1789 }
1790 for (i = 0; i < n; i++) {
1791 for (j = 0; j < n; j++) {
1792 Av[i * n + j] = M[i * two_n + n + j];
1793 }
1794 }
1795
1796 delete [] M;
1797 FREE_int(base_cols);
1798 if (f_v) {
1799 cout << "matrix_double_inverse done" << endl;
1800 }
1801}
1802
1803
1804int numerics::line_centered(double *pt1_in, double *pt2_in,
1805 double *pt1_out, double *pt2_out, double r, int verbose_level)
1806{
1807 int f_v = TRUE; //(verbose_level >= 1);
1808 double v[3];
1809 double x1, x2, x3, y1, y2, y3;
1810 double a, b, c, av, d, e;
1811 double lambda1, lambda2;
1812
1813
1814 if (f_v) {
1815 cout << "numerics::line_centered" << endl;
1816 cout << "r=" << r << endl;
1817 cout << "pt1_in=";
1818 vec_print(pt1_in, 3);
1819 cout << endl;
1820 cout << "pt2_in=";
1821 vec_print(pt2_in, 3);
1822 cout << endl;
1823 }
1824 x1 = pt1_in[0];
1825 x2 = pt1_in[1];
1826 x3 = pt1_in[2];
1827
1828 y1 = pt2_in[0];
1829 y2 = pt2_in[1];
1830 y3 = pt2_in[2];
1831
1832 v[0] = y1 - x1;
1833 v[1] = y2 - x2;
1834 v[2] = y3 - x3;
1835 if (f_v) {
1836 cout << "v=";
1837 vec_print(v, 3);
1838 cout << endl;
1839 }
1840 // solve
1841 // (x1+\lambda*v[0])^2 + (x2+\lambda*v[1])^2 + (x3+\lambda*v[2])^2 = r^2
1842 // which gives the quadratic
1843 // (v[0]^2+v[1]^2+v[2]^2) * \lambda^2
1844 // + (2*x1*v[0] + 2*x2*v[1] + 2*x3*v[2]) * \lambda
1845 // + x1^2 + x2^2 + x3^2 - r^2
1846 // = 0
1847 a = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
1848 b = 2. * (x1 * v[0] + x2 * v[1] + x3 * v[2]);
1849 c = x1 * x1 + x2 * x2 + x3 * x3 - r * r;
1850 if (f_v) {
1851 cout << "a=" << a << " b=" << b << " c=" << c << endl;
1852 }
1853 av = 1. / a;
1854 b = b * av;
1855 c = c * av;
1856 d = b * b * 0.25 - c;
1857 if (f_v) {
1858 cout << "a=" << a << " b=" << b << " c=" << c << " d=" << d << endl;
1859 }
1860 if (d < 0) {
1861 cout << "line_centered d < 0" << endl;
1862 cout << "r=" << r << endl;
1863 cout << "d=" << d << endl;
1864 cout << "a=" << a << endl;
1865 cout << "b=" << b << endl;
1866 cout << "c=" << c << endl;
1867 cout << "pt1_in=";
1868 vec_print(pt1_in, 3);
1869 cout << endl;
1870 cout << "pt2_in=";
1871 vec_print(pt2_in, 3);
1872 cout << endl;
1873 cout << "v=";
1874 vec_print(v, 3);
1875 cout << endl;
1876 exit(1);
1877 //return FALSE;
1878 //d = 0;
1879 }
1880 e = sqrt(d);
1881
1882 lambda1 = -b * 0.5 + e;
1883 lambda2 = -b * 0.5 - e;
1884 pt1_out[0] = x1 + lambda1 * v[0];
1885 pt1_out[1] = x2 + lambda1 * v[1];
1886 pt1_out[2] = x3 + lambda1 * v[2];
1887 pt2_out[0] = x1 + lambda2 * v[0];
1888 pt2_out[1] = x2 + lambda2 * v[1];
1889 pt2_out[2] = x3 + lambda2 * v[2];
1890 if (f_v) {
1891 cout << "numerics::line_centered done" << endl;
1892 }
1893 return TRUE;
1894}
1895
1896int numerics::line_centered_tolerant(double *pt1_in, double *pt2_in,
1897 double *pt1_out, double *pt2_out, double r, int verbose_level)
1898{
1899 int f_v = (verbose_level >= 1);
1900 double v[3];
1901 double x1, x2, x3, y1, y2, y3;
1902 double a, b, c, av, d, e;
1903 double lambda1, lambda2;
1904
1905
1906 if (f_v) {
1907 cout << "numerics::line_centered_tolerant" << endl;
1908 cout << "r=" << r << endl;
1909 cout << "pt1_in=";
1910 vec_print(pt1_in, 3);
1911 cout << endl;
1912 cout << "pt2_in=";
1913 vec_print(pt2_in, 3);
1914 cout << endl;
1915 }
1916 x1 = pt1_in[0];
1917 x2 = pt1_in[1];
1918 x3 = pt1_in[2];
1919
1920 y1 = pt2_in[0];
1921 y2 = pt2_in[1];
1922 y3 = pt2_in[2];
1923
1924 v[0] = y1 - x1;
1925 v[1] = y2 - x2;
1926 v[2] = y3 - x3;
1927 if (f_v) {
1928 cout << "v=";
1929 vec_print(v, 3);
1930 cout << endl;
1931 }
1932 // solve
1933 // (x1+\lambda*v[0])^2 + (x2+\lambda*v[1])^2 + (x3+\lambda*v[2])^2 = r^2
1934 // which gives the quadratic
1935 // (v[0]^2+v[1]^2+v[2]^2) * \lambda^2
1936 // + (2*x1*v[0] + 2*x2*v[1] + 2*x3*v[2]) * \lambda
1937 // + x1^2 + x2^2 + x3^2 - r^2
1938 // = 0
1939 a = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
1940 b = 2. * (x1 * v[0] + x2 * v[1] + x3 * v[2]);
1941 c = x1 * x1 + x2 * x2 + x3 * x3 - r * r;
1942 if (f_v) {
1943 cout << "a=" << a << " b=" << b << " c=" << c << endl;
1944 }
1945 av = 1. / a;
1946 b = b * av;
1947 c = c * av;
1948 d = b * b * 0.25 - c;
1949 if (f_v) {
1950 cout << "a=" << a << " b=" << b << " c=" << c << " d=" << d << endl;
1951 }
1952 if (d < 0) {
1953 cout << "line_centered d < 0" << endl;
1954 cout << "r=" << r << endl;
1955 cout << "d=" << d << endl;
1956 cout << "a=" << a << endl;
1957 cout << "b=" << b << endl;
1958 cout << "c=" << c << endl;
1959 cout << "pt1_in=";
1960 vec_print(pt1_in, 3);
1961 cout << endl;
1962 cout << "pt2_in=";
1963 vec_print(pt2_in, 3);
1964 cout << endl;
1965 cout << "v=";
1966 vec_print(v, 3);
1967 cout << endl;
1968 //exit(1);
1969 return FALSE;
1970 }
1971 e = sqrt(d);
1972 lambda1 = -b * 0.5 + e;
1973 lambda2 = -b * 0.5 - e;
1974 pt1_out[0] = x1 + lambda1 * v[0];
1975 pt1_out[1] = x2 + lambda1 * v[1];
1976 pt1_out[2] = x3 + lambda1 * v[2];
1977 pt2_out[0] = x1 + lambda2 * v[0];
1978 pt2_out[1] = x2 + lambda2 * v[1];
1979 pt2_out[2] = x3 + lambda2 * v[2];
1980 if (f_v) {
1981 cout << "numerics::line_centered_tolerant done" << endl;
1982 }
1983 return TRUE;
1984}
1985
1986
1988{
1989 if (a < 0) {
1990 return -1;
1991 }
1992 else if (a > 0) {
1993 return 1;
1994 }
1995 else {
1996 return 0;
1997 }
1998}
1999
2000
2001
2002
2003
2004void numerics::eigenvalues(double *A, int n, double *lambda, int verbose_level)
2005{
2006 int f_v = (verbose_level >= 1);
2007 int i, j;
2008
2009 if (f_v) {
2010 cout << "eigenvalues" << endl;
2011 }
2015
2016 Poly.init(n);
2018 for (i = 0; i < n; i++) {
2019 for (j = 0; j < n; j++) {
2020 P[i * n + j].init(n + 1);
2021 if (i == j) {
2022 P[i * n + j].coeff[0] = A[i * n + j];
2023 P[i * n + j].coeff[1] = -1.;
2024 P[i * n + j].degree = 1;
2025 }
2026 else {
2027 P[i * n + j].coeff[0] = A[i * n + j];
2028 P[i * n + j].degree = 0;
2029 }
2030 }
2031 }
2032 for (i = 0; i < n; i++) {
2033 for (j = 0; j < n; j++) {
2034 P[i * n + j].print(cout);
2035 cout << "; ";
2036 }
2037 cout << endl;
2038 }
2039
2040
2042 det->init(n + 1);
2044 P,
2045 det, n, 0 /*verbose_level*/);
2046
2047 cout << "characteristic polynomial ";
2048 det->print(cout);
2049 cout << endl;
2050
2051 //double *lambda;
2052
2053 //lambda = new double[n];
2054
2055 Poly.find_all_roots(det,
2056 lambda, verbose_level);
2057
2058
2059 // bubble sort:
2060 for (i = 0; i < n; i++) {
2061 for (j = i + 1; j < n; j++) {
2062 if (lambda[i] > lambda[j]) {
2063 double a;
2064
2065 a = lambda[i];
2066 lambda[i] = lambda[j];
2067 lambda[j] = a;
2068 }
2069 }
2070 }
2071
2072 cout << "The eigenvalues are: ";
2073 for (i = 0; i < n; i++) {
2074 cout << lambda[i];
2075 if (i < n - 1) {
2076 cout << ", ";
2077 }
2078 }
2079 cout << endl;
2080
2081
2082 if (f_v) {
2083 cout << "eigenvalues done" << endl;
2084 }
2085}
2086
2087void numerics::eigenvectors(double *A, double *Basis,
2088 int n, double *lambda, int verbose_level)
2089{
2090 int f_v = (verbose_level >= 1);
2091 int i, j;
2092
2093 if (f_v) {
2094 cout << "eigenvectors" << endl;
2095 }
2096
2097 cout << "The eigenvalues are: ";
2098 for (i = 0; i < n; i++) {
2099 cout << lambda[i];
2100 if (i < n - 1) {
2101 cout << ", ";
2102 }
2103 }
2104 cout << endl;
2105 double *B, *K;
2106 int u, v, h, k;
2107 double uv, vv, s;
2108
2109 B = new double[n * n];
2110 K = new double[n * n];
2111
2112 for (h = 0; h < n; ) {
2113 cout << "eigenvector " << h << " / " << n << " is " << lambda[h] << ":" << endl;
2114 for (i = 0; i < n; i++) {
2115 for (j = 0; j < n; j++) {
2116 if (i == j) {
2117 B[i * n + j] = A[i * n + j] - lambda[h];
2118 }
2119 else {
2120 B[i * n + j] = A[i * n + j];
2121 }
2122 }
2123 }
2124 k = Null_space(B, n, n, K, verbose_level);
2125 // K will be k x n
2126 // where k is the return value.
2127 cout << "the eigenvalue has multiplicity " << k << endl;
2128 for (u = 0; u < k; u++) {
2129 for (j = 0; j < n; j++) {
2130 Basis[j * n + h + u] = K[u * n + j];
2131 }
2132 if (u) {
2133 // perform Gram-Schmidt:
2134 for (v = 0; v < u; v++) {
2135 uv = 0;
2136 for (i = 0; i < n; i++) {
2137 uv += Basis[i * n + h + u] * Basis[i * n + h + v];
2138 }
2139 vv = 0;
2140 for (i = 0; i < n; i++) {
2141 vv += Basis[i * n + h + v] * Basis[i * n + h + v];
2142 }
2143 s = uv / vv;
2144 for (i = 0; i < n; i++) {
2145 Basis[i * n + h + u] -= s * Basis[i * n + h + v];
2146 }
2147 } // next v
2148 } // if (u)
2149 }
2150 // perform normalization:
2151 for (v = 0; v < k; v++) {
2152 vv = 0;
2153 for (i = 0; i < n; i++) {
2154 vv += Basis[i * n + h + v] * Basis[i * n + h + v];
2155 }
2156 s = 1 / sqrt(vv);
2157 for (i = 0; i < n; i++) {
2158 Basis[i * n + h + v] *= s;
2159 }
2160 }
2161 h += k;
2162 } // next h
2163
2164 cout << "The orthonormal Basis is: " << endl;
2165 for (i = 0; i < n; i++) {
2166 for (j = 0; j < n; j++) {
2167 cout << Basis[i * n + j] << "\t";
2168 }
2169 cout << endl;
2170 }
2171
2172 if (f_v) {
2173 cout << "eigenvectors done" << endl;
2174 }
2175}
2176
2177double numerics::rad2deg(double phi)
2178{
2179 return phi * 180. / M_PI;
2180}
2181
2182void numerics::vec_copy(double *from, double *to, int len)
2183{
2184 int i;
2185 double *p, *q;
2186
2187 for (p = from, q = to, i = 0; i < len; p++, q++, i++) {
2188 *q = *p;
2189 }
2190}
2191
2192void numerics::vec_swap(double *from, double *to, int len)
2193{
2194 int i;
2195 double *p, *q;
2196 double a;
2197
2198 for (p = from, q = to, i = 0; i < len; p++, q++, i++) {
2199 a = *q;
2200 *q = *p;
2201 *p = a;
2202 }
2203}
2204
2205void numerics::vec_print(ostream &ost, double *v, int len)
2206{
2207 int i;
2208
2209 ost << "( ";
2210 for (i = 0; i < len; i++) {
2211 ost << v[i];
2212 if (i < len - 1)
2213 ost << ", ";
2214 }
2215 ost << " )";
2216}
2217
2218void numerics::vec_scan(const char *s, double *&v, int &len)
2219{
2220
2221 istringstream ins(s);
2222 vec_scan_from_stream(ins, v, len);
2223}
2224
2225void numerics::vec_scan(std::string &s, double *&v, int &len)
2226{
2227
2228 istringstream ins(s);
2229 vec_scan_from_stream(ins, v, len);
2230}
2231
2232void numerics::vec_scan_from_stream(istream & is, double *&v, int &len)
2233{
2234 int verbose_level = 0;
2235 int f_v = (verbose_level >= 1);
2236 double a;
2237 char s[10000], c;
2238 int l, h;
2239
2240 len = 20;
2241 v = new double [len];
2242 h = 0;
2243 l = 0;
2244
2245 while (TRUE) {
2246 if (!is) {
2247 len = h;
2248 return;
2249 }
2250 l = 0;
2251 if (is.eof()) {
2252 //cout << "breaking off because of eof" << endl;
2253 len = h;
2254 return;
2255 }
2256 is >> c;
2257 //c = get_character(is, verbose_level - 2);
2258 if (c == 0) {
2259 len = h;
2260 return;
2261 }
2262 while (TRUE) {
2263 while (c != 0) {
2264
2265 if (f_v) {
2266 cout << "character \"" << c
2267 << "\", ascii=" << (int)c << endl;
2268 }
2269
2270 if (c == '-') {
2271 //cout << "c='" << c << "'" << endl;
2272 if (is.eof()) {
2273 //cout << "breaking off because of eof" << endl;
2274 break;
2275 }
2276 s[l++] = c;
2277 is >> c;
2278 //c = get_character(is, verbose_level - 2);
2279 }
2280 else if ((c >= '0' && c <= '9') || c == '.') {
2281 //cout << "c='" << c << "'" << endl;
2282 if (is.eof()) {
2283 //cout << "breaking off because of eof" << endl;
2284 break;
2285 }
2286 s[l++] = c;
2287 is >> c;
2288 //c = get_character(is, verbose_level - 2);
2289 }
2290 else {
2291 //cout << "breaking off because c='" << c << "'" << endl;
2292 break;
2293 }
2294 if (c == 0) {
2295 break;
2296 }
2297 //cout << "int_vec_scan_from_stream inside loop: \""
2298 //<< c << "\", ascii=" << (int)c << endl;
2299 }
2300 s[l] = 0;
2301 sscanf(s, "%lf", &a);
2302 //a = atoi(s);
2303 if (FALSE) {
2304 cout << "digit as string: " << s << ", numeric: " << a << endl;
2305 }
2306 if (h == len) {
2307 len += 20;
2308 double *v2;
2309
2310 v2 = new double [len];
2311 vec_copy(v, v2, h);
2312 delete [] v;
2313 v = v2;
2314 }
2315 v[h++] = a;
2316 l = 0;
2317 if (!is) {
2318 len = h;
2319 return;
2320 }
2321 if (c == 0) {
2322 len = h;
2323 return;
2324 }
2325 if (is.eof()) {
2326 //cout << "breaking off because of eof" << endl;
2327 len = h;
2328 return;
2329 }
2330 is >> c;
2331 //c = get_character(is, verbose_level - 2);
2332 if (c == 0) {
2333 len = h;
2334 return;
2335 }
2336 }
2337 }
2338}
2339
2340
2341#include <math.h>
2342
2343double numerics::cos_grad(double phi)
2344{
2345 double x;
2346
2347 x = (phi * M_PI) / 180.;
2348 return cos(x);
2349}
2350
2351double numerics::sin_grad(double phi)
2352{
2353 double x;
2354
2355 x = (phi * M_PI) / 180.;
2356 return sin(x);
2357}
2358
2359double numerics::tan_grad(double phi)
2360{
2361 double x;
2362
2363 x = (phi * M_PI) / 180.;
2364 return tan(x);
2365}
2366
2367double numerics::atan_grad(double x)
2368{
2369 double y, phi;
2370
2371 y = atan(x);
2372 phi = (y * 180.) / M_PI;
2373 return phi;
2374}
2375
2377 double *Px, double *Py,
2378 int *Qx, int *Qy,
2379 int N, double xmin, double ymin, double xmax, double ymax,
2380 int verbose_level)
2381{
2382 int f_v = (verbose_level >= 1);
2383 int f_vv = (verbose_level >= 2);
2384 double in[4], out[4];
2385 double x_min, x_max;
2386 double y_min, y_max;
2387 int i;
2388 double x, y;
2389
2390 x_min = x_max = Px[0];
2391 y_min = y_max = Py[0];
2392
2393 for (i = 1; i < N; i++) {
2394 x_min = MINIMUM(x_min, Px[i]);
2395 x_max = MAXIMUM(x_max, Px[i]);
2396 y_min = MINIMUM(y_min, Py[i]);
2397 y_max = MAXIMUM(y_max, Py[i]);
2398 }
2399 if (f_v) {
2400 cout << "numerics::adjust_coordinates_double: x_min=" << x_min
2401 << "x_max=" << x_max
2402 << "y_min=" << y_min
2403 << "y_max=" << y_max << endl;
2404 cout << "adjust_coordinates_double: ";
2405 cout
2406 << "xmin=" << xmin
2407 << " xmax=" << xmax
2408 << " ymin=" << ymin
2409 << " ymax=" << ymax
2410 << endl;
2411 }
2412
2413 in[0] = x_min;
2414 in[1] = y_min;
2415 in[2] = x_max;
2416 in[3] = y_max;
2417
2418 out[0] = xmin;
2419 out[1] = ymin;
2420 out[2] = xmax;
2421 out[3] = ymax;
2422
2423 for (i = 0; i < N; i++) {
2424 x = Px[i];
2425 y = Py[i];
2426 if (f_vv) {
2427 cout << "In:" << x << "," << y << " : ";
2428 }
2429 transform_llur_double(in, out, x, y);
2430 Qx[i] = (int)x;
2431 Qy[i] = (int)y;
2432 if (f_vv) {
2433 cout << " Out: " << Qx[i] << "," << Qy[i] << endl;
2434 }
2435 }
2436}
2437
2438void numerics::Intersection_of_lines(double *X, double *Y,
2439 double *a, double *b, double *c, int l1, int l2, int pt)
2440{
2442 a[l1], b[l1], c[l1],
2443 a[l2], b[l2], c[l2],
2444 X[pt], Y[pt]);
2445}
2446
2448 double a1, double b1, double c1,
2449 double a2, double b2, double c2,
2450 double &x, double &y)
2451{
2452 double d;
2453
2454 d = a1 * b2 - a2 * b1;
2455 d = 1. / d;
2456 x = d * (b2 * -c1 + -b1 * -c2);
2457 y = d * (-a2 * -c1 + a1 * -c2);
2458}
2459
2460void numerics::Line_through_points(double *X, double *Y,
2461 double *a, double *b, double *c,
2462 int pt1, int pt2, int line_idx)
2463{
2464 line_through_points(X[pt1], Y[pt1], X[pt2], Y[pt2],
2465 a[line_idx], b[line_idx], c[line_idx]);
2466}
2467
2468void numerics::line_through_points(double pt1_x, double pt1_y,
2469 double pt2_x, double pt2_y, double &a, double &b, double &c)
2470{
2471 double s, off;
2472 const double MY_EPS = 0.01;
2473
2474 if (ABS(pt2_x - pt1_x) > MY_EPS) {
2475 s = (pt2_y - pt1_y) / (pt2_x - pt1_x);
2476 off = pt1_y - s * pt1_x;
2477 a = s;
2478 b = -1;
2479 c = off;
2480 }
2481 else {
2482 s = (pt2_x - pt1_x) / (pt2_y - pt1_y);
2483 off = pt1_x - s * pt1_y;
2484 a = 1;
2485 b = -s;
2486 c = -off;
2487 }
2488}
2489
2490void numerics::intersect_circle_line_through(double rad, double x0, double y0,
2491 double pt1_x, double pt1_y,
2492 double pt2_x, double pt2_y,
2493 double &x1, double &y1, double &x2, double &y2)
2494{
2495 double a, b, c;
2496
2497 line_through_points(pt1_x, pt1_y, pt2_x, pt2_y, a, b, c);
2498 //cout << "intersect_circle_line_through pt1_x=" << pt1_x
2499 //<< " pt1_y=" << pt1_y << " pt2_x=" << pt2_x
2500 //<< " pt2_y=" << pt2_y << endl;
2501 //cout << "intersect_circle_line_through a=" << a << " b=" << b
2502 //<< " c=" << c << endl;
2503 intersect_circle_line(rad, x0, y0, a, b, c, x1, y1, x2, y2);
2504 //cout << "intersect_circle_line_through x1=" << x1 << " y1=" << y1
2505 // << " x2=" << x2 << " y2=" << y2 << endl << endl;
2506}
2507
2508
2509void numerics::intersect_circle_line(double rad, double x0, double y0,
2510 double a, double b, double c,
2511 double &x1, double &y1, double &x2, double &y2)
2512{
2513 double A, B, C;
2514 double a2 = a * a;
2515 double b2 = b * b;
2516 double c2 = c * c;
2517 double x02 = x0 * x0;
2518 double y02 = y0 * y0;
2519 double r2 = rad * rad;
2520 double p, q, u, disc, d;
2521
2522 cout << "a=" << a << " b=" << b << " c=" << c << endl;
2523 A = 1 + a2 / b2;
2524 B = 2 * a * c / b2 - 2 * x0 + 2 * a * y0 / b;
2525 C = c2 / b2 + 2 * c * y0 / b + x02 + y02 - r2;
2526 cout << "A=" << A << " B=" << B << " C=" << C << endl;
2527 p = B / A;
2528 q = C / A;
2529 u = -p / 2;
2530 disc = u * u - q;
2531 d = sqrt(disc);
2532 x1 = u + d;
2533 x2 = u - d;
2534 y1 = (-a * x1 - c) / b;
2535 y2 = (-a * x2 - c) / b;
2536}
2537
2538void numerics::affine_combination(double *X, double *Y,
2539 int pt0, int pt1, int pt2, double alpha, int new_pt)
2540//X[new_pt] = X[pt0] + alpha * (X[pt2] - X[pt1]);
2541//Y[new_pt] = Y[pt0] + alpha * (Y[pt2] - Y[pt1]);
2542{
2543 X[new_pt] = X[pt0] + alpha * (X[pt2] - X[pt1]);
2544 Y[new_pt] = Y[pt0] + alpha * (Y[pt2] - Y[pt1]);
2545}
2546
2547
2548void numerics::on_circle_double(double *Px, double *Py,
2549 int idx, double angle_in_degree, double rad)
2550{
2551
2552 Px[idx] = cos_grad(angle_in_degree) * rad;
2553 Py[idx] = sin_grad(angle_in_degree) * rad;
2554}
2555
2556void numerics::affine_pt1(int *Px, int *Py,
2557 int p0, int p1, int p2, double f1, int p3)
2558{
2559 int x = Px[p0] + (int)(f1 * (double)(Px[p2] - Px[p1]));
2560 int y = Py[p0] + (int)(f1 * (double)(Py[p2] - Py[p1]));
2561 Px[p3] = x;
2562 Py[p3] = y;
2563}
2564
2565void numerics::affine_pt2(int *Px, int *Py,
2566 int p0, int p1, int p1b,
2567 double f1, int p2, int p2b, double f2, int p3)
2568{
2569 int x = Px[p0]
2570 + (int)(f1 * (double)(Px[p1b] - Px[p1]))
2571 + (int)(f2 * (double)(Px[p2b] - Px[p2]));
2572 int y = Py[p0]
2573 + (int)(f1 * (double)(Py[p1b] - Py[p1]))
2574 + (int)(f2 * (double)(Py[p2b] - Py[p2]));
2575 Px[p3] = x;
2576 Py[p3] = y;
2577}
2578
2579
2580double numerics::norm_of_vector_2D(int x1, int x2, int y1, int y2)
2581{
2582 return sqrt((double)(x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
2583}
2584
2585#undef DEBUG_TRANSFORM_LLUR
2586
2587void numerics::transform_llur(int *in, int *out, int &x, int &y)
2588{
2589 int dx, dy; //, rad;
2590 double a, b; //, f;
2591
2592#ifdef DEBUG_TRANSFORM_LLUR
2593 cout << "transform_llur: ";
2594 cout << "In=" << in[0] << "," << in[1] << "," << in[2] << "," << in[3] << endl;
2595 cout << "Out=" << out[0] << "," << out[1] << "," << out[2] << "," << out[3] << endl;
2596#endif
2597 dx = x - in[0];
2598 dy = y - in[1];
2599 //rad = MIN(out[2] - out[0], out[3] - out[1]);
2600 a = (double) dx / (double)(in[2] - in[0]);
2601 b = (double) dy / (double)(in[3] - in[1]);
2602 //a = a / 300000.;
2603 //b = b / 300000.;
2604#ifdef DEBUG_TRANSFORM_LLUR
2605 cout << "transform_llur: (x,y)=(" << x << "," << y << ") in[2] - in[0]=" << in[2] - in[0] << " in[3] - in[1]=" << in[3] - in[1] << " (a,b)=(" << a << "," << b << ") -> ";
2606#endif
2607
2608 // projection on a disc of radius 1:
2609 //f = 300000 / sqrt(1. + a * a + b * b);
2610#ifdef DEBUG_TRANSFORM_LLUR
2611 cout << "f=" << f << endl;
2612#endif
2613 //a = f * a;
2614 //b = f * b;
2615
2616 //dx = (int)(a * f);
2617 //dy = (int)(b * f);
2618 dx = (int)(a * (double)(out[2] - out[0]));
2619 dy = (int)(b * (double)(out[3] - out[1]));
2620 x = dx + out[0];
2621 y = dy + out[1];
2622#ifdef DEBUG_TRANSFORM_LLUR
2623 cout << x << "," << y << " a=" << a << " b=" << b << endl;
2624#endif
2625}
2626
2627void numerics::transform_dist(int *in, int *out, int &x, int &y)
2628{
2629 int dx, dy;
2630 double a, b;
2631
2632 a = (double) x / (double)(in[2] - in[0]);
2633 b = (double) y / (double)(in[3] - in[1]);
2634 dx = (int)(a * (double) (out[2] - out[0]));
2635 dy = (int)(b * (double) (out[3] - out[1]));
2636 x = dx;
2637 y = dy;
2638}
2639
2640void numerics::transform_dist_x(int *in, int *out, int &x)
2641{
2642 int dx;
2643 double a;
2644
2645 a = (double) x / (double)(in[2] - in[0]);
2646 dx = (int)(a * (double) (out[2] - out[0]));
2647 x = dx;
2648}
2649
2650void numerics::transform_dist_y(int *in, int *out, int &y)
2651{
2652 int dy;
2653 double b;
2654
2655 b = (double) y / (double)(in[3] - in[1]);
2656 dy = (int)(b * (double) (out[3] - out[1]));
2657 y = dy;
2658}
2659
2660void numerics::transform_llur_double(double *in, double *out, double &x, double &y)
2661{
2662 double dx, dy;
2663 double a, b;
2664
2665#ifdef DEBUG_TRANSFORM_LLUR
2666 cout << "transform_llur_double: " << x << "," << y << " -> ";
2667#endif
2668 dx = x - in[0];
2669 dy = y - in[1];
2670 a = dx / (in[2] - in[0]);
2671 b = dy / (in[3] - in[1]);
2672 dx = a * (out[2] - out[0]);
2673 dy = b * (out[3] - out[1]);
2674 x = dx + out[0];
2675 y = dy + out[1];
2676#ifdef DEBUG_TRANSFORM_LLUR
2677 cout << x << "," << y << endl;
2678#endif
2679}
2680
2681
2682
2683void numerics::on_circle_int(int *Px, int *Py,
2684 int idx, int angle_in_degree, int rad)
2685{
2686 Px[idx] = (int)(cos_grad(angle_in_degree) * (double) rad);
2687 Py[idx] = (int)(sin_grad(angle_in_degree) * (double) rad);
2688}
2689
2690
2691double numerics::power_of(double x, int n)
2692{
2693 double b, c;
2694
2695 b = x;
2696 c = 1.;
2697 while (n) {
2698 if (n % 2) {
2699 //cout << "numerics::power_of mult(" << b << "," << c << ")=";
2700 c = b * c;
2701 //cout << c << endl;
2702 }
2703 b = b * b;
2704 n >>= 1;
2705 //cout << "numerics::power_of " << b << "^"
2706 //<< n << " * " << c << endl;
2707 }
2708 return c;
2709
2710}
2711
2712double numerics::bernoulli(double p, int n, int k)
2713{
2714 double q, P, Q, PQ, c;
2715 int nCk;
2717
2718 q = 1. - p;
2719 P = power_of(p, k);
2720 Q = power_of(q, n - k);
2721 PQ = P * Q;
2722 nCk = Combi.int_n_choose_k(n, k);
2723 c = (double) nCk * PQ;
2724 return c;
2725}
2726
2728 double *triangle_points, double &x, double &y,
2729 int verbose_level)
2730{
2731 int f_v = (verbose_level >= 1);
2732 double b1[3];
2733 double b2[3];
2734
2735 if (f_v) {
2736 cout << "numerics::local_coordinates_wrt_triangle" << endl;
2737 }
2738 vec_linear_combination(1., triangle_points + 1 * 3,
2739 -1, triangle_points + 0 * 3, b1, 3);
2740
2741 vec_linear_combination(1., triangle_points + 2 * 3,
2742 -1, triangle_points + 0 * 3, b2, 3);
2743
2744 if (f_v) {
2745 cout << "numerics::local_coordinates_wrt_triangle b1:" << endl;
2746 print_system(b1, 1, 3);
2747 cout << endl;
2748 cout << "numerics::local_coordinates_wrt_triangle b2:" << endl;
2749 print_system(b2, 1, 3);
2750 cout << endl;
2751 }
2752
2753 double system[9];
2754 double system_transposed[9];
2755 double K[3];
2756 int rk;
2757
2758 vec_copy(b1, system, 3);
2759 vec_copy(b2, system + 3, 3);
2761 -1, triangle_points + 0 * 3, system + 6, 3);
2762 transpose_matrix_nxn(system, system_transposed, 3);
2763 if (f_v) {
2764 cout << "system (transposed):" << endl;
2765 print_system(system_transposed, 3, 3);
2766 cout << endl;
2767 }
2768 rk = Null_space(system_transposed, 3, 3, K, 0 /* verbose_level */);
2769 if (f_v) {
2770 cout << "system transposed in RREF" << endl;
2771 print_system(system_transposed, 3, 3);
2772 cout << endl;
2773 cout << "K=" << endl;
2774 print_system(K, 1, 3);
2775 cout << endl;
2776 }
2777 // K will be rk x n
2778 if (rk != 1) {
2779 cout << "numerics::local_coordinates_wrt_triangle rk != 1" << endl;
2780 exit(1);
2781 }
2782
2783 if (ABS(K[2]) < EPSILON) {
2784 cout << "numerics::local_coordinates_wrt_triangle ABS(K[2]) < EPSILON" << endl;
2785 //exit(1);
2786 x = 0;
2787 y = 0;
2788 }
2789 else {
2790 double c, cv;
2791
2792 c = K[2];
2793 cv = -1. / c;
2794 // make the last coefficient -1
2795 // so we get the equation
2796 // x * b1 + y * b2 = v
2797 // where v is the point that we consider
2798 K[0] *= cv;
2799 K[1] *= cv;
2800 x = K[0];
2801 y = K[1];
2802 }
2803
2804 if (f_v) {
2805 cout << "numerics::local_coordinates_wrt_triangle done" << endl;
2806 }
2807
2808}
2809
2810
2812 double *line1_pt1_coords, double *line1_pt2_coords,
2813 double *line2_pt1_coords, double *line2_pt2_coords,
2814 double &lambda,
2815 double *pt_coords,
2816 int verbose_level)
2817{
2818 int f_v = (verbose_level >= 1);
2819 int f_vv = FALSE; // (verbose_level >= 2);
2820 //double B[3];
2821 double M[9];
2822 int i;
2823 double v[3];
2824 numerics N;
2825
2826 if (f_v) {
2827 cout << "numerics::intersect_line_and_line" << endl;
2828 }
2829
2830
2831 // equation of the form:
2832 // P_0 + \lambda * v = Q_0 + \mu * u
2833
2834 // where P_0 is a point on the line,
2835 // Q_0 is a point on the plane,
2836 // v is a direction vector of line 1
2837 // u is a direction vector of line 2
2838
2839 // M is the matrix whose columns are
2840 // v, -u, -P_0 + Q_0
2841
2842 // point on line 1, brought over on the other side, hence the minus:
2843 // -P_0
2844 M[0 * 3 + 2] = -1. * line1_pt1_coords[0]; //Line_coords[line1_idx * 6 + 0];
2845 M[1 * 3 + 2] = -1. * line1_pt1_coords[1]; //Line_coords[line1_idx * 6 + 1];
2846 M[2 * 3 + 2] = -1. * line1_pt1_coords[2]; //Line_coords[line1_idx * 6 + 2];
2847 // +P_1
2848 M[0 * 3 + 2] += line2_pt1_coords[0]; //Line_coords[line2_idx * 6 + 0];
2849 M[1 * 3 + 2] += line2_pt1_coords[1]; //Line_coords[line2_idx * 6 + 1];
2850 M[2 * 3 + 2] += line2_pt1_coords[2]; //Line_coords[line2_idx * 6 + 2];
2851
2852 // v = direction vector of line 1:
2853 for (i = 0; i < 3; i++) {
2854 v[i] = line1_pt2_coords[i] - line1_pt1_coords[i];
2855 }
2856 // we will need v[] later, hence we store this vector
2857 for (i = 0; i < 3; i++) {
2858 //v[i] = line1_pt2_coords[i] - line1_pt1_coords[i];
2859 //v[i] = Line_coords[line1_idx * 6 + 3 + i] -
2860 // Line_coords[line1_idx * 6 + i];
2861 M[i * 3 + 0] = v[i];
2862 }
2863
2864 // negative direction vector of line 2:
2865 for (i = 0; i < 3; i++) {
2866 M[i * 3 + 1] = -1. * (line2_pt2_coords[i] - line2_pt1_coords[i]);
2867 //M[i * 3 + 1] = -1. * (Line_coords[line2_idx * 6 + 3 + i] -
2868 // Line_coords[line2_idx * 6 + i]);
2869 }
2870
2871
2872 // solve M:
2873 int rk;
2874 int base_cols[3];
2875
2876 if (f_vv) {
2877 cout << "numerics::intersect_line_and_line "
2878 "before Gauss elimination:" << endl;
2879 N.print_system(M, 3, 3);
2880 }
2881
2882 rk = N.Gauss_elimination(M, 3, 3,
2883 base_cols, TRUE /* f_complete */,
2884 0 /* verbose_level */);
2885
2886 if (f_vv) {
2887 cout << "numerics::intersect_line_and_line "
2888 "after Gauss elimination:" << endl;
2889 N.print_system(M, 3, 3);
2890 }
2891
2892
2893 if (rk < 2) {
2894 cout << "numerics::intersect_line_and_line "
2895 "the matrix M does not have full rank" << endl;
2896 return FALSE;
2897 }
2898 lambda = M[0 * 3 + 2];
2899 for (i = 0; i < 3; i++) {
2900 pt_coords[i] = line1_pt1_coords[i] + lambda * v[i];
2901 //B[i] = Line_coords[line1_idx * 6 + i] + lambda * v[i];
2902 }
2903
2904 if (f_vv) {
2905 cout << "numerics::intersect_line_and_line "
2906 "The intersection point is "
2907 << pt_coords[0] << ", " << pt_coords[1] << ", " << pt_coords[2] << endl;
2908 }
2909 //point(B[0], B[1], B[2]);
2910
2911
2912 if (f_v) {
2913 cout << "numerics::intersect_line_and_line done" << endl;
2914 }
2915 return TRUE;
2916}
2917
2919 double *line1_pt1_coords, double *line1_pt2_coords,
2920 double *line2_pt1_coords, double *line2_pt2_coords,
2921 double *pt_in, double *pt_out,
2922 double *Cubic_coords_povray_ordering,
2923 int line1_idx, int line2_idx,
2924 int verbose_level)
2925{
2926 int f_v = (verbose_level >= 1);
2927 int i;
2928 int rk;
2929 numerics Num;
2930
2931 double M[16];
2932 double L[16];
2933 double Pts[16];
2934 double N[16];
2935 double C[20];
2936
2937 if (f_v) {
2938 cout << "numerics::clebsch_map_up "
2939 "line1_idx=" << line1_idx
2940 << " line2_idx=" << line2_idx << endl;
2941 }
2942
2943 if (line1_idx == line2_idx) {
2944 cout << "numerics::clebsch_map_up "
2945 "line1_idx == line2_idx, line1_idx=" << line1_idx << endl;
2946 exit(1);
2947 }
2948
2949 Num.vec_copy(line1_pt1_coords, M, 3);
2950 M[3] = 1.;
2951 Num.vec_copy(line1_pt2_coords, M + 4, 3);
2952 M[7] = 1.;
2953 Num.vec_copy(pt_in, M + 8, 3);
2954 M[11] = 1.;
2955
2956 if (f_v) {
2957 cout << "numerics::clebsch_map_up "
2958 "system for plane 1=" << endl;
2959 Num.print_system(M, 3, 4);
2960 }
2961
2962 rk = Num.Null_space(M, 3, 4, L, 0 /* verbose_level */);
2963 if (rk != 1) {
2964 cout << "numerics::clebsch_map_up "
2965 "system for plane 1 does not have nullity 1" << endl;
2966 cout << "numerics::clebsch_map_up "
2967 "nullity=" << rk << endl;
2968 exit(1);
2969 }
2970 if (f_v) {
2971 cout << "numerics::clebsch_map_up "
2972 "perp for plane 1=" << endl;
2973 Num.print_system(L, 1, 4);
2974 }
2975
2976 Num.vec_copy(line2_pt1_coords, M, 3);
2977 M[3] = 1.;
2978 Num.vec_copy(line2_pt2_coords, M + 4, 3);
2979 M[7] = 1.;
2980 Num.vec_copy(pt_in, M + 8, 3);
2981 M[11] = 1.;
2982 if (f_v) {
2983 cout << "numerics::clebsch_map_up "
2984 "system for plane 2=" << endl;
2985 Num.print_system(M, 3, 4);
2986 }
2987
2988 rk = Num.Null_space(M, 3, 4, L + 4, 0 /* verbose_level */);
2989 if (rk != 1) {
2990 cout << "numerics::clebsch_map_up "
2991 "system for plane 2 does not have nullity 1" << endl;
2992 cout << "numerics::clebsch_map_up "
2993 "nullity=" << rk << endl;
2994 exit(1);
2995 }
2996 if (f_v) {
2997 cout << "numerics::clebsch_map_up "
2998 "perp for plane 2=" << endl;
2999 Num.print_system(L + 4, 1, 4);
3000 }
3001
3002 if (f_v) {
3003 cout << "numerics::clebsch_map_up "
3004 "system for line=" << endl;
3005 Num.print_system(L, 2, 4);
3006 }
3007 rk = Num.Null_space(L, 2, 4, L + 8, 0 /* verbose_level */);
3008 if (rk != 2) {
3009 cout << "numerics::clebsch_map_up "
3010 "system for line does not have nullity 2" << endl;
3011 cout << "numerics::clebsch_map_up "
3012 "nullity=" << rk << endl;
3013 exit(1);
3014 }
3015 if (f_v) {
3016 cout << "numerics::clebsch_map_up "
3017 "perp for Line=" << endl;
3018 Num.print_system(L + 8, 2, 4);
3019 }
3020
3021 Num.vec_normalize_from_back(L + 8, 4);
3022 Num.vec_normalize_from_back(L + 12, 4);
3023 if (f_v) {
3024 cout << "numerics::clebsch_map_up "
3025 "perp for Line normalized=" << endl;
3026 Num.print_system(L + 8, 2, 4);
3027 }
3028
3029 if (ABS(L[11]) < 0.0001) {
3030 Num.vec_copy(L + 12, Pts, 4);
3031 Num.vec_add(L + 8, L + 12, Pts + 4, 4);
3032
3033 if (f_v) {
3034 cout << "numerics::clebsch_map_up "
3035 "two affine points on the line=" << endl;
3036 Num.print_system(Pts, 2, 4);
3037 }
3038
3039 }
3040 else {
3041 cout << "numerics::clebsch_map_up "
3042 "something is wrong with the line" << endl;
3043 exit(1);
3044 }
3045
3046
3047 Num.line_centered(Pts, Pts + 4, N, N + 4, 10, verbose_level - 1);
3048 N[3] = 1.;
3049 N[7] = 0.;
3050
3051 if (f_v) {
3052 cout << "numerics::clebsch_map_up "
3053 "line centered=" << endl;
3054 Num.print_system(N, 2, 4);
3055 }
3056
3057 //int l_idx;
3058 double line3_pt1_coords[3];
3059 double line3_pt2_coords[3];
3060
3061 // create a line:
3062 //l_idx = S->line(N[0], N[1], N[2], N[4], N[5], N[6]);
3063 //Line_idx[nb_line_idx++] = S->nb_lines - 1;
3064 for (i = 0; i < 3; i++) {
3065 line3_pt1_coords[i] = N[i];
3066 }
3067 for (i = 0; i < 3; i++) {
3068 line3_pt2_coords[i] = N[4 + i];
3069 }
3070
3071 for (i = 0; i < 3; i++) {
3072 N[4 + i] = N[4 + i] - N[i];
3073 }
3074 for (i = 8; i < 16; i++) {
3075 N[i] = 0.;
3076 }
3077
3078 if (f_v) {
3079 cout << "N=" << endl;
3080 Num.print_system(N, 4, 4);
3081 }
3082
3083
3084 Num.substitute_cubic_linear_using_povray_ordering(Cubic_coords_povray_ordering, C,
3085 N, 0 /* verbose_level */);
3086
3087 if (f_v) {
3088 cout << "numerics::clebsch_map_up "
3089 "transformed cubic=" << endl;
3090 Num.print_system(C, 1, 20);
3091 }
3092
3093 double a, b, c, d, tr, t1, t2, t3;
3094
3095 a = C[10];
3096 b = C[4];
3097 c = C[1];
3098 d = C[0];
3099
3100
3101 tr = -1 * b / a;
3102
3103 if (f_v) {
3104 cout << "numerics::clebsch_map_up "
3105 "a=" << a << " b=" << b
3106 << " c=" << c << " d=" << d << endl;
3107 cout << "clebsch_scene::create_point_up "
3108 "tr = " << tr << endl;
3109 }
3110
3111 double pt1_coords[3];
3112 double pt2_coords[3];
3113
3114 // creates a point:
3116 line3_pt1_coords, line3_pt2_coords,
3117 line1_pt1_coords, line1_pt2_coords,
3118 t1 /* lambda */,
3119 pt1_coords,
3120 0 /*verbose_level*/)) {
3121 cout << "numerics::clebsch_map_up "
3122 "problem computing intersection with line 1" << endl;
3123 exit(1);
3124 }
3125
3126 double P1[3];
3127
3128 for (i = 0; i < 3; i++) {
3129 P1[i] = N[i] + t1 * (N[4 + i] - N[i]);
3130 }
3131
3132 if (f_v) {
3133 cout << "numerics::clebsch_map_up t1=" << t1 << endl;
3134 cout << "numerics::clebsch_map_up P1=";
3135 Num.print_system(P1, 1, 3);
3136 cout << "numerics::clebsch_map_up point: ";
3137 Num.print_system(pt1_coords, 1, 3);
3138 }
3139
3140
3141 double eval_t1;
3142
3143 eval_t1 = (((a * t1 + b) * t1) + c) * t1 + d;
3144
3145 if (f_v) {
3146 cout << "numerics::clebsch_map_up "
3147 "eval_t1=" << eval_t1 << endl;
3148 }
3149
3150 // creates a point:
3152 line3_pt1_coords, line3_pt2_coords,
3153 line1_pt2_coords, line2_pt2_coords,
3154 t2 /* lambda */,
3155 pt2_coords,
3156 0 /*verbose_level*/)) {
3157 cout << "numerics::clebsch_map_up "
3158 "problem computing intersection with line 2" << endl;
3159 exit(1);
3160 }
3161
3162 double P2[3];
3163
3164 for (i = 0; i < 3; i++) {
3165 P2[i] = N[i] + t2 * (N[4 + i] - N[i]);
3166 }
3167 if (f_v) {
3168 cout << "numerics::clebsch_map_up t2=" << t2 << endl;
3169 cout << "numerics::clebsch_map_up P2=";
3170 Num.print_system(P2, 1, 3);
3171 cout << "numerics::clebsch_map_up point: ";
3172 Num.print_system(pt2_coords, 1, 3);
3173 }
3174
3175
3176 double eval_t2;
3177
3178 eval_t2 = (((a * t2 + b) * t2) + c) * t2 + d;
3179
3180 if (f_v) {
3181 cout << "numerics::clebsch_map_up "
3182 "eval_t2=" << eval_t2 << endl;
3183 }
3184
3185
3186
3187 t3 = tr - t1 - t2;
3188
3189
3190 double eval_t3;
3191
3192 eval_t3 = (((a * t3 + b) * t3) + c) * t3 + d;
3193
3194 if (f_v) {
3195 cout << "numerics::clebsch_map_up "
3196 "eval_t3=" << eval_t3 << endl;
3197 }
3198
3199
3200
3201 if (f_v) {
3202 cout << "numerics::clebsch_map_up "
3203 "tr=" << tr << " t1=" << t1
3204 << " t2=" << t2 << " t3=" << t3 << endl;
3205 }
3206
3207 double Q[3];
3208
3209 for (i = 0; i < 3; i++) {
3210 Q[i] = N[i] + t3 * N[4 + i];
3211 }
3212
3213 if (f_v) {
3214 cout << "numerics::clebsch_map_up Q=";
3215 Num.print_system(Q, 1, 3);
3216 }
3217
3218 // delete two points:
3219 //S->nb_points -= 2;
3220
3221 Num.vec_copy(Q, pt_out, 3);
3222
3223
3224
3225 if (f_v) {
3226 cout << "numerics::clebsch_map_up done" << endl;
3227 }
3228}
3229
3230
3231void numerics::project_to_disc(int f_projection_on, int f_transition, int step, int nb_steps,
3232 double rad, double height, double x, double y, double &xp, double &yp)
3233{
3234 double f;
3235
3236 if (f_transition) {
3237 double x1, y1, d0, d1;
3238 f = rad / sqrt(height * height + x * x + y * y);
3239 x1 = x * f;
3240 y1 = y * f;
3241 d1 = (double) step / (double) nb_steps;
3242 d0 = 1. - d1;
3243 xp = x * d0 + x1 * d1;
3244 yp = y * d0 + y1 * d1;
3245 }
3246 else if (f_projection_on) {
3247 f = rad / sqrt(height * height + x * x + y * y);
3248 xp = x * f;
3249 yp = y * f;
3250 }
3251 else {
3252 xp = x;
3253 yp = y;
3254 }
3255}
3256
3257
3258}}
3259
3260
a collection of functions related to sorted vectors
various functions related to geometries
Definition: geometry.h:721
void AG_element_unrank(int q, int *v, int stride, int len, long int a)
numerical functions, mostly concerned with double
Definition: globals.h:129
int triangular_prism(double *P1, double *P2, double *P3, double *abc3, double *angles3, double *T3, int verbose_level)
Definition: numerics.cpp:458
void vec_add(double *a, double *b, double *c, int len)
Definition: numerics.cpp:82
double atan_xy(double x, double y)
Definition: numerics.cpp:938
void vec_linear_combination3(double c1, double *v1, double c2, double *v2, double c3, double *v3, double *w, int len)
Definition: numerics.cpp:69
void orthogonal_transformation_from_point_to_basis_vector(double *from, double *A, double *Av, int verbose_level)
Definition: numerics.cpp:1099
int intersect_line_and_line(double *line1_pt1_coords, double *line1_pt2_coords, double *line2_pt1_coords, double *line2_pt2_coords, double &lambda, double *pt_coords, int verbose_level)
Definition: numerics.cpp:2811
double distance_euclidean(double *x, double *y, int len)
Definition: numerics.cpp:984
void make_Rx(double *R, double chi)
Definition: numerics.cpp:920
void make_Rz(double *R, double phi)
Definition: numerics.cpp:885
void make_Ry(double *R, double psi)
Definition: numerics.cpp:902
void vec_scalar_multiple(double *a, double lambda, int len)
Definition: numerics.cpp:100
void plane_through_three_points(double *p1, double *p2, double *p3, double *n, double &d)
Definition: numerics.cpp:1051
void vec_linear_combination1(double c1, double *v1, double *w, int len)
Definition: numerics.cpp:49
int Gauss_elimination(double *A, int m, int n, int *base_cols, int f_complete, int verbose_level)
Definition: numerics.cpp:109
void substitute_quadric_linear(double *coeff_in, double *coeff_out, double *A4_inv, int verbose_level)
Definition: numerics.cpp:1224
void eigenvectors(double *A, double *Basis, int n, double *lambda, int verbose_level)
Definition: numerics.cpp:2087
void get_kernel(double *M, int m, int n, int *base_cols, int nb_base_cols, int &kernel_m, int &kernel_n, double *kernel)
Definition: numerics.cpp:282
void print_system(double *A, int m, int n)
Definition: numerics.cpp:270
void intersect_circle_line(double rad, double x0, double y0, double a, double b, double c, double &x1, double &y1, double &x2, double &y2)
Definition: numerics.cpp:2509
void vec_linear_combination(double c1, double *v1, double c2, double *v2, double *v3, int len)
Definition: numerics.cpp:59
double distance_from_origin(double x1, double x2, double x3)
Definition: numerics.cpp:998
void affine_combination(double *X, double *Y, int pt0, int pt1, int pt2, double alpha, int new_pt)
Definition: numerics.cpp:2538
void vec_scan_from_stream(std::istream &is, double *&v, int &len)
Definition: numerics.cpp:2232
void vec_print(double *a, int len)
Definition: numerics.cpp:35
void mult_matrix(double *v, double *R, double *vR)
Definition: numerics.cpp:841
int general_prism(double *Pts, int nb_pts, double *Pts_xy, double *abc3, double *angles3, double *T3, int verbose_level)
Definition: numerics.cpp:631
void eigenvalues(double *A, int n, double *lambda, int verbose_level)
Definition: numerics.cpp:2004
void transpose_matrix_nxn(double *A, double *At, int n)
Definition: numerics.cpp:1213
void local_coordinates_wrt_triangle(double *pt, double *triangle_points, double &x, double &y, int verbose_level)
Definition: numerics.cpp:2727
void vec_scan(const char *s, double *&v, int &len)
Definition: numerics.cpp:2218
void transform_llur_double(double *in, double *out, double &x, double &y)
Definition: numerics.cpp:2660
void project_to_disc(int f_projection_on, int f_transition, int step, int nb_steps, double rad, double height, double x, double y, double &xp, double &yp)
Definition: numerics.cpp:3231
void on_circle_int(int *Px, int *Py, int idx, int angle_in_degree, int rad)
Definition: numerics.cpp:2683
double bernoulli(double p, int n, int k)
Definition: numerics.cpp:2712
void make_unit_vector(double *v, int len)
Definition: numerics.cpp:1019
void mult_matrix_4x4(double *v, double *R, double *vR)
Definition: numerics.cpp:1187
int Null_space(double *M, int m, int n, double *K, int verbose_level)
Definition: numerics.cpp:371
void cross_product(double *u, double *v, double *n)
Definition: numerics.cpp:977
void adjust_coordinates_double(double *Px, double *Py, int *Qx, int *Qy, int N, double xmin, double ymin, double xmax, double ymax, int verbose_level)
Definition: numerics.cpp:2376
int line_centered(double *pt1_in, double *pt2_in, double *pt1_out, double *pt2_out, double r, int verbose_level)
Definition: numerics.cpp:1804
void output_double(double a, std::ostream &ost)
Definition: numerics.cpp:1177
void affine_pt1(int *Px, int *Py, int p0, int p1, int p2, double f1, int p3)
Definition: numerics.cpp:2556
void make_transform_t_varphi_u_double(int n, double *varphi, double *u, double *A, double *Av, int verbose_level)
Definition: numerics.cpp:1722
double power_of(double x, int n)
Definition: numerics.cpp:2691
void intersection_of_lines(double a1, double b1, double c1, double a2, double b2, double c2, double &x, double &y)
Definition: numerics.cpp:2447
void vec_subtract(double *a, double *b, double *c, int len)
Definition: numerics.cpp:91
void transform_llur(int *in, int *out, int &x, int &y)
Definition: numerics.cpp:2587
int line_centered_tolerant(double *pt1_in, double *pt2_in, double *pt1_out, double *pt2_out, double r, int verbose_level)
Definition: numerics.cpp:1896
void center_of_mass(double *Pts, int len, int *Pt_idx, int nb_pts, double *c)
Definition: numerics.cpp:1032
void transform_dist(int *in, int *out, int &x, int &y)
Definition: numerics.cpp:2627
void Line_through_points(double *X, double *Y, double *a, double *b, double *c, int pt1, int pt2, int line_idx)
Definition: numerics.cpp:2460
void affine_pt2(int *Px, int *Py, int p0, int p1, int p1b, double f1, int p2, int p2b, double f2, int p3)
Definition: numerics.cpp:2565
void clebsch_map_up(double *line1_pt1_coords, double *line1_pt2_coords, double *line2_pt1_coords, double *line2_pt2_coords, double *pt_in, double *pt_out, double *Cubic_coords_povray_ordering, int line1_idx, int line2_idx, int verbose_level)
Definition: numerics.cpp:2918
void substitute_quartic_linear_using_povray_ordering(double *coeff_in, double *coeff_out, double *A4_inv, int verbose_level)
Definition: numerics.cpp:1517
void Intersection_of_lines(double *X, double *Y, double *a, double *b, double *c, int l1, int l2, int pt)
Definition: numerics.cpp:2438
void transform_dist_x(int *in, int *out, int &x)
Definition: numerics.cpp:2640
void intersect_circle_line_through(double rad, double x0, double y0, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double &x1, double &y1, double &x2, double &y2)
Definition: numerics.cpp:2490
void transpose_matrix_4x4(double *A, double *At)
Definition: numerics.cpp:1202
void vec_swap(double *from, double *to, int len)
Definition: numerics.cpp:2192
void substitute_cubic_linear_using_povray_ordering(double *coeff_in, double *coeff_out, double *A4_inv, int verbose_level)
Definition: numerics.cpp:1345
void vec_normalize_from_back(double *v, int len)
Definition: numerics.cpp:415
void vec_normalize_to_minus_one_from_back(double *v, int len)
Definition: numerics.cpp:435
double norm_of_vector_2D(int x1, int x2, int y1, int y2)
Definition: numerics.cpp:2580
void line_through_points(double pt1_x, double pt1_y, double pt2_x, double pt2_y, double &a, double &b, double &c)
Definition: numerics.cpp:2468
void mult_matrix_matrix(double *A, double *B, double *C, int m, int n, int o)
Definition: numerics.cpp:855
double dot_product(double *u, double *v, int len)
Definition: numerics.cpp:965
void transform_dist_y(int *in, int *out, int &y)
Definition: numerics.cpp:2650
void vec_copy(double *from, double *to, int len)
Definition: numerics.cpp:2182
void on_circle_double(double *Px, double *Py, int idx, double angle_in_degree, double rad)
Definition: numerics.cpp:2548
void matrix_double_inverse(double *A, double *Av, int n, int verbose_level)
Definition: numerics.cpp:1752
domain for polynomials with double coefficients
Definition: ring_theory.h:465
void determinant_over_polynomial_ring(polynomial_double *P, polynomial_double *det, int n, int verbose_level)
void find_all_roots(polynomial_double *p, double *lambda, int verbose_level)
polynomials with double coefficients, related to class polynomial_double_domain
Definition: ring_theory.h:500
#define MINIMUM(x, y)
Definition: foundations.h:216
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define NEW_int(n)
Definition: foundations.h:625
#define ABS(x)
Definition: foundations.h:220
#define NEW_OBJECTS(type, n)
Definition: foundations.h:639
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define M_PI
Definition: foundations.h:237
#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
#define EPSILON
Definition: numerics.cpp:16
#define EPS
Definition: numerics.cpp:455