@@ -20995,7 +20995,7 @@ namespace cimg_library {
2099520995 s1 = ++s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
2099620996 p1 = compile(s0,s1++,depth1,0,block_flags);
2099720997 _cimg_mp_check_notnan_index(p1,s0);
20998- } else { p1 = 11; s1 = s0; }
20998+ } else { p1 = 11; s1 = s0; } // Default: #-1
2099920999 _cimg_mp_check_list();
2100021000 _cimg_mp_check_const_scalar(p1,1,1);
2100121001 p3 = (unsigned int)cimg::mod((int)mem[p1],imglist.width());
@@ -21014,52 +21014,64 @@ namespace cimg_library {
2101421014 s1 = ++s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
2101521015 p1 = compile(s0,s1++,depth1,0,block_flags);
2101621016 _cimg_mp_check_notnan_index(p1,s0);
21017- } else { p1 = 11; s1 = s0; }
21017+ } else { p1 = 11; s1 = s0; } // Default: #-1
2101821018 _cimg_mp_check_list();
2101921019 CImg<ulongT>::vector((ulongT)mp_da_freeze,_cimg_mp_slot_nan,p1).move_to(code);
2102021020 _cimg_mp_return_nan();
2102121021 }
2102221022
2102321023 if (!std::strncmp(ss,"da_insert(",10) ||
21024+ !std::strncmp(ss,"da_insert_n(",12) ||
2102421025 !std::strncmp(ss,"da_push(",8) ||
21025- !std::strncmp(ss,"da_push_heap(",13)) { // Insert element(s) in a dynamic array
21026+ !std::strncmp(ss,"da_push_n(",10) ||
21027+ !std::strncmp(ss,"da_push_heap(",13) ||
21028+ !std::strncmp(ss,"da_push_heap_n(",15)) { // Insert element(s) in a dynamic array
2102621029 if (!is_inside_critical) is_parallelizable = false;
21027- const bool is_push = *ss3=='p', is_push_heap = *ss7=='_';
21028- _cimg_mp_op(is_push_heap?"Function 'da_push_heap()'":
21029- is_push?"Function 'da_push()'":"Function 'da_insert()'");
21030- s0 = ss + (is_push_heap?13:is_push?8:10);
21030+ const bool
21031+ is_push_heap = *ss3=='p' && *ss7=='_' && *ss8=='h',
21032+ is_push = !is_push_heap && *ss3=='p',
21033+ is_insert = !is_push_heap && !is_push,
21034+ is_n = is_push_heap?ss[12]=='_':is_push?*ss7=='_':ss[9]=='_';
21035+ _cimg_mp_op(is_push_heap?(is_n?"Function 'da_push_heap_n()'":"Function 'da_push_heap()'"):
21036+ is_push?(is_n?"Function 'da_push_n()'":"Function 'da_push()'"):
21037+ (is_n?"Function 'da_insert_n()'":"Function 'da_insert()'"));
21038+ s0 = ss + (is_push_heap?13:is_push?8:10) + (is_n?2:0);
2103121039 if (*s0=='#') { // Index specified
2103221040 s1 = ++s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
2103321041 p1 = compile(s0,s1++,depth1,0,block_flags);
2103421042 _cimg_mp_check_notnan_index(p1,s0);
21035- } else { p1 = 11; s1 = s0; }
21043+ } else { p1 = 11; s1 = s0; } // Default: #-1
2103621044 _cimg_mp_check_list();
21037- if (!is_push ) {
21045+ if (is_n ) {
2103821046 s0 = s1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
21039- arg1 = compile(s0,s1++,depth1,0,block_flags); // Position
21040- } else if (is_push_heap) arg1 = ~0U - 1;
21041- else arg1 = ~0U;
21042- CImg<ulongT>::vector((ulongT)mp_da_insert_or_push,_cimg_mp_slot_nan,p1,arg1,0,0).move_to(l_opcode);
21043- p3 = p1==~0U?2:3;
21047+ arg1 = compile(s0,s1++,depth1,0,block_flags); // Count
21048+ } else arg1 = ~0U;
21049+ if (is_insert) {
21050+ s0 = s1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
21051+ arg2 = compile(s0,s1++,depth1,0,block_flags); // Position
21052+ } else if (is_push_heap) arg2 = ~0U - 1;
21053+ else arg2 = ~0U;
21054+ CImg<ulongT>::vector((ulongT)mp_da_insert_or_push_n,_cimg_mp_slot_nan,p1,arg1,arg2,0,0).move_to(l_opcode);
21055+ pos = (p1==~0U?2:3) + (is_n?1:0) + (is_insert?1:0);
2104421056 p1 = ~0U;
2104521057 for (s = s1; s<se; ++s) {
2104621058 ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
2104721059 (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
21048- arg2 = compile(s,ns,depth1,0,block_flags); // Element
21049- p2 = size(arg2 );
21050- if (p1==~0U) p1 = p2 ;
21060+ arg3 = compile(s,ns,depth1,0,block_flags); // Element
21061+ p3 = size(arg3 );
21062+ if (p1==~0U) p1 = p3 ;
2105121063 else {
21052- if (!p1) _cimg_mp_check_type(arg2,p3 ,1,0);
21053- else _cimg_mp_check_type(arg2,p3 ,2,p1);
21064+ if (!p1) _cimg_mp_check_type(arg3,pos ,1,0);
21065+ else _cimg_mp_check_type(arg3,pos ,2,p1);
2105421066 }
21055- CImg<ulongT>::vector(arg2 ).move_to(l_opcode);
21067+ CImg<ulongT>::vector(arg3 ).move_to(l_opcode);
2105621068 s = ns;
21057- ++p3 ;
21069+ ++pos ;
2105821070 }
21059- if (p1==~0U) compile(++s1,se1,depth1,0,block_flags); // Missing element -> error
21071+ if (p1==~0U && !is_n ) compile(++s1,se1,depth1,0,block_flags); // Missing element -> error, if !is_n
2106021072 (l_opcode>'y').move_to(opcode);
21061- opcode[4 ] = p1;
21062- opcode[5 ] = opcode._height;
21073+ opcode[5 ] = p1;
21074+ opcode[6 ] = opcode._height;
2106321075 opcode.move_to(code);
2106421076 _cimg_mp_return_nan();
2106521077 }
@@ -21071,7 +21083,7 @@ namespace cimg_library {
2107121083 s0 = ss + 11; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
2107221084 p1 = compile(ss + 11,s0++,depth1,0,block_flags);
2107321085 _cimg_mp_check_notnan_index(p1,ss + 11);
21074- } else { p1 = 11; s0 = ss + 10; }
21086+ } else { p1 = 11; s0 = ss + 10; } // Default: #-1
2107521087 _cimg_mp_check_list();
2107621088
2107721089 arg1 = arg2 = ~0U;
@@ -21091,7 +21103,7 @@ namespace cimg_library {
2109121103 s0 = ss + 9; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
2109221104 p1 = compile(ss + 9,s0++,depth1,0,block_flags);
2109321105 _cimg_mp_check_notnan_index(p1,ss + 9);
21094- } else { p1 = 11; s0 = ss + 8; }
21106+ } else { p1 = 11; s0 = ss + 8; } // Default: #-1
2109521107 _cimg_mp_check_list();
2109621108 _cimg_mp_scalar1(da_size,p1);
2109721109 }
@@ -26568,25 +26580,34 @@ namespace cimg_library {
2656826580 return cimg::type<double>::nan();
2656926581 }
2657026582
26571- static double mp_da_insert_or_push(_cimg_math_parser& mp) {
26572- const bool is_push_heap = mp.opcode[3]==~0U - 1, is_push = mp.opcode[3]>=~0U - 1;
26573- const char *const s_op = is_push_heap?"da_push_heap":is_push?"da_push":"da_insert";
26583+ static double mp_da_insert_or_push_n(_cimg_math_parser& mp) {
26584+ const unsigned int count = (unsigned int)(mp.opcode[3]==~0U?1:std::max(_mp_arg(3),0.));
26585+ if (!count) return cimg::type<double>::nan();
26586+ const bool
26587+ is_n = mp.opcode[3]!=~0U,
26588+ is_push_heap = mp.opcode[4]==~0U - 1,
26589+ is_push = mp.opcode[4]>=~0U - 1;
26590+ const char *const s_op =
26591+ is_push_heap?(is_n?"da_push_heap_n":"da_push_heap"):
26592+ is_push?(is_n?"da_push_n":"da_push"):
26593+ (is_n?"da_insert_n":"da_insert");
26594+ const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.imglist.width());
26595+ CImg<T> &img = mp.imglist[ind];
2657426596 mp_check_list(mp,s_op);
2657526597 const unsigned int
26576- dim = (unsigned int)mp.opcode[4],
26577- _dim = std::max(1U,dim),
26578- nb_elts = (unsigned int)mp.opcode[5] - 6,
26579- ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.imglist.width());
26580- CImg<T> &img = mp.imglist[ind];
26598+ dim = (unsigned int)(mp.opcode[5]==~0U?img._spectrum:mp.opcode[5]),
26599+ dim1 = std::max(1U,dim),
26600+ nb_elts = (unsigned int)mp.opcode[6] - 7,
26601+ nb_elts1 = std::max(1U,nb_elts);
2658126602 const int
2658226603 siz = img?(int)cimg::float2uint(img[img._height - 1]):0,
26583- pos0 = is_push?siz:(int)_mp_arg(3 ),
26604+ pos0 = is_push?siz:(int)_mp_arg(4 ),
2658426605 pos = pos0<0?pos0 + siz:pos0;
2658526606
26586- if (img && _dim !=img._spectrum)
26607+ if (img && dim1 !=img._spectrum)
2658726608 throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function '%s()': "
2658826609 "Element to insert has invalid size %u (should be %u).",
26589- mp.imgout.pixel_type(),s_op,_dim ,img._spectrum);
26610+ mp.imgout.pixel_type(),s_op,dim1 ,img._spectrum);
2659026611 if (img && (img._width!=1 || img._depth!=1 || siz<0 || siz>img.height() - 1))
2659126612 throw CImgArgumentException("[" cimg_appname "_math_parser] CImg<%s>: Function '%s()': "
2659226613 "Specified image #%u of size (%d,%d,%d,%d) cannot be used as dynamic array%s.",
@@ -26598,31 +26619,42 @@ namespace cimg_library {
2659826619 "Invalid position %d (not in range -%d...%d).",
2659926620 mp.imgout.pixel_type(),s_op,pos0,siz,siz);
2660026621
26601- if (siz + nb_elts + 1>=img._height) // Increase size of dynamic array, if necessary
26602- img.resize(1,2*siz + nb_elts + 1,1,_dim ,0);
26622+ if (siz + count*nb_elts1 + 1>=img._height) // Increase size of dynamic array, if necessary
26623+ img.resize(1,2*siz + count*nb_elts1 + 1,1,dim1 ,0);
2660326624
2660426625 if (pos!=siz) // Move existing data in dynamic array
26605- cimg_forC(img,c) std::memmove(img.data(0,pos + nb_elts,0,c),img.data(0,pos,0,c),(siz - pos)*sizeof(T));
26606-
26607- if (!dim) // Scalar or vector1() elements
26608- for (unsigned int k = 0; k<nb_elts; ++k) {
26609- int index = pos + k;
26610- img[index] = (T)_mp_arg(6 + k);
26611- if (is_push_heap) while (index>0) { // Heapify-up
26626+ cimg_forC(img,c) std::memmove(img.data(0,pos + count*nb_elts1,0,c),img.data(0,pos,0,c),(siz - pos)*sizeof(T));
26627+
26628+ if (dim1==1) { // Scalar or vector1() elements
26629+ if (nb_elts) {
26630+ 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));
26633+ } else std::memset(&img[pos],0,count*sizeof(T));
26634+ if (is_push_heap) for (unsigned int k = 0; k<nb_elts; ++k) {
26635+ int index = pos + k;
26636+ while (index>0) { // Heapify-up
2661226637 const int index_parent = (index - 1)/2;
2661326638 if (img[index]<img[index_parent]) {
2661426639 cimg::swap(img[index],img[index_parent]);
2661526640 index = index_parent; }
2661626641 else break;
2661726642 }
26618- }
26619- else // vectorN() elements, with N>1
26620- for (unsigned int k = 0; k<nb_elts; ++k) {
26621- int index = pos + k;
26622- const double *const ptrs = &_mp_arg(6 + k) + 1;
26623- T *ptrd = img.data(0,index);
26624- cimg_forC(img,c) { *ptrd = ptrs[c]; ptrd+=img._height; }
26625- if (is_push_heap) while (index>0) { // Heapify-up
26643+ }
26644+ } else { // vectorN() elements, with N>1
26645+ if (nb_elts) {
26646+ for (unsigned int k = 0; k<nb_elts; ++k) {
26647+ T *ptrd = img.data(0,pos + k);
26648+ const double *const ptrs = &_mp_arg(7 + k) + 1;
26649+ cimg_forC(img,c) { *ptrd = ptrs[c]; ptrd+=img._height; }
26650+ }
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));
26654+ } 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) {
26656+ int index = pos + k;
26657+ while (index>0) { // Heapify-up
2662626658 const int index_parent = (index - 1)/2;
2662726659 if (img[index]<img[index_parent]) {
2662826660 T *ptr0 = img.data(0,index), *ptr1 = img.data(0,index_parent);
@@ -26631,8 +26663,9 @@ namespace cimg_library {
2663126663 }
2663226664 else break;
2663326665 }
26634- }
26635- img[img._height - 1] = cimg::uint2float(siz + nb_elts,(T)0);
26666+ }
26667+ }
26668+ img[img._height - 1] = cimg::uint2float(siz + count*nb_elts1,(T)0);
2663626669 return cimg::type<double>::nan();
2663726670 }
2663826671
@@ -26769,7 +26802,7 @@ namespace cimg_library {
2676926802 _mp_debug(complex_sqrt): _mp_debug(complex_tan): _mp_debug(complex_tanh): _mp_debug(continue):
2677026803 _mp_debug(convolve): _mp_debug(copy): _mp_debug(correlate): _mp_debug(cos): _mp_debug(cosh): _mp_debug(cov):
2677126804 _mp_debug(critical): _mp_debug(cross): _mp_debug(cumulate): _mp_debug(cut):
26772- _mp_debug(da_back_or_pop): _mp_debug(da_freeze): _mp_debug(da_insert_or_push ):
26805+ _mp_debug(da_back_or_pop): _mp_debug(da_freeze): _mp_debug(da_insert_or_push_n ):
2677326806 _mp_debug(da_remove): _mp_debug(da_size): _mp_debug(date): _mp_debug(debug): _mp_debug(decrement):
2677426807 _mp_debug(deg2rad): _mp_debug(det): _mp_debug(diag): _mp_debug(div): _mp_debug(do): _mp_debug(dot):
2677526808 _mp_debug(echo): _mp_debug(ellipse): _mp_debug(epoch): _mp_debug(eq): _mp_debug(equalize):
0 commit comments