36#include "hdrl_utils.h"
37#include "hdrl_types.h"
38#include "hdrl_elemop.h"
44#define SQR(a) ((a) * (a))
69cpl_error_code hdrl_elemop_add(hdrl_data_t * a, hdrl_error_t * ea,
size_t na,
70 const hdrl_data_t * b,
const hdrl_error_t * eb,
size_t nb,
71 const cpl_binary * mask)
73 if (a == b && ea == eb) {
74 for (
size_t i = 0; i < na; i++) {
75 if (mask == NULL || mask[i] == CPL_BINARY_0) {
82 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
85 for (
size_t i = 0; i < na; i++) {
86 if (mask == NULL || mask[i] == CPL_BINARY_0) {
88 ea[i] = hypot(ea[i], eb[0]);
93 for (
size_t i = 0; i < na; i++) {
94 if (mask == NULL || mask[i] == CPL_BINARY_0) {
96 ea[i] = hypot(ea[i], eb[i]);
102 return CPL_ERROR_NONE;
123cpl_error_code hdrl_elemop_sub(hdrl_data_t * a, hdrl_error_t * ea,
size_t na,
124 const hdrl_data_t * b,
const hdrl_error_t * eb,
size_t nb,
125 const cpl_binary * mask)
127 if (a == b && ea == eb) {
128 for (
size_t i = 0; i < na; i++) {
129 if (mask == NULL || mask[i] == CPL_BINARY_0) {
136 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
139 for (
size_t i = 0; i < na; i++) {
140 if (mask == NULL || mask[i] == CPL_BINARY_0) {
142 ea[i] = hypot(ea[i], eb[0]);
147 for (
size_t i = 0; i < na; i++) {
148 if (mask == NULL || mask[i] == CPL_BINARY_0) {
150 ea[i] = hypot(ea[i], eb[i]);
156 return CPL_ERROR_NONE;
177cpl_error_code hdrl_elemop_mul(hdrl_data_t * a, hdrl_error_t * ea,
size_t na,
178 const hdrl_data_t * b,
const hdrl_error_t * eb,
size_t nb,
179 const cpl_binary * mask)
181 if (a == b && ea == eb) {
182 for (
size_t i = 0; i < na; i++) {
183 if (mask == NULL || mask[i] == CPL_BINARY_0) {
184 const hdrl_data_t a_ = a[i] * a[i];
185 ea[i] = 2 * fabs(a[i]) * ea[i];
191 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
194 const hdrl_data_t b0 = b[0];
195 const hdrl_error_t eb0 = eb[0];
196 for (
size_t i = 0; i < na; i++) {
197 if (mask == NULL || mask[i] == CPL_BINARY_0) {
198 const hdrl_data_t a_ = a[i] * b0;
199 ea[i] = hypot(eb0 * a[i], ea[i] * b0);
205 for (
size_t i = 0; i < na; i++) {
206 if (mask == NULL || mask[i] == CPL_BINARY_0) {
207 const hdrl_data_t a_ = a[i] * b[i];
208 ea[i] = hypot(eb[i] * a[i], ea[i] * b[i]);
215 return CPL_ERROR_NONE;
240cpl_error_code hdrl_elemop_div(hdrl_data_t * a, hdrl_error_t * ea,
size_t na,
241 const hdrl_data_t * b,
const hdrl_error_t * eb,
size_t nb,
242 const cpl_binary * mask)
244 if (a == b && ea == eb) {
245 for (
size_t i = 0; i < na; i++) {
246 if (mask == NULL || mask[i] == CPL_BINARY_0) {
253 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
256 const hdrl_data_t rb0 = 1. / b[0];
257 const hdrl_error_t eb0 = eb[0];
258 for (
size_t i = 0; i < na; i++) {
259 if (mask == NULL || mask[i] == CPL_BINARY_0) {
260 const hdrl_data_t a_ = a[i] * rb0;
267 ea[i] = sqrt(SQR(ea[i] * rb0) +
268 SQR(eb0 * a_ * rb0));
275 for (
size_t i = 0; i < na; i++) {
276 if (mask == NULL || mask[i] == CPL_BINARY_0) {
277 const hdrl_data_t rb = 1. / b[i];
278 const hdrl_data_t a_ = a[i] * rb;
285 ea[i] = sqrt(SQR(ea[i] * rb) +
286 SQR(eb[i] * a_ * rb));
294 return CPL_ERROR_NONE;
298static inline void pow_scalar(hdrl_data_t base, hdrl_error_t base_e,
299 hdrl_data_t exp, hdrl_error_t exp_e,
300 hdrl_data_t* out, hdrl_error_t* out_e){
304 if(base == 0. && exp < 0.){
310 if(exp_e == .0 && exp == 2.0){
312 *out_e = fabs(2.0 * base_e * base);
316 *out = pow(base, exp);
320 *out_e = fabs(*out * (exp / base * base_e));
324 const hdrl_data_t log_base = log(fabs(base));
325 *out_e = fabs(*out) * sqrt(SQR( exp / base * base_e)
326 + SQR(log_base * exp_e));
351cpl_error_code hdrl_elemop_pow(hdrl_data_t * a, hdrl_error_t * ea,
size_t na,
352 const hdrl_data_t * b,
const hdrl_error_t * eb,
size_t nb,
353 const cpl_binary * mask)
355 if (a == b && ea == eb) {
356 for (
size_t i = 0; i < na; i++) {
357 if (mask == NULL || mask[i] == CPL_BINARY_0) {
358 hdrl_data_t loga = log(fabs(a[i]));
359 a[i] = pow(a[i], a[i]);
361 sqrt(SQR(ea[i]) * (1. + SQR(loga) + 2 * loga));
366 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
369 for (
size_t i = 0; i < na; i++) {
370 if (mask == NULL || mask[i] == CPL_BINARY_0) {
371 pow_scalar(a[i], ea[i], b[0], eb[0], &a[i], &ea[i]);
376 for (
size_t i = 0; i < na; i++) {
377 if (mask == NULL || mask[i] == CPL_BINARY_0) {
378 pow_scalar(a[i], ea[i], b[i], eb[i], &a[i], &ea[i]);
384 return CPL_ERROR_NONE;
409cpl_error_code hdrl_elemop_pow_inverted(hdrl_data_t * a, hdrl_error_t * ea,
size_t na,
410 const hdrl_data_t * b,
const hdrl_error_t * eb,
size_t nb,
411 const cpl_binary * mask)
413 if (a == b && ea == eb) {
415 return hdrl_elemop_pow(a, ea, na, b, eb, nb, mask);
418 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
421 for (
size_t i = 0; i < na; i++) {
422 if (mask == NULL || mask[i] == CPL_BINARY_0) {
423 pow_scalar(b[0], eb[0], a[i], ea[i], &a[i], &ea[i]);
428 for (
size_t i = 0; i < na; i++) {
429 if (mask == NULL || mask[i] == CPL_BINARY_0) {
430 pow_scalar(b[i], eb[i], a[i], ea[i], &a[i], &ea[i]);
436 return CPL_ERROR_NONE;
440typedef cpl_error_code (hdrl_math_op_f)(
441 hdrl_data_t * a, hdrl_error_t * ea,
size_t na,
442 const hdrl_data_t * b,
const hdrl_error_t * eb,
size_t nb,
443 const cpl_binary * mask);
445typedef cpl_error_code (hdrl_math_op_image_f)(
446 cpl_image * a, cpl_image * ae,
447 const cpl_image * b,
const cpl_image * be);
449typedef cpl_error_code (hdrl_math_op_image_scalar_f)(
450 cpl_image * a, cpl_image * ae,
451 const hdrl_data_t b,
const hdrl_error_t be);
454check_input(cpl_image * a, cpl_image * ae,
455 const cpl_image * b,
const cpl_image * be)
457 cpl_ensure_code(a, CPL_ERROR_NULL_INPUT);
458 cpl_ensure_code(ae, CPL_ERROR_NULL_INPUT);
459 cpl_ensure_code(b, CPL_ERROR_NULL_INPUT);
460 cpl_ensure_code(be, CPL_ERROR_NULL_INPUT);
462 cpl_ensure_code(cpl_image_get_size_x(a) == cpl_image_get_size_x(ae),
463 CPL_ERROR_INCOMPATIBLE_INPUT);
464 cpl_ensure_code(cpl_image_get_size_y(a) == cpl_image_get_size_y(ae),
465 CPL_ERROR_INCOMPATIBLE_INPUT);
466 cpl_ensure_code(cpl_image_get_size_x(b) == cpl_image_get_size_x(be),
467 CPL_ERROR_INCOMPATIBLE_INPUT);
468 cpl_ensure_code(cpl_image_get_size_y(b) == cpl_image_get_size_y(be),
469 CPL_ERROR_INCOMPATIBLE_INPUT);
470 cpl_ensure_code(cpl_image_get_size_x(a) == cpl_image_get_size_x(b),
471 CPL_ERROR_INCOMPATIBLE_INPUT);
472 cpl_ensure_code(cpl_image_get_size_y(a) == cpl_image_get_size_y(b),
473 CPL_ERROR_INCOMPATIBLE_INPUT);
474 cpl_ensure_code(cpl_image_get_type(a) == HDRL_TYPE_DATA,
475 CPL_ERROR_INCOMPATIBLE_INPUT);
476 cpl_ensure_code(cpl_image_get_type(ae) == HDRL_TYPE_ERROR,
477 CPL_ERROR_INCOMPATIBLE_INPUT);
478 cpl_ensure_code(cpl_image_get_type(b) == HDRL_TYPE_DATA,
479 CPL_ERROR_INCOMPATIBLE_INPUT);
480 cpl_ensure_code(cpl_image_get_type(be) == HDRL_TYPE_ERROR,
481 CPL_ERROR_INCOMPATIBLE_INPUT);
483 return CPL_ERROR_NONE;
488hdrl_elemop_image_scalar(cpl_image * a, cpl_image * ae,
489 const hdrl_data_t b,
const hdrl_error_t be,
492 const cpl_binary * dmask = NULL;
493 cpl_ensure_code(a, CPL_ERROR_NULL_INPUT);
494 cpl_ensure_code(ae, CPL_ERROR_NULL_INPUT);
495 cpl_ensure_code(cpl_image_get_type(a) == HDRL_TYPE_DATA,
496 CPL_ERROR_INCOMPATIBLE_INPUT);
497 cpl_ensure_code(cpl_image_get_type(ae) == HDRL_TYPE_ERROR,
498 CPL_ERROR_INCOMPATIBLE_INPUT);
499 const cpl_mask * bpm = cpl_image_get_bpm_const(a);
502 dmask = cpl_mask_get_data_const(bpm);
505 if (f == hdrl_elemop_div && b == 0.) {
506 cpl_msg_warning(cpl_func,
"dividing image by scalar zero");
507 cpl_image_add_scalar(a, NAN);
508 cpl_image_add_scalar(ae, NAN);
509 cpl_image_reject_value(a, CPL_VALUE_NAN);
510 cpl_image_reject_value(ae, CPL_VALUE_NAN);
511 return cpl_error_get_code();
514 cpl_error_code err = f(hdrl_get_image_data(a),
515 hdrl_get_image_error(ae),
516 hdrl_get_image_npix(a),
519 if (f == hdrl_elemop_pow || f == hdrl_elemop_pow_inverted) {
520 cpl_image_reject_value(a, CPL_VALUE_NAN);
521 cpl_image_reject_from_mask(ae, cpl_image_get_bpm(a));
529hdrl_elemop_image_add_scalar(cpl_image * a, cpl_image * ae,
530 const hdrl_data_t b,
const hdrl_error_t be)
532 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_add);
536hdrl_elemop_image_sub_scalar(cpl_image * a, cpl_image * ae,
537 const hdrl_data_t b,
const hdrl_error_t be)
539 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_sub);
543hdrl_elemop_image_mul_scalar(cpl_image * a, cpl_image * ae,
544 const hdrl_data_t b,
const hdrl_error_t be)
546 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_mul);
550hdrl_elemop_image_div_scalar(cpl_image * a, cpl_image * ae,
551 const hdrl_data_t b,
const hdrl_error_t be)
553 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_div);
557hdrl_elemop_image_pow_scalar(cpl_image * a, cpl_image * ae,
558 const hdrl_data_t b,
const hdrl_error_t be)
560 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_pow);
564hdrl_elemop_image_exp_scalar(cpl_image * a, cpl_image * ae,
565 const hdrl_data_t b,
const hdrl_error_t be)
567 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_pow_inverted);
571hdrl_elemop_image(cpl_image * a, cpl_image * ae,
572 const cpl_image * b,
const cpl_image * be,
575 cpl_error_code r = check_input(a, ae, b, be);
576 const cpl_binary * dmask = NULL;
577 cpl_ensure_code(r == CPL_ERROR_NONE, r);
578 const cpl_mask * bbpm = cpl_image_get_bpm_const(b);
581 if (cpl_image_get_bpm_const(a)) {
583 cpl_mask * abpm = cpl_image_get_bpm(a);
584 cpl_mask_or(abpm, bbpm);
585 dmask = cpl_mask_get_data_const(abpm);
589 cpl_image_reject_from_mask(a, bbpm);
590 dmask = cpl_mask_get_data_const(bbpm);
594 const cpl_mask * abpm = cpl_image_get_bpm_const(a);
596 dmask = cpl_mask_get_data_const(abpm);
600 r = f(hdrl_get_image_data(a),
601 hdrl_get_image_error(ae),
602 hdrl_get_image_npix(a),
603 hdrl_get_image_data_const(b),
604 hdrl_get_image_error_const(be),
605 hdrl_get_image_npix(a),
608 if (f == hdrl_elemop_div || f == hdrl_elemop_pow) {
609 cpl_image_reject_value(a, CPL_VALUE_NAN);
610 cpl_image_reject_from_mask(ae, cpl_image_get_bpm(a));
617hdrl_elemop_image_add_image(cpl_image * a, cpl_image * ae,
618 const cpl_image * b,
const cpl_image * be)
620 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_add);
624hdrl_elemop_image_sub_image(cpl_image * a, cpl_image * ae,
625 const cpl_image * b,
const cpl_image * be)
627 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_sub);
631hdrl_elemop_image_mul_image(cpl_image * a, cpl_image * ae,
632 const cpl_image * b,
const cpl_image * be)
634 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_mul);
638hdrl_elemop_image_div_image(cpl_image * a, cpl_image * ae,
639 const cpl_image * b,
const cpl_image * be)
641 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_div);
645hdrl_elemop_image_pow_image(cpl_image * a, cpl_image * ae,
646 const cpl_image * b,
const cpl_image * be)
648 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_pow);
652hdrl_elemop_imagelist_vector(cpl_imagelist * self_d,
653 cpl_imagelist * self_e,
654 const cpl_vector * other_d,
655 const cpl_vector * other_e,
656 hdrl_math_op_image_scalar_f * f)
658 cpl_ensure_code(self_d, CPL_ERROR_NULL_INPUT);
659 cpl_ensure_code(self_e, CPL_ERROR_NULL_INPUT);
660 cpl_ensure_code(other_d, CPL_ERROR_NULL_INPUT);
661 cpl_ensure_code(other_e, CPL_ERROR_NULL_INPUT);
662 const size_t nz = cpl_imagelist_get_size(self_d);
663 cpl_ensure_code(nz == (
size_t)cpl_imagelist_get_size(self_e),
664 CPL_ERROR_INCOMPATIBLE_INPUT);
665 cpl_ensure_code(nz == (
size_t)cpl_vector_get_size(other_d),
666 CPL_ERROR_INCOMPATIBLE_INPUT);
667 cpl_ensure_code(nz == (
size_t)cpl_vector_get_size(other_e),
668 CPL_ERROR_INCOMPATIBLE_INPUT);
670 for (
size_t i = 0; i < nz; i++) {
671 cpl_image * ad = cpl_imagelist_get(self_d, i);
672 cpl_image * ae = cpl_imagelist_get(self_e, i);
673 const double bd = cpl_vector_get(other_d, i);
674 const double be = cpl_vector_get(other_e, i);
678 return cpl_error_get_code();
682hdrl_elemop_imagelist_add_vector(cpl_imagelist * a,
684 const cpl_vector * b,
685 const cpl_vector * be)
687 return hdrl_elemop_imagelist_vector(a, ae, b, be,
688 hdrl_elemop_image_add_scalar);
692hdrl_elemop_imagelist_sub_vector(cpl_imagelist * a,
694 const cpl_vector * b,
695 const cpl_vector * be)
697 return hdrl_elemop_imagelist_vector(a, ae, b, be,
698 hdrl_elemop_image_sub_scalar);
702hdrl_elemop_imagelist_mul_vector(cpl_imagelist * a,
704 const cpl_vector * b,
705 const cpl_vector * be)
707 return hdrl_elemop_imagelist_vector(a, ae, b, be,
708 hdrl_elemop_image_mul_scalar);
712hdrl_elemop_imagelist_div_vector(cpl_imagelist * a,
714 const cpl_vector * b,
715 const cpl_vector * be)
717 return hdrl_elemop_imagelist_vector(a, ae, b, be,
718 hdrl_elemop_image_div_scalar);
722hdrl_elemop_imagelist_pow_vector(cpl_imagelist * a,
724 const cpl_vector * b,
725 const cpl_vector * be)
727 return hdrl_elemop_imagelist_vector(a, ae, b, be,
728 hdrl_elemop_image_pow_scalar);
732hdrl_elemop_imagelist_image(cpl_imagelist * self_d,
733 cpl_imagelist * self_e,
734 const cpl_image * other_d,
735 const cpl_image * other_e,
736 hdrl_math_op_image_f * f)
738 cpl_ensure_code(self_d, CPL_ERROR_NULL_INPUT);
739 cpl_ensure_code(self_e, CPL_ERROR_NULL_INPUT);
740 cpl_ensure_code(other_d, CPL_ERROR_NULL_INPUT);
741 cpl_ensure_code(other_e, CPL_ERROR_NULL_INPUT);
742 const size_t nz = cpl_imagelist_get_size(self_d);
743 cpl_ensure_code(nz == (
size_t)cpl_imagelist_get_size(self_e),
744 CPL_ERROR_INCOMPATIBLE_INPUT);
746 for (
size_t i = 0; i < nz; i++) {
747 cpl_image * ad = cpl_imagelist_get(self_d, i);
748 cpl_image * ae = cpl_imagelist_get(self_e, i);
749 f(ad, ae, other_d, other_e);
752 return cpl_error_get_code();
756hdrl_elemop_imagelist_add_image(cpl_imagelist * a,
759 const cpl_image * be)
761 return hdrl_elemop_imagelist_image(a, ae, b, be,
762 hdrl_elemop_image_add_image);
766hdrl_elemop_imagelist_sub_image(cpl_imagelist * a,
769 const cpl_image * be)
771 return hdrl_elemop_imagelist_image(a, ae, b, be,
772 hdrl_elemop_image_sub_image);
776hdrl_elemop_imagelist_mul_image(cpl_imagelist * a,
779 const cpl_image * be)
781 return hdrl_elemop_imagelist_image(a, ae, b, be,
782 hdrl_elemop_image_mul_image);
786hdrl_elemop_imagelist_div_image(cpl_imagelist * a,
789 const cpl_image * be)
791 return hdrl_elemop_imagelist_image(a, ae, b, be,
792 hdrl_elemop_image_div_image);
796hdrl_elemop_imagelist_pow_image(cpl_imagelist * a,
799 const cpl_image * be)
801 return hdrl_elemop_imagelist_image(a, ae, b, be,
802 hdrl_elemop_image_pow_image);
806hdrl_elemop_imagelist(cpl_imagelist * self_d,
807 cpl_imagelist * self_e,
808 const cpl_imagelist * other_d,
809 const cpl_imagelist * other_e,
810 hdrl_math_op_image_f * f)
812 cpl_ensure_code(self_d, CPL_ERROR_NULL_INPUT);
813 cpl_ensure_code(other_d, CPL_ERROR_NULL_INPUT);
814 cpl_ensure_code(self_e, CPL_ERROR_NULL_INPUT);
815 cpl_ensure_code(other_e, CPL_ERROR_NULL_INPUT);
816 const size_t nz = cpl_imagelist_get_size(self_d);
817 cpl_ensure_code(nz == (
size_t)cpl_imagelist_get_size(self_e),
818 CPL_ERROR_INCOMPATIBLE_INPUT);
819 cpl_ensure_code(nz == (
size_t)cpl_imagelist_get_size(other_d),
820 CPL_ERROR_INCOMPATIBLE_INPUT);
821 cpl_ensure_code(nz == (
size_t)cpl_imagelist_get_size(other_e),
822 CPL_ERROR_INCOMPATIBLE_INPUT);
824 for (
size_t i = 0; i < nz; i++) {
825 cpl_image * ad = cpl_imagelist_get(self_d, i);
826 cpl_image * ae = cpl_imagelist_get(self_e, i);
827 const cpl_image * bd = cpl_imagelist_get_const(other_d, i);
828 const cpl_image * be = cpl_imagelist_get_const(other_e, i);
832 return cpl_error_get_code();
836hdrl_elemop_imagelist_add_imagelist(cpl_imagelist * a,
838 const cpl_imagelist * b,
839 const cpl_imagelist * be)
841 return hdrl_elemop_imagelist(a, ae, b, be,
842 hdrl_elemop_image_add_image);
846hdrl_elemop_imagelist_sub_imagelist(cpl_imagelist * a,
848 const cpl_imagelist * b,
849 const cpl_imagelist * be)
851 return hdrl_elemop_imagelist(a, ae, b, be,
852 hdrl_elemop_image_sub_image);
856hdrl_elemop_imagelist_mul_imagelist(cpl_imagelist * a,
858 const cpl_imagelist * b,
859 const cpl_imagelist * be)
861 return hdrl_elemop_imagelist(a, ae, b, be,
862 hdrl_elemop_image_mul_image);
866hdrl_elemop_imagelist_div_imagelist(cpl_imagelist * a,
868 const cpl_imagelist * b,
869 const cpl_imagelist * be)
871 return hdrl_elemop_imagelist(a, ae, b, be,
872 hdrl_elemop_image_div_image);
876hdrl_elemop_imagelist_pow_imagelist(cpl_imagelist * a,
878 const cpl_imagelist * b,
879 const cpl_imagelist * be)
881 return hdrl_elemop_imagelist(a, ae, b, be,
882 hdrl_elemop_image_pow_image);