diff --git a/CImg.h b/CImg.h index 2dcbd041..6e17b9fd 100644 --- a/CImg.h +++ b/CImg.h @@ -54,7 +54,7 @@ // Set version number of the library. #ifndef cimg_version -#define cimg_version 342 +#define cimg_version 343 /*----------------------------------------------------------- # @@ -22379,6 +22379,19 @@ namespace cimg_library { _cimg_mp_const_scalar(is_scalar(arg1)?0:size(arg1)); } + if (!std::strncmp(ss,"softmax(",8)) { // Softmax + _cimg_mp_op("Function 'softmax()'"); + s1 = ss8; while (s10) pos = is_comp_vector(arg1)?arg1:((return_comp = true), vector(p1)); + else _cimg_mp_return(1); + CImg::vector((ulongT)mp_vector_softmax,pos,arg1,p1,arg2).move_to(code); + _cimg_mp_return(pos); + } + if (!std::strncmp(ss,"solve(",6)) { // Solve square linear system _cimg_mp_op("Function 'solve()'"); s1 = ss6; while (s10) pos = is_comp_vector(arg1)?arg1:((return_comp = true), vector(p1)); else { @@ -29241,6 +29254,19 @@ namespace cimg_library { return _mp_arg(1); } + static double mp_vector_softmax(_cimg_math_parser& mp) { + const unsigned int siz = (unsigned int)mp.opcode[3]; + const double temperature = _mp_arg(4); + if (siz>0) { // Vector-valued argument + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + CImg(ptrd,siz,1,1,1,true) = CImg(ptrs,siz,1,1,1,true).get_softmax(temperature); + return cimg::type::nan(); + } + // Scalar-valued argument. + return 1; + } + static double mp_vector_unitnorm(_cimg_math_parser& mp) { const unsigned int siz = (unsigned int)mp.opcode[3]; const double p = _mp_arg(4); @@ -30211,6 +30237,28 @@ namespace cimg_library { return (+*this).ror(img); } + //! Softmax operator. + CImg& softmax(const float temperature=1) { + return get_softmax(temperature).move_to(*this); + } + + //! Softmax operator \newinstance. + CImg get_softmax(const float temperature=1) const { + if (is_empty()) return CImg(); + CImg res(_width,_height,_depth,_spectrum); + const T val_max = max(); + Tfloat sum = 0; + cimg_pragma_openmp(parallel reduction(+:sum) cimg_openmp_if_size(size(),4096)) { + cimg_pragma_openmp(for) + cimg_rofoff(*this,off) { + const Tfloat val = std::exp(((Tfloat)_data[off] - val_max)/temperature); + res[off] = val; + sum+=val; + } + } + return res/=sum; + } + //! Pointwise min operator between instance image and a value. /** \param val Value used as the reference argument of the min operator. diff --git a/html/header.html b/html/header.html index 9927edf8..676dded0 100644 --- a/html/header.html +++ b/html/header.html @@ -23,7 +23,7 @@
Logo

- Latest stable version: 3.4.2 (2024/09/04) + Latest stable version: 3.4.2        Current pre-release: 3.4.3 (2024/09/09)


diff --git a/html/header_doxygen.html b/html/header_doxygen.html index 85913177..5838603b 100644 --- a/html/header_doxygen.html +++ b/html/header_doxygen.html @@ -26,7 +26,7 @@
Logo

- Latest stable version: 3.4.2 (2024/09/04) + Latest stable version: 3.4.2        Current pre-release: 3.4.3 (2024/09/09)