00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 #ifdef HAVE_CONFIG_H
00132 # include <config.h>
00133 #endif
00134
00135
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 #define COLUMN_ORDER1 "Order1"
00166 #define COLUMN_ORDER2 "Order2"
00167 #define COLUMN_COEFF "Coeff"
00168
00171
00172
00173
00174 #include <uves_utils_polynomial.h>
00175
00176 #include <uves_utils.h>
00177 #include <uves_utils_wrappers.h>
00178 #include <uves_dump.h>
00179 #include <uves_msg.h>
00180 #include <uves_error.h>
00181
00182 #include <cpl.h>
00183
00184
00185
00186
00189 struct _polynomial
00190 {
00192 cpl_polynomial *pol;
00193
00195 cpl_vector *vec;
00196 double *vec_data;
00197
00198 int dimension;
00199
00201 double *shift;
00202
00204 double *scale;
00205 };
00206
00207
00208
00209
00210
00221
00222 polynomial *
00223 uves_polynomial_new(const cpl_polynomial *pol)
00224 {
00225 polynomial *p = NULL;
00226 int i;
00227
00228
00229 assure(pol != NULL, CPL_ERROR_ILLEGAL_INPUT, "Null polynomial");
00230
00231
00232 p = cpl_calloc(1, sizeof(polynomial)) ;
00233 assure_mem( p );
00234
00235 check( p->dimension = cpl_polynomial_get_dimension(pol), "Error reading dimension");
00236
00237
00238 p->vec = cpl_vector_new(p->dimension);
00239 assure_mem( p->vec );
00240 p->vec_data = cpl_vector_get_data(p->vec);
00241
00242
00243 p->shift = cpl_calloc(p->dimension + 1, sizeof(double));
00244 assure_mem( p->shift );
00245
00246 p->scale = cpl_malloc((p->dimension + 1) * sizeof(double));
00247 assure_mem( p->scale );
00248 for (i = 0; i <= p->dimension; i++)
00249 p->scale[i] = 1.0;
00250
00251 check( p->pol = cpl_polynomial_duplicate(pol), "Error copying polynomial");
00252
00253 cleanup:
00254 if (cpl_error_get_code() != CPL_ERROR_NONE)
00255 uves_polynomial_delete(&p);
00256
00257 return p;
00258 }
00259
00260
00268
00269 polynomial *
00270 uves_polynomial_new_zero(int dim)
00271 {
00272 polynomial *result = NULL;
00273 cpl_polynomial *p = NULL;
00274
00275 assure( dim >= 1, CPL_ERROR_ILLEGAL_INPUT, "Illegal dimension: %d", dim);
00276
00277 p = cpl_polynomial_new(dim);
00278 assure_mem( p );
00279
00280 result = uves_polynomial_new(p);
00281 assure_mem( result );
00282
00283 cleanup:
00284 uves_free_polynomial(&p);
00285
00286 return result;
00287 }
00288
00289
00296
00297 void
00298 uves_polynomial_delete(polynomial **p)
00299 {
00300 uves_polynomial_delete_const((const polynomial **)p);
00301 }
00302
00303
00310
00311 void
00312 uves_polynomial_delete_const(const polynomial **p)
00313 {
00314 if (*p == NULL) return;
00315 cpl_polynomial_delete((*p)->pol);
00316 cpl_vector_delete((*p)->vec);
00317 cpl_free((*p)->shift);
00318 cpl_free((*p)->scale);
00319 uves_free(*p);
00320 *p = NULL;
00321 return;
00322 }
00323
00329
00330 int
00331 uves_polynomial_get_degree(const polynomial *p)
00332 {
00333 int result = -1;
00334 assure( p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00335
00336 result = cpl_polynomial_get_degree(p->pol);
00337
00338 cleanup:
00339 return result;
00340 }
00341
00342
00348
00349 polynomial *
00350 uves_polynomial_duplicate(const polynomial *p)
00351 {
00352 polynomial *result = NULL;
00353 int dimension;
00354 int i;
00355
00356 assure( p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00357 dimension = uves_polynomial_get_dimension(p);
00358
00359 check( result = uves_polynomial_new(p->pol),
00360 "Error allocating polynomial");
00361
00362 for (i = 0; i <= dimension; i++)
00363 {
00364 result->shift[i] = p->shift[i];
00365 result->scale[i] = p->scale[i];
00366 }
00367
00368 cleanup:
00369 if (cpl_error_get_code() != CPL_ERROR_NONE)
00370 {
00371 uves_polynomial_delete(&result);
00372 return NULL;
00373 }
00374
00375 return result;
00376 }
00377
00378
00379
00390
00391 cpl_table *
00392 uves_polynomial_convert_to_table(const polynomial *p)
00393 {
00394 cpl_table *t = NULL;
00395 int degree;
00396 int i, j, row;
00397
00398
00399 assure( p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00400 assure( uves_polynomial_get_dimension(p) == 2,
00401 CPL_ERROR_ILLEGAL_INPUT, "Polynomial must be 2D");
00402
00403 degree = cpl_polynomial_get_degree(p->pol);
00404
00405
00406
00407 t = cpl_table_new(3 + 3 + (degree + 1)*(degree + 2)/2);
00408 cpl_table_new_column(t, COLUMN_ORDER1, CPL_TYPE_INT);
00409 cpl_table_new_column(t, COLUMN_ORDER2, CPL_TYPE_INT);
00410 cpl_table_new_column(t, COLUMN_COEFF , CPL_TYPE_DOUBLE);
00411
00412 row = 0;
00413
00414
00415 cpl_table_set_int (t, COLUMN_ORDER1, row, -1);
00416 cpl_table_set_int (t, COLUMN_ORDER2, row, -1);
00417 cpl_table_set_double(t, COLUMN_COEFF , row, p->shift[0]); row++;
00418
00419 cpl_table_set_int (t, COLUMN_ORDER1, row, -1);
00420 cpl_table_set_int (t, COLUMN_ORDER2, row, -1);
00421 cpl_table_set_double(t, COLUMN_COEFF , row, p->shift[1]); row++;
00422
00423 cpl_table_set_int (t, COLUMN_ORDER1, row, -1);
00424 cpl_table_set_int (t, COLUMN_ORDER2, row, -1);
00425 cpl_table_set_double(t, COLUMN_COEFF , row, p->shift[2]); row++;
00426
00427
00428 cpl_table_set_int (t, COLUMN_ORDER1, row, -1);
00429 cpl_table_set_int (t, COLUMN_ORDER2, row, -1);
00430 cpl_table_set_double(t, COLUMN_COEFF, row, p->scale[0]); row++;
00431
00432 cpl_table_set_int (t, COLUMN_ORDER1, row, -1);
00433 cpl_table_set_int (t, COLUMN_ORDER2, row, -1);
00434 cpl_table_set_double(t, COLUMN_COEFF, row, p->scale[1]); row++;
00435
00436 cpl_table_set_int (t, COLUMN_ORDER1, row, -1);
00437 cpl_table_set_int (t, COLUMN_ORDER2, row, -1);
00438 cpl_table_set_double(t, COLUMN_COEFF, row, p->scale[2]); row++;
00439
00440
00441 for (i = 0; i <= degree; i++){
00442 for (j = 0; j+i <= degree; j++){
00443 double coeff;
00444 cpl_size power[2];
00445 power[0] = i;
00446 power[1] = j;
00447
00448 coeff = cpl_polynomial_get_coeff(p->pol, power);
00449 cpl_table_set_int (t, COLUMN_ORDER1, row, power[0]);
00450 cpl_table_set_int (t, COLUMN_ORDER2, row, power[1]);
00451 cpl_table_set_double(t, COLUMN_COEFF , row, coeff);
00452
00453 row++;
00454 }
00455 }
00456
00457 cleanup:
00458 return t;
00459 }
00460
00461
00470
00471 polynomial *
00472 uves_polynomial_convert_from_table(cpl_table *t)
00473 {
00474 polynomial *p = NULL;
00475 cpl_polynomial *pol = NULL;
00476 cpl_type type;
00477 int i;
00478
00479
00480 check( pol = cpl_polynomial_new(2), "Error initializing polynomial");
00481
00482
00483 assure(t != NULL, CPL_ERROR_NULL_INPUT, "Null table");
00484 assure(cpl_table_has_column(t, COLUMN_ORDER1), CPL_ERROR_ILLEGAL_INPUT,
00485 "No '%s' column found in table", COLUMN_ORDER1);
00486 assure(cpl_table_has_column(t, COLUMN_ORDER2), CPL_ERROR_ILLEGAL_INPUT,
00487 "No '%s' column found in table", COLUMN_ORDER2);
00488 assure(cpl_table_has_column(t, COLUMN_COEFF ), CPL_ERROR_ILLEGAL_INPUT,
00489 "No '%s' column found in table", COLUMN_COEFF );
00490
00491 type = cpl_table_get_column_type(t, COLUMN_ORDER1);
00492 assure(type == CPL_TYPE_INT , CPL_ERROR_INVALID_TYPE,
00493 "Column '%s' has type %s. Integer expected", COLUMN_ORDER1,
00494 uves_tostring_cpl_type(type));
00495
00496 type = cpl_table_get_column_type(t, COLUMN_ORDER2);
00497 assure(type == CPL_TYPE_INT , CPL_ERROR_INVALID_TYPE,
00498 "Column '%s' has type %s. Integer expected", COLUMN_ORDER2,
00499 uves_tostring_cpl_type(type));
00500
00501 type = cpl_table_get_column_type(t, COLUMN_COEFF);
00502 assure(type == CPL_TYPE_DOUBLE, CPL_ERROR_INVALID_TYPE,
00503 "Column '%s' has type %s. Double expected", COLUMN_COEFF ,
00504 uves_tostring_cpl_type(type));
00505
00506 assure(cpl_table_get_nrow(t) > 1 + 2 + 1 + 2, CPL_ERROR_ILLEGAL_INPUT,
00507 "Table must contain at least one coefficient");
00508
00509
00510 for(i = 3 + 3; i < cpl_table_get_nrow(t); i++) {
00511 double coeff;
00512 cpl_size power[2];
00513
00514 check(( power[0] = cpl_table_get_int(t, COLUMN_ORDER1, i, NULL),
00515 power[1] = cpl_table_get_int(t, COLUMN_ORDER2, i, NULL),
00516 coeff = cpl_table_get_double(t, COLUMN_COEFF , i, NULL)),
00517 "Error reading table row %d", i);
00518
00519 uves_msg_debug("Pol.coeff.(%" CPL_SIZE_FORMAT ", %" CPL_SIZE_FORMAT ") = %e", power[0], power[1], coeff);
00520
00521 check( cpl_polynomial_set_coeff(pol, power, coeff), "Error creating polynomial");
00522 }
00523 p = uves_polynomial_new(pol);
00524
00525
00526 uves_polynomial_rescale(p, 0, cpl_table_get_double( t, COLUMN_COEFF, 3, NULL));
00527 uves_polynomial_rescale(p, 1, cpl_table_get_double( t, COLUMN_COEFF, 4, NULL));
00528 uves_polynomial_rescale(p, 2, cpl_table_get_double( t, COLUMN_COEFF, 5, NULL));
00529 uves_polynomial_shift (p, 0, cpl_table_get_double( t, COLUMN_COEFF, 0, NULL));
00530 uves_polynomial_shift (p, 1, cpl_table_get_double( t, COLUMN_COEFF, 1, NULL));
00531 uves_polynomial_shift (p, 2, cpl_table_get_double( t, COLUMN_COEFF, 2, NULL));
00532
00533 cleanup:
00534 uves_free_polynomial(&pol);
00535 if (cpl_error_get_code() != CPL_ERROR_NONE)
00536 uves_polynomial_delete(&p);
00537
00538 return p;
00539 }
00540
00541
00542
00548
00549 int
00550 uves_polynomial_get_dimension(const polynomial *p)
00551 {
00552 int dim = -1;
00553 assure(p != NULL, CPL_ERROR_ILLEGAL_INPUT, "Null polynomial");
00554
00555
00556 dim = p->dimension;
00557
00558 cleanup:
00559 return dim;
00560 }
00561
00562
00570
00571 void uves_polynomial_dump(const polynomial *p, FILE *stream)
00572 {
00573 if (p == NULL)
00574 fprintf(stream, "Null polynomial\n");
00575 else {
00576 int i;
00577 cpl_polynomial_dump(p->pol, stream);
00578 fprintf(stream, "shift_y \t= %f \tscale_y \t= %f\n", p->shift[0], p->scale[0]);
00579 for (i = 1; i <= uves_polynomial_get_dimension(p); i++)
00580 {
00581 fprintf(stream, "shift_x%d \t= %f \tscale_x%d \t= %f\n",
00582 i, p->shift[i], i, p->scale[i]);
00583 }
00584 }
00585 return;
00586 }
00587
00588
00602
00603 cpl_error_code
00604 uves_polynomial_rescale(polynomial *p, int varno, double scale)
00605 {
00606 assure(p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00607 assure(0 <= varno && varno <= uves_polynomial_get_dimension(p),
00608 CPL_ERROR_ILLEGAL_INPUT, "Illegal variable number: %d", varno);
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 p->shift[varno] *= scale;
00623 p->scale[varno] *= scale;
00624
00625 cleanup:
00626 return cpl_error_get_code();
00627 }
00628
00629
00643
00644 cpl_error_code
00645 uves_polynomial_shift(polynomial *p, int varno, double shift)
00646 {
00647 assure(p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00648 assure(0 <= varno && varno <= uves_polynomial_get_dimension(p),
00649 CPL_ERROR_ILLEGAL_INPUT, "Illegal variable number: %d", varno);
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 p->shift[varno] += shift;
00661
00662 cleanup:
00663 return cpl_error_get_code();
00664 }
00665
00666
00675
00676 double
00677 uves_polynomial_evaluate_1d(const polynomial *p, double x)
00678 {
00679 double result = 0;
00680
00681 assure(p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00682 assure(uves_polynomial_get_dimension(p) == 1,
00683 CPL_ERROR_ILLEGAL_INPUT, "Polynomial must be 1d");
00684
00685 check( result =
00686 cpl_polynomial_eval_1d(p->pol, (x - p->shift[1])/p->scale[1], NULL)
00687 * p->scale[0] + p->shift[0],
00688 "Could not evaluate polynomial");
00689
00690 cleanup:
00691 return result;
00692 }
00693
00694
00695
00705
00706
00707 double
00708 uves_polynomial_evaluate_2d(const polynomial *p, double x1, double x2)
00709 {
00710 double result = 0;
00711
00712 assure(p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00713 assure(p->dimension == 2, CPL_ERROR_ILLEGAL_INPUT,
00714 "Polynomial must be 2d. It's %dd", p->dimension);
00715 {
00716 double scale = p->scale[0];
00717 double shift = p->shift[0];
00718
00719
00720
00721 p->vec_data[0] = (x1 - p->shift[1]) / p->scale[1];
00722 p->vec_data[1] = (x2 - p->shift[2]) / p->scale[2];
00723
00724 result = cpl_polynomial_eval(p->pol, p->vec) * scale + shift;
00725 }
00726
00727 cleanup:
00728 return result;
00729 }
00730
00731
00744
00745 double
00746 uves_polynomial_solve_1d(const polynomial *p, double value, double guess, int multiplicity)
00747 {
00748 double result = 0;
00749 cpl_size power[1];
00750 double coeff0;
00751
00752 assure(p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00753 assure(uves_polynomial_get_dimension(p) == 1, CPL_ERROR_ILLEGAL_INPUT,
00754 "Polynomial must be 1d");
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 power[0] = 0;
00765 check(( coeff0 = cpl_polynomial_get_coeff(p->pol, power),
00766 cpl_polynomial_set_coeff(p->pol, power, coeff0 + (p->shift[0] - value)/p->scale[0])),
00767 "Error setting coefficient");
00768
00769 check( cpl_polynomial_solve_1d(p->pol, (guess - p->shift[1]) / p->scale[1],
00770 &result, multiplicity), "Could not find root");
00771
00772 cpl_polynomial_set_coeff(p->pol, power, coeff0);
00773
00774
00775 result = result * p->scale[1] + p->shift[1];
00776
00777 cleanup:
00778 return result;
00779 }
00780
00781
00798
00799 double
00800 uves_polynomial_solve_2d(const polynomial *p, double value, double guess,
00801 int multiplicity, int varno, double x_value)
00802 {
00803 double result = 0;
00804 polynomial *pol_1d = NULL;
00805
00806 assure( 1 <= varno && varno <= 2, CPL_ERROR_ILLEGAL_INPUT,
00807 "Illegal variable number: %d", varno);
00808
00809 check( pol_1d = uves_polynomial_collapse(p, varno, x_value),
00810 "Could not collapse polynomial");
00811
00812 check( result = uves_polynomial_solve_1d(pol_1d, value, guess, multiplicity),
00813 "Could not find root");
00814
00815 cleanup:
00816 uves_polynomial_delete(&pol_1d);
00817 return result;
00818 }
00819
00820
00829
00830 double
00831 uves_polynomial_derivative_2d(const polynomial *p, double x1, double x2, int varno)
00832 {
00833 double result = 0;
00834 cpl_size power[2];
00835
00836 assure (1 <= varno && varno <= 2, CPL_ERROR_ILLEGAL_INPUT,
00837 "Illegal variable number (%d)", varno);
00838
00839 assure(p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00840 assure(uves_polynomial_get_dimension(p) == 2, CPL_ERROR_ILLEGAL_INPUT,
00841 "Polynomial must be 2d. It's %dd", uves_polynomial_get_dimension(p));
00842
00843
00844
00845
00846
00847
00848
00849 x1 = (x1 - p->shift[1])/p->scale[1];
00850 x2 = (x2 - p->shift[2])/p->scale[2];
00851
00852
00853
00854
00855 {
00856 int degree = cpl_polynomial_get_degree(p->pol);
00857 double yj = 1;
00858 int i, j;
00859
00860 result = 0;
00861 for (j = 0, yj = 1;
00862 j <= degree; j++,
00863 yj *= (varno == 1) ? x2 : x1)
00864 {
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 double sum = 0;
00876 for (i = degree; i >= 1; i--)
00877 {
00878 double c_ij;
00879
00880 power[0] = (varno == 1) ? i : j;
00881 power[1] = (varno == 1) ? j : i;
00882
00883 c_ij = cpl_polynomial_get_coeff(p->pol, power);
00884
00885 sum += (i * c_ij);
00886 if (i >= 2) sum *= (varno == 1) ? x1 : x2;
00887 }
00888
00889
00890 result += yj * sum;
00891 }
00892 }
00893
00894 result *= p->scale[0];
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 cleanup:
00908 return result;
00909 }
00910
00911
00918
00919 double
00920 uves_polynomial_derivative_1d(const polynomial *p, double x)
00921 {
00922 double result = 0;
00923 double dummy;
00924
00925 assure(p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00926 assure(uves_polynomial_get_dimension(p) == 1,
00927 CPL_ERROR_ILLEGAL_INPUT, "Polynomial must be 1d");
00928
00929 check( dummy = cpl_polynomial_eval_1d(p->pol, (x - p->shift[1])/p->scale[1], &result),
00930 "Error evaluating derivative");
00931
00932 cleanup:
00933 return result;
00934 }
00935
00936
00943
00944 polynomial *
00945 uves_polynomial_add_2d(const polynomial *p1, const polynomial *p2)
00946 {
00947 polynomial *result = NULL;
00948 cpl_polynomial *pol = NULL;
00949
00950 assure(p1 != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00951 assure(p2 != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
00952 assure(uves_polynomial_get_dimension(p1) == 2,
00953 CPL_ERROR_ILLEGAL_INPUT, "Polynomial must be 2d");
00954 assure(uves_polynomial_get_dimension(p2) == 2,
00955 CPL_ERROR_ILLEGAL_INPUT, "Polynomial must be 2d");
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 {
00967 int degree, i, j;
00968
00969 degree = uves_max_int(uves_polynomial_get_degree(p1),
00970 uves_polynomial_get_degree(p2));
00971
00972 pol = cpl_polynomial_new(2);
00973 for (i = 0; i <= degree; i++)
00974 for (j = 0; j <= degree; j++) {
00975 double coeff1, coeff2;
00976 cpl_size power[2];
00977
00978
00979 coeff1 = uves_polynomial_get_coeff_2d(p1, i, j);
00980 coeff2 = uves_polynomial_get_coeff_2d(p2, i, j);
00981
00982 power[0] = i;
00983 power[1] = j;
00984 cpl_polynomial_set_coeff(pol, power, coeff1 + coeff2);
00985 }
00986 }
00987
00988 result = uves_polynomial_new(pol);
00989
00990 cleanup:
00991 uves_free_polynomial(&pol);
00992 return result;
00993 }
00994
00995
01008
01009 static cpl_error_code
01010 derivative_cpl_polynomial(cpl_polynomial *p, int varno)
01011 {
01012 int dimension, degree;
01013 int i, j;
01014 cpl_size power[2];
01015
01016 assure(p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
01017 dimension = cpl_polynomial_get_dimension(p);
01018 degree = cpl_polynomial_get_degree(p);
01019 assure( 1 <= dimension && dimension <= 2, CPL_ERROR_ILLEGAL_INPUT,
01020 "Illegal dimension: %d", dimension);
01021 assure( 1 <= varno && varno <= dimension, CPL_ERROR_ILLEGAL_INPUT,
01022 "Illegal variable number: %d", varno);
01023
01024 if (dimension == 1)
01025 {
01026
01027 for(i = 0; i <= degree; i++)
01028 {
01029 double coeff;
01030 power[0] = i+1;
01031
01032
01033 coeff = cpl_polynomial_get_coeff(p, power);
01034
01035 power[0] = i;
01036 cpl_polynomial_set_coeff(p, power, (i+1) * coeff);
01037 }
01038 }
01039
01040 if (dimension == 2)
01041 {
01042
01043 for(i = 0; i <= degree; i++)
01044 {
01045 for(j = 0; i + j <= degree; j++)
01046 {
01047 double coeff;
01048 power[varno - 1] = i+1;
01049 power[2 - varno] = j;
01050
01051 coeff = cpl_polynomial_get_coeff(p, power);
01052
01053 power[varno - 1] = i;
01054
01055 cpl_polynomial_set_coeff(p, power, (i+1) * coeff);
01056 }
01057 }
01058 }
01059
01060 cleanup:
01061 return cpl_error_get_code();
01062 }
01063
01064
01074
01075 cpl_error_code
01076 uves_polynomial_derivative(polynomial *p, int varno)
01077 {
01078 int dimension;
01079
01080 assure( p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
01081 check ( dimension = uves_polynomial_get_dimension(p), "Error reading dimension");
01082 assure( 1 <= varno && varno <= dimension, CPL_ERROR_ILLEGAL_INPUT,
01083 "Illegal variable number: %d", varno);
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 p->shift[0] = 0;
01098 p->scale[0] = p->scale[0] / p->scale[varno];
01099
01100 check( derivative_cpl_polynomial(p->pol, varno),
01101 "Error calculating derivative of CPL-polynomial");
01102
01103 cleanup:
01104 return cpl_error_get_code();
01105 }
01106
01107
01108
01117
01118 double
01119 uves_polynomial_get_coeff_2d(const polynomial *p, int degree1, int degree2)
01120 {
01121 polynomial *pp = NULL;
01122 int dimension;
01123 double result = 0;
01124 double factorial;
01125
01126 assure( p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
01127 check ( dimension = uves_polynomial_get_dimension(p), "Error reading dimension");
01128 assure(dimension == 2, CPL_ERROR_ILLEGAL_INPUT, "Illegal dimension: %d", dimension);
01129 assure( 0 <= degree1, CPL_ERROR_ILLEGAL_INPUT, "Illegal degree: %d", degree1);
01130 assure( 0 <= degree2, CPL_ERROR_ILLEGAL_INPUT, "Illegal degree: %d", degree2);
01131
01132
01133
01134
01135
01136
01137 pp = uves_polynomial_duplicate(p);
01138
01139 factorial = 1;
01140 while(degree1 > 0)
01141 {
01142 check( uves_polynomial_derivative(pp, 1), "Error calculating derivative");
01143
01144 factorial *= degree1;
01145 degree1 -= 1;
01146 }
01147
01148 while(degree2 > 0)
01149 {
01150 check( uves_polynomial_derivative(pp, 2), "Error calculating derivative");
01151
01152 factorial *= degree2;
01153 degree2 -= 1;
01154 }
01155
01156 check( result = uves_polynomial_evaluate_2d(pp, 0, 0) / factorial,
01157 "Error evaluating polynomial");
01158
01159 cleanup:
01160 uves_polynomial_delete(&pp);
01161 return result;
01162 }
01163
01173
01174 double
01175 uves_polynomial_get_coeff_1d(const polynomial *p, int degree)
01176 {
01177 polynomial *pp = NULL;
01178 int dimension;
01179 double result = 0;
01180 double factorial;
01181
01182 assure( p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
01183 check ( dimension = uves_polynomial_get_dimension(p), "Error reading dimension");
01184 assure(dimension == 1, CPL_ERROR_ILLEGAL_INPUT, "Illegal dimension: %d", dimension);
01185 assure( 0 <= degree, CPL_ERROR_ILLEGAL_INPUT, "Illegal degree: %d", degree);
01186
01187
01188
01189
01190
01191
01192 pp = uves_polynomial_duplicate(p);
01193
01194 factorial = 1;
01195 while(degree > 0)
01196 {
01197 check( uves_polynomial_derivative(pp, 1), "Error calculating derivative");
01198
01199 factorial *= degree;
01200 degree -= 1;
01201 }
01202
01203 check( result = uves_polynomial_evaluate_1d(pp, 0) / factorial,
01204 "Error evaluating polynomial");
01205
01206 cleanup:
01207 uves_polynomial_delete(&pp);
01208 return result;
01209 }
01210
01211
01212
01228
01229 polynomial *
01230 uves_polynomial_collapse(const polynomial *p, int varno, double value)
01231 {
01232 polynomial *result = NULL;
01233 cpl_polynomial *pol = NULL;
01234 cpl_size *power = NULL;
01235
01236 int i, j;
01237 int degree, dimension;
01238
01239 assure(p != NULL, CPL_ERROR_NULL_INPUT, "Null polynomial");
01240 dimension = uves_polynomial_get_dimension(p);
01241 assure(dimension > 0, CPL_ERROR_ILLEGAL_INPUT,
01242 "Polynomial has non-positive dimension: %d", dimension);
01243 assure(dimension != 1, CPL_ERROR_ILLEGAL_OUTPUT,
01244 "Don't collapse a 1d polynomial. Evaluate it!");
01245
01246
01247
01248
01249 assure(dimension == 2, CPL_ERROR_ILLEGAL_INPUT, "Polynomial must be 2d");
01250
01251 assure(1 <= varno && varno <= dimension, CPL_ERROR_ILLEGAL_INPUT,
01252 "Wrong variable number");
01253 value = (value - p->shift[varno]) / p->scale[varno];
01254
01255
01256 degree = cpl_polynomial_get_degree(p->pol);
01257 pol = cpl_polynomial_new(dimension - 1);
01258 power = cpl_malloc(sizeof(cpl_size) * dimension);
01259 assure_mem( power );
01260 for (i = 0; i <= degree; i++)
01261 {
01262 double coeff;
01263
01264 power[2-varno] = i;
01265
01266
01267 coeff = 0;
01268 for (j = degree - i; j >= 0; j--)
01269 {
01270 power[varno-1] = j;
01271 coeff += cpl_polynomial_get_coeff(p->pol, power);
01272 if (j > 0) coeff *= value;
01273 }
01274
01275 power[0] = i;
01276 cpl_polynomial_set_coeff(pol, power, coeff);
01277 }
01278
01279
01280 result = uves_polynomial_new(pol);
01281
01282
01283 j = 0;
01284 for(i = 0; i <= dimension - 1; i++)
01285 {
01286 if (i == varno)
01287 {
01288
01289 j += 2;
01290
01291 }
01292 else
01293 {
01294 result->shift[i] = p->shift[j];
01295 result->scale[i] = p->scale[j];
01296 j += 1;
01297 }
01298 }
01299
01300 assure(cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
01301 "Error collapsing polynomial");
01302
01303 cleanup:
01304 cpl_free(power); power = NULL;
01305 uves_free_polynomial(&pol);
01306 if (cpl_error_get_code() != CPL_ERROR_NONE)
01307 {
01308 uves_polynomial_delete(&result);
01309 }
01310 return result;
01311 }
01312
01313
01314
01315
01335
01336 polynomial * uves_polynomial_fit_1d(
01337 const cpl_vector * x_pos,
01338 const cpl_vector * values,
01339 const cpl_vector * sigmas,
01340 int poly_deg,
01341 double * mse)
01342 {
01343 int nc ;
01344 int np ;
01345 cpl_matrix * ma = NULL;
01346 cpl_matrix * mb = NULL;
01347 cpl_matrix * mx = NULL;
01348 const double * x_pos_data ;
01349 const double * values_data ;
01350 const double * sigmas_data = NULL;
01351 double mean_x, mean_z;
01352 polynomial * result = NULL;
01353 cpl_polynomial * out ;
01354 cpl_vector * x_val = NULL;
01355 int i, j ;
01356
01357
01358 assure_nomsg( x_pos != NULL && values != NULL, CPL_ERROR_NULL_INPUT);
01359 assure( poly_deg >= 0, CPL_ERROR_ILLEGAL_INPUT,
01360 "Polynomial degree is %d. Must be non-negative", poly_deg);
01361 np = cpl_vector_get_size(x_pos) ;
01362
01363 nc = 1 + poly_deg ;
01364 assure( np >= nc, CPL_ERROR_ILLEGAL_INPUT,
01365 "Not enough points (%d) to fit %d-order polynomial. %d point(s) needed",
01366 np, poly_deg, nc);
01367
01368
01369
01370
01371
01372 ma = cpl_matrix_new(np, nc) ;
01373 mb = cpl_matrix_new(np, 1) ;
01374
01375
01376 mean_x = cpl_vector_get_mean(x_pos);
01377 mean_z = cpl_vector_get_mean(values);
01378
01379
01380 x_pos_data = cpl_vector_get_data_const(x_pos) ;
01381 values_data = cpl_vector_get_data_const(values) ;
01382 if (sigmas != NULL)
01383 {
01384 sigmas_data = cpl_vector_get_data_const(sigmas) ;
01385 }
01386
01387 if (sigmas != NULL)
01388 {
01389 for (i=0 ; i<np ; i++)
01390 {
01391
01392 if (sigmas_data[i] == 0)
01393 {
01394 uves_free_matrix(&ma) ;
01395 uves_free_matrix(&mb) ;
01396 assure(false, CPL_ERROR_DIVISION_BY_ZERO,
01397 "Sigmas must be non-zero");
01398 }
01399 for (j=0 ; j<nc ; j++)
01400 {
01401 cpl_matrix_set(ma, i, j,
01402 uves_pow_int(x_pos_data[i] - mean_x, j) /
01403 sigmas_data[i]) ;
01404 }
01405
01406 cpl_matrix_set(mb, i, 0, (values_data[i] - mean_z) / sigmas_data[i]);
01407 }
01408 }
01409 else
01410 {
01411 for (i=0 ; i<np ; i++)
01412 {
01413 for (j=0 ; j<nc ; j++)
01414 {
01415 cpl_matrix_set(ma, i, j,
01416 uves_pow_int(x_pos_data[i] - mean_x, j) / 1);
01417 }
01418
01419 cpl_matrix_set(mb, i, 0, (values_data[i] - mean_z) / 1) ;
01420 }
01421 }
01422
01423
01424 check( mx = cpl_matrix_solve_normal(ma, mb),
01425 "Could not invert matrix");
01426 uves_free_matrix(&ma);
01427 uves_free_matrix(&mb);
01428
01429
01430 out = cpl_polynomial_new(1) ;
01431 cpl_size deg=0;
01432 for (deg=0 ; deg<nc ; deg++) {
01433 cpl_polynomial_set_coeff(out, °, cpl_matrix_get(mx, deg, 0)) ;
01434 }
01435 uves_free_matrix(&mx);
01436
01437
01438 if (mse != NULL) {
01439 *mse = 0.00 ;
01440 x_val = cpl_vector_new(1) ;
01441 for (i=0 ; i<np ; i++)
01442 {
01443 double residual;
01444 cpl_vector_set(x_val, 0, x_pos_data[i] - mean_x) ;
01445
01446 residual = (values_data[i] - mean_z) - cpl_polynomial_eval(out, x_val);
01447 *mse += residual*residual;
01448 }
01449 uves_free_vector(&x_val) ;
01450
01451 *mse /= (double)np ;
01452 }
01453
01454
01455 result = uves_polynomial_new(out);
01456 uves_free_polynomial(&out);
01457
01458 uves_polynomial_shift(result, 0, mean_z);
01459 uves_polynomial_shift(result, 1, mean_x);
01460
01461 cleanup:
01462 uves_free_vector(&x_val);
01463 uves_free_matrix(&ma);
01464 uves_free_matrix(&mb);
01465 uves_free_matrix(&mx);
01466 return result;
01467 }
01468
01469
01470
01514
01515 polynomial *
01516 uves_polynomial_fit_2d(
01517 const cpl_bivector * xy_pos,
01518 const cpl_vector * values,
01519 const cpl_vector * sigmas,
01520 int poly_deg1,
01521 int poly_deg2,
01522 double * mse,
01523 double * red_chisq,
01524 polynomial ** variance)
01525 {
01526 int nc ;
01527 int degx, degy ;
01528 int * degx_tab ;
01529 int * degy_tab ;
01530 int np ;
01531 cpl_matrix * ma ;
01532 cpl_matrix * mb ;
01533 cpl_matrix * mx ;
01534 cpl_matrix * mat;
01535 cpl_matrix * mat_ma;
01536 cpl_matrix * cov = NULL;
01537 const double * xy_pos_data_x ;
01538 const double * xy_pos_data_y ;
01539 const double * values_data ;
01540 const double * sigmas_data = NULL;
01541 const cpl_vector* xy_pos_x;
01542 const cpl_vector* xy_pos_y;
01543 double mean_x, mean_y, mean_z;
01544 cpl_polynomial * out ;
01545 cpl_polynomial * variance_cpl ;
01546 polynomial * result = NULL;
01547 cpl_size * powers ;
01548
01549
01550 assure(xy_pos && values, CPL_ERROR_NULL_INPUT, "Null input");
01551 assure(poly_deg1 >= 0, CPL_ERROR_ILLEGAL_INPUT, "Polynomial degree1 is %d", poly_deg1);
01552 assure(poly_deg2 >= 0, CPL_ERROR_ILLEGAL_INPUT, "Polynomial degree2 is %d", poly_deg2);
01553 np = cpl_bivector_get_size(xy_pos) ;
01554
01555
01556 assure( (variance == NULL && red_chisq == NULL) || sigmas != NULL,
01557 CPL_ERROR_ILLEGAL_INPUT,
01558 "Cannot calculate variance or chi_sq without knowing");
01559
01560
01561 nc = (1 + poly_deg1)*(1 + poly_deg2) ;
01562
01563 assure(np >= nc, CPL_ERROR_SINGULAR_MATRIX, "%d coefficients. Only %d points", nc, np);
01564
01565
01566
01567
01568 assure(red_chisq == NULL || np > nc, CPL_ERROR_ILLEGAL_INPUT,
01569 "%d coefficients. %d points. Cannot calculate chi square", nc, np);
01570
01571 degx_tab = cpl_malloc(nc * sizeof(int)) ;
01572 assure_mem( degx_tab );
01573
01574 degy_tab = cpl_malloc(nc * sizeof(int)) ;
01575 if (degy_tab == NULL) {
01576 cpl_free(degx_tab);
01577 assure_mem( false );
01578 }
01579
01580 {
01581 int i=0 ;
01582 for (degy=0 ; degy<=poly_deg2 ; degy++) {
01583 for (degx=0 ; degx<=poly_deg1 ; degx++) {
01584 degx_tab[i] = degx ;
01585 degy_tab[i] = degy ;
01586 i++ ;
01587 }
01588 }
01589 }
01590
01591
01592
01593
01594
01595 ma = cpl_matrix_new(np, nc) ;
01596 mb = cpl_matrix_new(np, 1) ;
01597
01598
01599 xy_pos_x = cpl_bivector_get_x_const(xy_pos);
01600 xy_pos_y = cpl_bivector_get_y_const(xy_pos);
01601
01602 mean_x = cpl_vector_get_mean(xy_pos_x);
01603 mean_y = cpl_vector_get_mean(xy_pos_y);
01604 mean_z = cpl_vector_get_mean(values);
01605
01606
01607
01608 xy_pos_data_x = cpl_vector_get_data_const(xy_pos_x) ;
01609 xy_pos_data_y = cpl_vector_get_data_const(xy_pos_y) ;
01610 values_data = cpl_vector_get_data_const(values) ;
01611 if (sigmas != NULL)
01612 {
01613 sigmas_data = cpl_vector_get_data_const(sigmas) ;
01614 }
01615
01616 if (sigmas != NULL)
01617 {
01618 int i;
01619 for (i=0 ; i<np ; i++) {
01620 double *ma_data = cpl_matrix_get_data(ma);
01621 double *mb_data = cpl_matrix_get_data(mb);
01622
01623 int j = 0;
01624 double valy = 1;
01625
01626
01627 if (sigmas_data[i] == 0)
01628 {
01629 uves_free_matrix(&ma) ;
01630 uves_free_matrix(&mb) ;
01631 cpl_free(degx_tab) ;
01632 cpl_free(degy_tab) ;
01633 assure(false, CPL_ERROR_DIVISION_BY_ZERO,
01634 "Sigmas must be non-zero. sigma[%d] is %f", i, sigmas_data[i]);
01635 }
01636
01637 for (degy=0 ; degy<=poly_deg2 ; degy++) {
01638 double valx = 1;
01639 for (degx=0 ; degx<=poly_deg1 ; degx++) {
01640 ma_data[j + i*nc] = valx * valy / sigmas_data[i];
01641 valx *= (xy_pos_data_x[i] - mean_x);
01642 j++;
01643 }
01644 valy *= (xy_pos_data_y[i] - mean_y);
01645 }
01646
01647
01648
01649 mb_data[0 + i*1] = (values_data[i] - mean_z) / sigmas_data[i];
01650 }
01651 }
01652 else
01653 {
01654 int i;
01655 for (i=0 ; i<np ; i++) {
01656 double *ma_data = cpl_matrix_get_data(ma);
01657 double *mb_data = cpl_matrix_get_data(mb);
01658
01659 double valy = 1;
01660 int j = 0;
01661 for (degy=0 ; degy<=poly_deg2 ; degy++) {
01662 double valx = 1;
01663 for (degx=0 ; degx<=poly_deg1 ; degx++) {
01664 ma_data[j + i*nc] = valx * valy / 1;
01665 valx *= (xy_pos_data_x[i] - mean_x);
01666 j++;
01667 }
01668 valy *= (xy_pos_data_y[i] - mean_y);
01669 }
01670
01671
01672
01673 mb_data[0 + i*1] = (values_data[i] - mean_z) / 1;
01674 }
01675 }
01676
01677
01678
01679 if (variance != NULL)
01680 {
01681 mat = cpl_matrix_transpose_create(ma);
01682 if (mat != NULL)
01683 {
01684 mat_ma = cpl_matrix_product_create(mat, ma);
01685 if (mat_ma != NULL)
01686 {
01687 cov = cpl_matrix_invert_create(mat_ma);
01688
01689
01690
01691
01692 variance_cpl = cpl_polynomial_new(2);
01693 }
01694 }
01695 uves_free_matrix(&mat);
01696 uves_free_matrix(&mat_ma);
01697 }
01698
01699
01700 mx = cpl_matrix_solve_normal(ma, mb) ;
01701
01702 uves_free_matrix(&ma) ;
01703 uves_free_matrix(&mb) ;
01704 if (mx == NULL) {
01705 cpl_free(degx_tab) ;
01706 cpl_free(degy_tab) ;
01707 uves_free_matrix(&cov) ;
01708 assure(false, CPL_ERROR_ILLEGAL_OUTPUT, "Matrix inversion failed") ;
01709 }
01710
01711
01712 out = cpl_polynomial_new(2) ;
01713 powers = cpl_malloc(2 * sizeof(cpl_size)) ;
01714 if (powers == NULL) {
01715 cpl_free(degx_tab) ;
01716 cpl_free(degy_tab) ;
01717 uves_free_matrix(&mx) ;
01718 uves_free_matrix(&cov) ;
01719 uves_free_polynomial(&out) ;
01720 assure_mem( false );
01721 }
01722
01723 {
01724 int i;
01725 for (i = 0 ; i < nc ; i++)
01726 {
01727 powers[0] = degx_tab[i] ;
01728 powers[1] = degy_tab[i] ;
01729 cpl_polynomial_set_coeff(out, powers, cpl_matrix_get(mx, i, 0)) ;
01730
01731
01732 if (variance != NULL &&
01733 cov != NULL && variance_cpl != NULL
01734 )
01735 {
01736 int j;
01737 for (j = 0; j < nc; j++)
01738 {
01739 double coeff;
01740
01741
01742
01743
01744
01745
01746 powers[0] = degx_tab[i] + degx_tab[j] ;
01747 powers[1] = degy_tab[i] + degy_tab[j] ;
01748
01749 coeff = cpl_polynomial_get_coeff(variance_cpl, powers);
01750 cpl_polynomial_set_coeff(variance_cpl, powers,
01751 coeff + cpl_matrix_get(cov, i, j)) ;
01752 }
01753 }
01754 }
01755 }
01756
01757 cpl_free(powers) ;
01758 cpl_free(degx_tab) ;
01759 cpl_free(degy_tab) ;
01760 uves_free_matrix(&cov) ;
01761 uves_free_matrix(&mx) ;
01762
01763
01764 result = uves_polynomial_new(out);
01765 uves_free_polynomial(&out);
01766 uves_polynomial_shift(result, 0, mean_z);
01767 uves_polynomial_shift(result, 1, mean_x);
01768 uves_polynomial_shift(result, 2, mean_y);
01769
01770
01771 if (variance != NULL)
01772 {
01773 *variance = uves_polynomial_new(variance_cpl);
01774 uves_free_polynomial(&variance_cpl);
01775
01776
01777
01778
01779 uves_polynomial_shift(*variance, 1, mean_x);
01780 uves_polynomial_shift(*variance, 2, mean_y);
01781
01782
01783
01784 }
01785
01786
01787 if (mse != NULL || red_chisq != NULL)
01788 {
01789 int i;
01790
01791 if (mse != NULL) *mse = 0.00 ;
01792 if (red_chisq != NULL) *red_chisq = 0.00 ;
01793 for (i = 0 ; i < np ; i++)
01794 {
01795 double regress = uves_polynomial_evaluate_2d(result,
01796 xy_pos_data_x[i],
01797 xy_pos_data_y[i]);
01798
01799 if (mse != NULL)
01800 {
01801 double residual = values_data[i] - regress;
01802 *mse += residual*residual;
01803 }
01804 if (red_chisq != NULL)
01805 {
01806 *red_chisq += uves_pow_int((values_data[i] - regress) /
01807 sigmas_data[i], 2);
01808 }
01809 }
01810
01811 if (mse != NULL) *mse /= (double) np ;
01812
01813 if (red_chisq != NULL)
01814 {
01815 passure( np > nc, "%d %d", np, nc);
01816 *red_chisq /= (double) (np - nc) ;
01817 }
01818 }
01819
01820 cleanup:
01821 return result ;
01822 }
01823
01824