GIRAFFE Pipeline Reference Manual

gimath.c
1/*
2 * This file is part of the GIRAFFE Pipeline
3 * Copyright (C) 2002-2019 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24#include <math.h>
25
26#include <cxmemory.h>
27#include <cxmessages.h>
28
29#include "gimath.h"
30
31
41inline static cxdouble
42_giraffe_chebyshev2d_eval(cxdouble ax, cxdouble bx, cxdouble ay, cxdouble by,
43 const cpl_matrix* coeffs, cxdouble x, cxdouble y)
44{
45
46 cxint i, k;
47 cxint xorder;
48 cxint yorder;
49
50 const cxdouble* _coeffs = NULL;
51
52 cxdouble x_n = (2.0 * x - ax - bx) / (bx - ax);
53 cxdouble y_n = (2.0 * y - ay - by) / (by - ay);
54 cxdouble cx0 = 1.0;
55 cxdouble cx1 = x_n;
56 cxdouble sum = 0.;
57
58
59 cx_assert(coeffs != NULL);
60
61 xorder = cpl_matrix_get_nrow(coeffs);
62 yorder = cpl_matrix_get_ncol(coeffs);
63
64 _coeffs = cpl_matrix_get_data_const(coeffs);
65 cx_assert(_coeffs != NULL);
66
67 for (i = 0, k = 0; i < xorder; i++) {
68
69 register cxint j;
70
71 register cxdouble cx2 = 0.;
72 register cxdouble cy0 = 1.0;
73 register cxdouble cy1 = y_n;
74
75
76 if (i < 2) {
77 cx2 = cx0;
78 }
79 else {
80 cx2 = 2.0 * cx1 * x_n - cx0;
81 }
82
83 for (j = 0; j < yorder; j++) {
84
85 cxdouble cy2 = 0.;
86
87 if (j < 2) {
88 cy2 = cy0;
89 }
90 else {
91 cy2 = 2.0 * cy1 * y_n - cy0;
92 }
93
94 sum += cx2 * cy2 * _coeffs[k++];
95
96 cy0 = cy1;
97 cy1 = cy2;
98
99 }
100
101 cx0 = cx1;
102 cx1 = cx2;
103
104 }
105
106 return sum;
107
108}
109
110
111cxdouble
112giraffe_interpolate_linear(cxdouble x, cxdouble x_0, cxdouble y_0,
113 cxdouble x_1, cxdouble y_1)
114{
115
116 register cxdouble t = (x - x_0) / (x_1 - x_0);
117
118 return (1. - t) * y_0 + t * y_1;
119
120}
121
122
137cpl_matrix *
138giraffe_chebyshev_base1d(cxdouble start, cxdouble size, cxint order,
139 cpl_matrix *m_x)
140{
141
142 register cxint32 i, j, x_nrow, t_ncol;
143
144 register cxdouble xn, dsize2, d2size;
145
146 cxdouble *pmx, *pmt;
147
148 cpl_matrix *m_t = NULL;
149
150
151 /*
152 * Preprocessing
153 */
154
155 dsize2 = size / 2.0;
156 d2size = 2.0 / size;
157
158 x_nrow = cpl_matrix_get_nrow(m_x);
159
160 m_t = cpl_matrix_new(order, x_nrow);
161
162 if (m_t == NULL) {
163 return NULL;
164 }
165
166 t_ncol = x_nrow;
167
168 pmx = cpl_matrix_get_data(m_x);
169 pmt = cpl_matrix_get_data(m_t);
170
171
172 /*
173 * Processing
174 */
175
176 for (j = 0; j < t_ncol; j++) {
177
178 /*
179 * Normalize array between [-1,1]
180 * x[n] = (array[n] - start - size / 2.0) * 2.0 / size;
181 */
182
183 xn = (pmx[j] - start - dsize2) * d2size;
184
185 /*
186 * Ones for first column: T[0] = 1.0
187 */
188
189 pmt[j] = 1.0;
190
191 if (order < 2) {
192 continue;
193 }
194
195 /*
196 * X for second column: T[1] = x
197 */
198
199 pmt[j+t_ncol] = xn;
200
201 for (i = 2; i < order; i++) {
202
203 /*
204 * compute Chebyshev coefficients for following columns
205 * with: T[k] = 2 * x * T[k-1] - T[k-2]
206 */
207
208 pmt[j+i*t_ncol] = 2.0 * xn * pmt[j+(i-1)*t_ncol] -
209 pmt[j+(i-2)*t_ncol];
210
211 }
212 }
213
214 return m_t;
215
216}
217
218
239cpl_matrix *
240giraffe_chebyshev_base2d(cxdouble xstart, cxdouble ystart, cxdouble xsize,
241 cxdouble ysize, cxint xorder, cxint yorder,
242 cpl_matrix *m_x, cpl_matrix *m_y)
243{
244
245 register cxint32 i, j, k, l;
246
247 cxint32 x_nrow, y_nrow, /*t_nrow,*/ t_ncol;
248
249 register cxdouble dxsize2, d2xsize;
250 register cxdouble dysize2, d2ysize;
251 register cxdouble x_n, y_n;
252 register cxdouble bx0, bx1, bx2, by0, by1, by2;
253
254 cxdouble *pmx, *pmy, *pmt;
255
256 cpl_matrix *m_t = NULL;
257
258
259 /*
260 * Preprocsesing
261 */
262
263 dxsize2 = xsize / 2.0;
264 d2xsize = 2.0 / xsize;
265 dysize2 = ysize / 2.0;
266 d2ysize = 2.0 / ysize;
267
268 x_nrow = cpl_matrix_get_nrow(m_x);
269 y_nrow = cpl_matrix_get_nrow(m_y);
270
271 if (x_nrow != y_nrow) {
272 return NULL;
273 }
274
275 m_t = cpl_matrix_new(xorder * yorder, x_nrow);
276
277 if (m_t == NULL) {
278 return NULL;
279 }
280
281 /*t_nrow = cpl_matrix_get_nrow(m_t);*/
282 t_ncol = cpl_matrix_get_ncol(m_t);
283
284 pmx = cpl_matrix_get_data(m_x);
285 pmy = cpl_matrix_get_data(m_y);
286 pmt = cpl_matrix_get_data(m_t);
287
288
289 /*
290 * Processing
291 */
292
293 for (j = 0; j < t_ncol; j++) {
294
295 /*
296 * Normalize array between [-1,1]
297 * x[n] = (array[n] - start - size / 2.0) * 2.0 / size;
298 */
299
300 x_n = (pmx[j] - xstart - dxsize2) * d2xsize;
301 y_n = (pmy[j] - ystart - dysize2) * d2ysize;
302
303 bx0 = 1.0;
304 bx1 = x_n;
305
306 for (l = 0,i = 0; i < xorder; i++) {
307
308 if (i < 2) {
309 bx2 = bx0;
310 }
311 else {
312 bx2 = 2.0 * bx1 * x_n - bx0;
313 }
314
315 by0 = 1.0;
316 by1 = y_n;
317
318 for (k = 0; k < yorder; k++) {
319
320 if (k < 2) {
321 by2 = by0;
322 }
323 else {
324 by2 = 2.0 * by1 * y_n - by0;
325 }
326
327 pmt[j + (l++) * t_ncol] = bx2 * by2;
328
329 by0 = by1;
330 by1 = by2;
331
332 }
333
334 bx0 = bx1;
335 bx1 = bx2;
336
337 }
338 }
339
340 return m_t;
341
342}
343
344
363cpl_matrix *
364giraffe_chebyshev_base2dt(cxdouble xstart, cxdouble ystart, cxdouble xsize,
365 cxdouble ysize, cxint xorder, cxint yorder,
366 cpl_matrix *m_x, cpl_matrix *m_y)
367{
368
369 register cxint32 i, j, k, l;
370
371 cxint32 x_nrow, y_nrow, t_nrow, t_ncol;
372
373 register cxdouble dxsize2, d2xsize;
374 register cxdouble dysize2, d2ysize;
375 register cxdouble x_n, y_n;
376 register cxdouble bx0, bx1, bx2, by0, by1, by2;
377
378 cxdouble *pmx, *pmy, *pmt;
379
380 cpl_matrix *m_t = NULL;
381
382
383 /*
384 * Preprocess
385 */
386
387 dxsize2 = xsize / 2.0;
388 d2xsize = 2.0 / xsize;
389 dysize2 = ysize / 2.0;
390 d2ysize = 2.0 / ysize;
391
392 x_nrow = cpl_matrix_get_nrow(m_x);
393 y_nrow = cpl_matrix_get_nrow(m_y);
394
395 if (x_nrow != y_nrow) {
396 return NULL;
397 }
398
399 m_t = cpl_matrix_new(x_nrow, xorder * yorder);
400
401 if (m_t == NULL) {
402 return NULL;
403 }
404
405 t_nrow = cpl_matrix_get_nrow(m_t);
406 t_ncol = cpl_matrix_get_ncol(m_t);
407
408 pmx = cpl_matrix_get_data(m_x);
409 pmy = cpl_matrix_get_data(m_y);
410 pmt = cpl_matrix_get_data(m_t);
411
412
413 /*
414 * Process
415 */
416
417 for (j = 0; j < t_nrow; j++) {
418
419 /*
420 * Normalize array between [-1,1]
421 * x[n] = (array[n] - start - size / 2.0) * 2.0 / size;
422 */
423
424 x_n = (pmx[j] - xstart - dxsize2) * d2xsize;
425 y_n = (pmy[j] - ystart - dysize2) * d2ysize;
426
427 bx0 = 1.0;
428 bx1 = x_n;
429
430 for (l = 0, i = 0; i < xorder; i++) {
431
432 if (i < 2) {
433 bx2 = bx0;
434 }
435 else {
436 bx2 = 2.0 * bx1 * x_n - bx0;
437 }
438
439 by0 = 1.0;
440 by1 = y_n;
441
442 for (k = 0; k < yorder; k++) {
443
444 if (k < 2) {
445 by2 = by0;
446 }
447 else {
448 by2 = 2.0 * by1 * y_n - by0;
449 }
450
451 pmt[j * t_ncol + (l++)] = bx2 * by2;
452
453 by0 = by1;
454 by1 = by2;
455
456 }
457
458 bx0 = bx1;
459 bx1 = bx2;
460
461 }
462 }
463
464 return m_t;
465}
466
467
482cpl_matrix *
483giraffe_chebyshev_fit1d(cxdouble start, cxdouble size, cpl_matrix *m_c,
484 cpl_matrix *m_x)
485{
486
487 register cxint32 i, j, jj, order;
488
489 cxint32 x_nrow, c_nrow, c_ncol, t_nrow, t_ncol;
490
491 register cxdouble xn;
492 register cxdouble dsize2, d2size;
493 register cxdouble *f0 = NULL;
494 register cxdouble *t0 = NULL;
495 register cxdouble *c0 = NULL;
496
497 cxdouble *pmc, *pmx, *pmt, *pmf;
498
499 cpl_matrix *m_t; /* 1D Chabyshev base transposed */
500 cpl_matrix *m_f; /* 1D Chabyshev fit */
501
502
503 /*
504 * Preprocess
505 */
506
507 dsize2 = size / 2.0;
508 d2size = 2.0 / size;
509
510 c_nrow = cpl_matrix_get_nrow(m_c);
511 c_ncol = cpl_matrix_get_ncol(m_c);
512 x_nrow = cpl_matrix_get_nrow(m_x);
513 order = c_nrow;
514
515 m_t = cpl_matrix_new(x_nrow, order);
516
517 if (m_t == NULL) {
518 return NULL;
519 }
520
521 m_f = cpl_matrix_new(c_nrow, x_nrow);
522
523 if (m_f == NULL) {
524 cpl_matrix_delete(m_t);
525 return NULL;
526 }
527
528 t_nrow = cpl_matrix_get_nrow(m_t);
529 t_ncol = cpl_matrix_get_ncol(m_t);
530
531 pmc = cpl_matrix_get_data(m_c);
532 pmx = cpl_matrix_get_data(m_x);
533 pmt = cpl_matrix_get_data(m_t);
534 pmf = cpl_matrix_get_data(m_f);
535
536
537 /*
538 * Process
539 */
540
541 for (j = 0; j < t_nrow; j++) {
542
543 /*
544 * Normalize array between [-1,1]
545 * x[n] = (array[n] - start - size / 2.0) * 2.0 / size;
546 */
547
548 xn = (pmx[j] - start - dsize2) * d2size;
549
550 /*
551 * Ones for first column: T[0] = 1.0
552 */
553
554 jj = j * t_ncol;
555
556 pmt[jj] = 1.0;
557
558 if (order < 2) {
559 continue;
560 }
561
562 /*
563 * X for second column: T[1] = x
564 */
565
566 pmt[jj+1] = xn;
567
568 for (i = 2; i < order; i++) {
569
570 /*
571 * Compute Chebyshev coefficients for following columns
572 * with: T[k] = 2 * x * T[k-1] - T[k-2]
573 */
574
575 pmt[jj + i] = 2.0 * xn * pmt[jj + (i - 1)] - pmt[jj + (i - 2)];
576
577 }
578 }
579
580 for (i = 0, f0 = pmf ; i < c_nrow; i++) {
581 for (j = 0, t0 = pmt; j < t_nrow; j++, f0++) {
582 for (jj = 0, *f0 = 0, c0 = pmc + i * c_ncol; jj < c_ncol; jj++) {
583 *f0 += *c0++ * *t0++;
584 }
585 }
586 }
587
588 cpl_matrix_delete(m_t);
589
590 return m_f;
591
592}
593
594
612cpl_matrix *
613giraffe_chebyshev_fit2d(cxdouble xstart, cxdouble ystart, cxdouble xsize,
614 cxdouble ysize, const cpl_matrix* m_c,
615 const cpl_matrix* m_x, const cpl_matrix* m_y)
616{
617
618 cxint i;
619 cxint nx;
620
621 const cxdouble* _x = NULL;
622 const cxdouble* _y = NULL;
623
624 cxdouble bx = xstart + xsize;
625 cxdouble by = ystart + ysize;
626
627 cpl_matrix *f = NULL;
628
629
630 if (m_c == NULL || m_x == NULL || m_y == NULL) {
631 return NULL;
632 }
633
634 nx = cpl_matrix_get_nrow(m_x);
635
636 if (nx != cpl_matrix_get_nrow(m_y)) {
637 return NULL;
638 }
639
640 f = cpl_matrix_new(nx, 1);
641
642 if (f == NULL) {
643 return NULL;
644 }
645
646 _x = cpl_matrix_get_data_const(m_x);
647 _y = cpl_matrix_get_data_const(m_y);
648
649
650 for (i = 0; i < nx; i++) {
651
652 cxdouble sum = _giraffe_chebyshev2d_eval(xstart, bx, ystart, by,
653 m_c, _x[i], _y[i]);
654 cpl_matrix_set(f, i, 0, sum);
655
656 }
657
658 return f;
659
660}
661
662
663#define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;}
664
692cxint
693giraffe_gauss_jordan(
694 cpl_matrix *mA,
695 cxint n,
696 cpl_matrix *mB,
697 cxint m
698) {
699
700 cxint *indxc, *indxr, *ipiv;
701 register cxint i, icol = 0, irow = 0, j, jj, k, l, ll;
702 register cxdouble big, dum, pivinv, swap;
703
704 cxdouble *pd_mA = NULL, *pd_mB = NULL;
705 cxint nr_mA, nr_mB;
706
707 pd_mA = cpl_matrix_get_data(mA);
708 pd_mB = cpl_matrix_get_data(mB);
709 nr_mA = cpl_matrix_get_nrow(mA);
710 nr_mB = cpl_matrix_get_nrow(mB);
711
712 indxc = (cxint *) cx_calloc(n, sizeof(cxint));
713 indxr = (cxint *) cx_calloc(n, sizeof(cxint));
714 ipiv = (cxint *) cx_calloc(n, sizeof(cxint));
715
716 for (i = 0; i < n; i++) {
717 /* main loop over the columns to be reduced */
718 big = 0.0;
719 for (j = 0; j < n; j++) {
720 /* outer loop of the search of a pivot element */
721 jj = j * nr_mA;
722 if (ipiv[j] != 1) {
723 for (k = 0; k < n; k++) {
724 if (ipiv[k] == 0) {
725 if (fabs(pd_mA[jj + k]) >= big) {
726 big = fabs(pd_mA[jj + k]);
727 irow = j;
728 icol = k;
729 }
730 } else if (ipiv[k] > 1) {
731 cx_free((cxptr) ipiv);
732 cx_free((cxptr) indxr);
733 cx_free((cxptr) indxc);
734 /* matrix singular 1 */
735 return -1;
736 }
737 }
738 }
739 }
740
741 /* We now have the pivot, so we interchange rows, if needed, to put
742 * the pivot element on the diagonal. The columns are not physically
743 * interchanged, only relabeled
744 */
745
746 ++(ipiv[icol]);
747
748 if (irow != icol) {
749 for (l = 0; l < n; l++) {
750 SWAP(pd_mA[irow * nr_mA + l], pd_mA[icol * nr_mA + l])
751 }
752 for (l = 0; l < m; l++) {
753 SWAP(pd_mB[irow * nr_mB + l], pd_mB[icol * nr_mB + l])
754 }
755 }
756
757 indxr[i] = irow;
758 indxc[i] = icol;
759
760 if (pd_mA[icol * nr_mA + icol] == 0.0) {
761 cx_free((cxptr) ipiv);
762 cx_free((cxptr) indxr);
763 cx_free((cxptr) indxc);
764 /* matrix singular 2 */
765 return -2;
766 }
767
768 /* divide the pivot row by the pivot element */
769 pivinv = 1.0 / pd_mA[icol * nr_mA + icol];
770 pd_mA[icol * nr_mA + icol] = 1.0;
771
772 for (l = 0; l < n; l++) {
773 pd_mA[icol * nr_mA + l] *= pivinv;
774 }
775
776 for (l = 0; l < m; l++) {
777 pd_mB[icol * nr_mB + l] *= pivinv;
778 }
779
780 for (ll = 0; ll < n; ll++) {
781 /* reduce the rows... except for the pivot one */
782 if (ll != icol) {
783 dum = pd_mA[ll * nr_mA + icol];
784 pd_mA[ll * nr_mA + icol] = 0.0;
785
786 for (l = 0; l < n; l++) {
787 pd_mA[ll * nr_mA + l] -= pd_mA[icol * nr_mA + l] * dum;
788 }
789
790 for (l = 0; l < m; l++) {
791 pd_mB[ll * nr_mB + l] -= pd_mB[icol * nr_mB + l] * dum;
792 }
793 }
794 }
795 }
796
797 cx_free((cxptr) ipiv);
798
799 /* unscramble the solution in view of the column interchanges */
800 for (l = (n-1); l >= 0; l--) {
801 if (indxr[l] != indxc[l]) {
802 for (k = 0; k < n; k++) {
803 SWAP(pd_mA[k * nr_mA + indxr[l]], pd_mA[k * nr_mA + indxc[l]]);
804 }
805 }
806 }
807 cx_free((cxptr)indxr);
808 cx_free((cxptr)indxc);
809
810 return 0;
811
812} /* end of gauss_jordan() */
813
814#undef SWAP
815
842void
843giraffe_compute_image_coordinates(
844 cxlong nx,
845 cxlong ny,
846 cpl_matrix *mXi,
847 cpl_matrix *mYi
848) {
849
850 register cxlong i, j, k;
851 register cxdouble *pd_mXi = NULL, *pd_mYi = NULL;
852
853 if ((mXi != NULL) && (mYi != NULL)) {
854
855 pd_mXi = cpl_matrix_get_data(mXi);
856 pd_mYi = cpl_matrix_get_data(mYi);
857
858 for (j = 0; j < nx; j++) {
859 for (k = 0; k < ny; k++) {
860 i = k + j * ny;
861 pd_mXi[i] = (cxdouble) j;
862 pd_mYi[i] = (cxdouble) k;
863 }
864 }
865 } else if (mXi != NULL) {
866
867 pd_mXi = cpl_matrix_get_data(mXi);
868
869 for (j = 0; j < nx; j++) {
870 for (k = 0; k < ny; k++) {
871 i = k + j * ny;
872 pd_mXi[i] = (cxdouble) j;
873 }
874 }
875 } else if (mYi != NULL) {
876
877 pd_mYi = cpl_matrix_get_data(mYi);
878
879 for (j = 0; j < nx; j++) {
880 for (k = 0; k < ny; k++) {
881 i = k + j * ny;
882 pd_mYi[i] = (cxdouble) k;
883 }
884 }
885 }
886
887 return;
888
889} /* end of giraffe_compute_image_coordinates() */
890

This file is part of the GIRAFFE Pipeline Reference Manual 2.18.0.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Feb 21 2025 02:35:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004