diff --git a/CImg.h b/CImg.h index 5b14c296646fd108c6282f5ca9dcc6198db52b00..24bfe7d0c340539649f5cfafd85c54f394699e17 100644 --- a/CImg.h +++ b/CImg.h @@ -19105,6 +19105,38 @@ namespace cimg_library_suffixed { CImg<ulongT>::vector((ulongT)mp_matrix_svd,pos,arg1,p2,p3).move_to(code); _cimg_mp_return(pos); } + + if (!std::strncmp(ss,"swap(",5)) { // Memory swap + _cimg_mp_op("Function 'swap()'"); + ref.assign(14); + s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; + arg1 = p1 = compile(ss5,s1,depth1,ref,is_single); + s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; + arg2 = compile(s1,s2,depth1,ref._data + 7,is_single); + arg3 = ~0U; arg4 = arg5 = 1; + if (s2<se1) { + s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3; + arg3 = compile(s2,s3,depth1,0,is_single); + if (s3<se1) { + s1 = ++s3; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; + arg4 = compile(s3,s1,depth1,0,is_single); + arg5 = s1<se1?compile(++s1,se1,depth1,0,is_single):1; + } + } + if (_cimg_mp_is_vector(arg1) && !ref[0]) ++arg1; + if (_cimg_mp_is_vector(arg2)) { + if (arg3==~0U) arg3 = constant(_cimg_mp_size(arg2)); + if (!ref[7]) ++arg2; + } + if (arg3==~0U) arg3 = 1; + _cimg_mp_check_type(arg3,3,1,0); + _cimg_mp_check_type(arg4,4,1,0); + _cimg_mp_check_type(arg5,5,1,0); + CImg<ulongT>(1,21).move_to(code); + code.back().get_shared_rows(0,6).fill((ulongT)mp_memswap,p1,arg1,arg2,arg3,arg4,arg5); + code.back().get_shared_rows(7,20).fill(ref); + _cimg_mp_return(p1); + } break; case 't' : @@ -22373,6 +22405,52 @@ namespace cimg_library_suffixed { return _mp_arg(1); } + static double mp_memswap(_cimg_math_parser& mp) { + longT siz = (longT)_mp_arg(4); + const longT inc_d = (longT)_mp_arg(5), inc_s = (longT)_mp_arg(6); + if (siz>0) { + const bool + is_doubled = mp.opcode[7]<=1, + is_doubles = mp.opcode[14]<=1; + if (is_doubled && is_doubles) { // (double*) <- (double*) + double + *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[7],siz,inc_d), + *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[14],siz,inc_s); + if (ptrs + (siz - 1)*inc_s<ptrd || ptrs>ptrd + (siz - 1)*inc_d) { + while (siz-->0) { cimg::swap(*ptrd,*ptrs); ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg<doubleT> buf((unsigned int)siz); + const double *ptrb = ptrs; + cimg_for(buf,ptr,double) { *ptr = *ptrb; ptrb+=inc_s; } + ptrb = buf; + while (siz-->0) { *ptrs = *ptrd; *ptrd = *(ptrb++); ptrd+=inc_d; ptrs+=inc_s; } + } + } else if (is_doubled && !is_doubles) { // (double*) <- (float*) + double *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[7],siz,inc_d); + float *ptrs = _mp_memcopy_float(mp,&mp.opcode[14],siz,inc_s); + while (siz-->0) { const float val = *ptrs; *ptrs = (float)*ptrd; *ptrd = val; ptrd+=inc_d; ptrs+=inc_s; } + } else if (!is_doubled && is_doubles) { // (float*) <- (double*) + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[7],siz,inc_d); + double *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[14],siz,inc_s); + while (siz-->0) { const float val = *ptrd; *ptrd = (float)*ptrs; *ptrs = val; ptrd+=inc_d; ptrs+=inc_s; } + } else { // (float*) <- (float*) + float + *ptrd = _mp_memcopy_float(mp,&mp.opcode[7],siz,inc_d), + *ptrs = _mp_memcopy_float(mp,&mp.opcode[14],siz,inc_s); + if (ptrs + (siz - 1)*inc_s<ptrd || ptrs>ptrd + (siz - 1)*inc_d) { + while (siz-->0) { cimg::swap(*ptrd,*ptrs); ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg<floatT> buf((unsigned int)siz); + const float *ptrb = ptrs; + cimg_for(buf,ptr,float) { *ptr = *ptrb; ptrb+=inc_s; } + ptrb = buf; + while (siz-->0) { *ptrs = *ptrd; *ptrd = *(ptrb++); ptrd+=inc_d; ptrs+=inc_s; } + } + } + } + return _mp_arg(1); + } + static double mp_min(_cimg_math_parser& mp) { const unsigned int i_end = (unsigned int)mp.opcode[2]; double val = _mp_arg(3);