@@ -23659,29 +23659,34 @@ namespace cimg_library {
2365923659 if (!std::strncmp(ss,"sort(",5)) { // Sort vector
2366023660 _cimg_mp_op("Function 'sort()'");
2366123661 s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
23662- arg1 = compile(ss5,s1,depth1,0,block_flags);
23663- arg2 = arg4 = 1; arg3 = ~0U; arg5 = 0 ;
23662+ arg1 = compile(ss5,s1,depth1,0,block_flags); // X
23663+ arg2 = arg5 = 1; arg3 = arg6 = 0; arg4 = ~0U ;
2366423664 if (s1<se1) {
2366523665 s0 = ++s1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
23666- arg2 = compile(s1,s0,depth1,0,block_flags);
23666+ arg2 = compile(s1,s0,depth1,0,block_flags); // is_increasing
2366723667 if (s0<se1) {
2366823668 s1 = ++s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
23669- arg3 = compile(s0,s1,depth1,0,block_flags);
23669+ arg3 = compile(s0,s1,depth1,0,block_flags); // starting_index
2367023670 if (s1<se1) {
2367123671 s0 = ++s1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
23672- arg4 = compile(s1,s0,depth1,0,block_flags);
23673- arg5 = s0<se1?compile(++s0,se1,depth1,0,block_flags):0;
23672+ arg4 = compile(s1,s0,depth1,0,block_flags); // nb_elt
23673+ if (s0<se1) {
23674+ s1 = ++s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
23675+ arg5 = compile(s0,s1,depth1,0,block_flags); // size_elt
23676+ arg6 = s1<se1?compile(++s1,se1,depth1,0,block_flags):0; // sort_index
23677+ }
2367423678 }
2367523679 }
2367623680 }
2367723681 _cimg_mp_check_type(arg1,1,2,0);
2367823682 _cimg_mp_check_type(arg2,2,1,0);
23679- if (arg3!=~0U) _cimg_mp_check_type(arg3,3,1,0);
23680- _cimg_mp_check_type(arg4,4,1,0);
23683+ _cimg_mp_check_type(arg3,3,1,0);
23684+ if (arg4!=~0U) _cimg_mp_check_type(arg4,4,1,0);
2368123685 _cimg_mp_check_type(arg5,5,1,0);
23686+ _cimg_mp_check_type(arg6,6,1,0);
2368223687 p1 = size(arg1);
2368323688 pos = vector(p1);
23684- CImg<ulongT>::vector((ulongT)mp_sort,pos,arg1,p1,arg2,arg3,arg4,arg5).move_to(code);
23689+ CImg<ulongT>::vector((ulongT)mp_sort,pos,arg1,p1,arg2,arg3,arg4,arg5,arg6 ).move_to(code);
2368523690 return_comp = true;
2368623691 _cimg_mp_return(pos);
2368723692 }
@@ -26628,10 +26633,11 @@ namespace cimg_library {
2662826633 if (dim1==1) { // Scalar or vector1() elements
2662926634 if (nb_elts) {
2663026635 for (unsigned int k = 0; k<nb_elts; ++k) img[pos + k] = (T)_mp_arg(7 + k);
26631- if (count>1)
26632- for (unsigned int k = 1; k<count; ++k) std::memcpy(&img[pos + k*nb_elts],&img[pos],nb_elts*sizeof(T));
26636+ if (count>1) // Exponentially recopy sequence of scalar elements
26637+ for (unsigned int k = 1; k<count; k<<=1)
26638+ std::memcpy(&img[pos + k*nb_elts],&img[pos],std::min(k,count - k)*nb_elts*sizeof(T));
2663326639 } else std::memset(&img[pos],0,count*sizeof(T));
26634- if (is_push_heap) for (unsigned int k = 0; k<nb_elts ; ++k) {
26640+ if (is_push_heap) for (unsigned int k = 0; k<count*nb_elts1 ; ++k) {
2663526641 int index = pos + k;
2663626642 while (index>0) { // Heapify-up
2663726643 const int index_parent = (index - 1)/2;
@@ -26648,11 +26654,14 @@ namespace cimg_library {
2664826654 const double *const ptrs = &_mp_arg(7 + k) + 1;
2664926655 cimg_forC(img,c) { *ptrd = ptrs[c]; ptrd+=img._height; }
2665026656 }
26651- if (count>1)
26652- cimg_forC(img,c) for (unsigned int k = 1; k<count; ++k)
26653- std::memcpy(img.data(0,pos + k*nb_elts,0,c),img.data(0,pos,0,c),nb_elts*sizeof(T));
26657+ if (count>1) // Exponentially recopy sequence of vector-valued elements
26658+ cimg_forC(img,c) {
26659+ T *const ptr = img.data(0,0,0,c);
26660+ for (unsigned int k = 1; k<count; k<<=1)
26661+ std::memcpy(&ptr[pos + k*nb_elts],&ptr[pos],std::min(k,count - k)*nb_elts*sizeof(T));
26662+ }
2665426663 } else cimg_forC(img,c) std::memset(img.data(0,pos,0,c),0,count*sizeof(T));
26655- if (is_push_heap) for (unsigned int k = 0; k<nb_elts ; ++k) {
26664+ if (is_push_heap) for (unsigned int k = 0; k<count*nb_elts1 ; ++k) {
2665626665 int index = pos + k;
2665726666 while (index>0) { // Heapify-up
2665826667 const int index_parent = (index - 1)/2;
@@ -29515,21 +29524,31 @@ namespace cimg_library {
2951529524 static double mp_sort(_cimg_math_parser& mp) {
2951629525 double *const ptrd = &_mp_arg(1) + 1;
2951729526 const double *const ptrs = &_mp_arg(2) + 1;
29527+ const int
29528+ siz = (int)mp.opcode[3],
29529+ starting_index = (int)_mp_arg(5),
29530+ nb_elts = mp.opcode[6]==~0U?siz:(int)_mp_arg(6),
29531+ siz_elt = (int)_mp_arg(7),
29532+ sort_index = (int)_mp_arg(8),
29533+ end_index = starting_index + nb_elts*siz_elt;
2951829534 const bool is_increasing = (bool)_mp_arg(4);
29519- const unsigned int
29520- siz = (unsigned int)mp.opcode[3],
29521- nb_elts = mp.opcode[5]==~0U?siz:(unsigned int)_mp_arg(5),
29522- siz_elt = (unsigned int)_mp_arg(6),
29523- sort_index = std::min((unsigned int)_mp_arg(7),siz_elt - 1);
29524- const ulongT sn = siz_elt*nb_elts;
29525- if (sn>siz || siz_elt<1)
29535+
29536+ if (starting_index<0 || nb_elts<0 || siz_elt<=0 || sort_index<0 || sort_index>=siz_elt || end_index>siz)
2952629537 throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function 'sort()': "
29527- "Arguments 'nb_elts=%g' and 'siz_elt=%g' are invalid "
29528- "for sorting a vector of size %u.",
29529- mp.imgin.pixel_type(),_mp_arg(5),_mp_arg(6),siz);
29530- CImg<doubleT>(ptrd,siz_elt,nb_elts,1,1,true) = CImg<doubleT>(ptrs,siz_elt,nb_elts,1,1,true).
29531- shift(-(int)sort_index,0,0,0,2).get_sort(is_increasing,siz_elt>1?'y':0).shift((int)sort_index,0,0,0,2);
29532- if (sn<siz) CImg<doubleT>(ptrd + sn,siz - sn,1,1,1,true) = CImg<doubleT>(ptrs + sn,siz - sn,1,1,1,true);
29538+ "Invalid arguments 'starting_index=%g', 'nb_elts=%g', 'siz_elt=%g' and "
29539+ "'sort_index=%g', for sorting a vector of size %u.",
29540+ mp.imgin.pixel_type(),_mp_arg(5),_mp_arg(6),_mp_arg(7),_mp_arg(8),siz);
29541+ if (nb_elts) {
29542+ if (starting_index>0) // Recopy left side
29543+ std::memcpy(ptrd,ptrs,starting_index*sizeof(double));
29544+ if (end_index<siz) // Recopy right side
29545+ std::memcpy(ptrd + end_index,ptrs + end_index,(siz - end_index)*sizeof(double));
29546+
29547+ // Sort region.
29548+ CImg<doubleT>(ptrd + starting_index,siz_elt,nb_elts,1,1,true) =
29549+ CImg<doubleT>(ptrs + starting_index,siz_elt,nb_elts,1,1,true).
29550+ shift(-(int)sort_index,0,0,0,2).get_sort(is_increasing,siz_elt>1?'y':0).shift((int)sort_index,0,0,0,2);
29551+ }
2953329552 return cimg::type<double>::nan();
2953429553 }
2953529554
0 commit comments