From 3711eb5e1613797b582dd2d2b3627523bc7620ea Mon Sep 17 00:00:00 2001 From: David Tschumperle Date: Fri, 9 Feb 2024 11:45:58 +0100 Subject: [PATCH 1/9] Auto-commit for release 3.3.4_pre --- html/header.html | 2 +- html/header_doxygen.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/html/header.html b/html/header.html index bc787f33..935d9f37 100644 --- a/html/header.html +++ b/html/header.html @@ -23,7 +23,7 @@
Logo

- Latest stable version: 3.3.3        Current pre-release: 3.3.4 (2024/02/07) + Latest stable version: 3.3.3        Current pre-release: 3.3.4 (2024/02/09)


diff --git a/html/header_doxygen.html b/html/header_doxygen.html index 50d00033..3a4aa3c3 100644 --- a/html/header_doxygen.html +++ b/html/header_doxygen.html @@ -26,7 +26,7 @@
Logo

- Latest stable version: 3.3.3        Current pre-release: 3.3.4 (2024/02/07) + Latest stable version: 3.3.3        Current pre-release: 3.3.4 (2024/02/09)


From 074e17d61d23109c7f7107026e6fe46f7282d55f Mon Sep 17 00:00:00 2001 From: David Tschumperle Date: Sat, 10 Feb 2024 19:37:33 +0100 Subject: [PATCH 2/9] math_parser: Add support for specifying binary litterals '0b....'. --- CImg.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/CImg.h b/CImg.h index 553733e2..0854222b 100644 --- a/CImg.h +++ b/CImg.h @@ -17261,13 +17261,22 @@ namespace cimg_library { if (!cimg::strcasecmp(s,"inf")) { val = cimg::type::inf(); nb = 1; } else if (!cimg::strcasecmp(s,"nan")) { val = cimg::type::nan(); nb = 1; } if (nb==1 && is_sth) val = -val; - } else if (*s=='0' && (s[1]=='x' || s[1]=='X')) { // Hexadecimal number + } else if (*s=='0' && (s[1]=='x' || s[1]=='X')) { // Hexadecimal litteral is_sth = *ss=='-'; if (cimg_sscanf(s + 2,"%x%c",&arg1,&sep)==1) { nb = 1; val = (double)arg1; if (is_sth) val = -val; } + } else if (*s=='0' && (s[1]=='b' || s[1]=='B')) { // Binary litteral + is_sth = *ss=='-'; + variable_name.assign(64); + if (cimg_sscanf(s + 2,"%63[01]%c",variable_name.data(),&sep)==1) { + nb = 1; + val = (double)std::strtol(variable_name,0,2); + } + if (is_sth) val = -val; + variable_name.assign(); } if (!nb) nb = cimg_sscanf(ss,"%lf%c%c",&val,&(sep=0),&(end=0)); if (nb==1) _cimg_mp_const_scalar(val); @@ -30824,7 +30833,7 @@ namespace cimg_library { bool is_not = false; // Detect preceding '!' operator if (*ptr=='!') { is_not = true; ++ptr; while (*ptr && cimg::is_blank(*ptr)) ++ptr; } - if ((*ptr=='w' || *ptr=='h' || *ptr=='d' || *ptr=='s' || *ptr=='r') || std::sscanf(ptr,"%lf %n",&value,&n)==1) { + if ((*ptr=='w' || *ptr=='h' || *ptr=='d' || *ptr=='s' || *ptr=='r') || cimg_sscanf(ptr,"%lf %n",&value,&n)==1) { if (!n) { switch (*ptr) { case 'w': value = (double)_width; break; From 7889b9a29e624aad85bdb7bc47892dc89f9e1f65 Mon Sep 17 00:00:00 2001 From: David Tschumperle Date: Sat, 10 Feb 2024 19:40:06 +0100 Subject: [PATCH 3/9] . --- CImg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CImg.h b/CImg.h index 0854222b..27e9e20d 100644 --- a/CImg.h +++ b/CImg.h @@ -17270,8 +17270,8 @@ namespace cimg_library { } } else if (*s=='0' && (s[1]=='b' || s[1]=='B')) { // Binary litteral is_sth = *ss=='-'; - variable_name.assign(64); - if (cimg_sscanf(s + 2,"%63[01]%c",variable_name.data(),&sep)==1) { + variable_name.assign(65); + if (cimg_sscanf(s + 2,"%64[01]%c",variable_name.data(),&sep)==1) { nb = 1; val = (double)std::strtol(variable_name,0,2); } From 5dfa95ebcdae8a828e1be3910a4f43bc6c3b7a12 Mon Sep 17 00:00:00 2001 From: David Tschumperle Date: Sun, 11 Feb 2024 18:11:03 +0100 Subject: [PATCH 4/9] . --- CImg.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/CImg.h b/CImg.h index 27e9e20d..6438cc02 100644 --- a/CImg.h +++ b/CImg.h @@ -6907,9 +6907,9 @@ namespace cimg_library { return _fibonacci(n); // Not precise, but better than the wrong overflowing calculation } - //! Calculate greatest common divisor. - inline long gcd(long a, long b) { - while (a) { const long c = a; a = b%a; b = c; } + //! Calculate greatest common divisor of two integers. + inline cimg_long gcd(cimg_long a, cimg_long b) { + while (a) { const cimg_long c = a; a = b%a; b = c; } return b; } @@ -30524,6 +30524,15 @@ namespace cimg_library { return (s%2)?res:(T)((res + kth_smallest((s>>1) - 1))/2); } + //! Return greatest common diviser of all image values. + cimg_long gcd() const { + if (is_empty()) return 0; + const ulongT siz = size(); + cimg_long res = (cimg_long)*data; + for (ulongT k = 1; k Date: Sun, 11 Feb 2024 20:50:31 +0100 Subject: [PATCH 5/9] math_parser(): Make 'gcd()' work for multiple numbers. --- CImg.h | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/CImg.h b/CImg.h index 6438cc02..fafa6aab 100644 --- a/CImg.h +++ b/CImg.h @@ -6908,8 +6908,11 @@ namespace cimg_library { } //! Calculate greatest common divisor of two integers. - inline cimg_long gcd(cimg_long a, cimg_long b) { - while (a) { const cimg_long c = a; a = b%a; b = c; } + template + inline T gcd(T a, T b) { + if (a<0) a = -a; + if (b<0) b = -b; + while (a) { const T c = a; a = b%a; b = c; } return b; } @@ -20927,18 +20930,6 @@ namespace cimg_library { _cimg_mp_scalar3(mp_gauss,arg1,arg2,arg3); } - if (!std::strncmp(ss,"gcd(",4)) { // Gcd - _cimg_mp_op("Function 'gcd()'"); - s1 = ss4; while (s1 values; + if (i_end==5) { // Only a single argument + if ((unsigned)mp.opcode[4]==1) return _mp_arg(3); // Real value + else values.assign(&_mp_arg(3),(unsigned int)mp.opcode[4],1,1,1,true); // Vector value + } else { + unsigned int siz = 0; + for (unsigned int i = 4; i1) std::memcpy(ptr,&_mp_arg(i),len*sizeof(double)); + else *ptr = _mp_arg(i); + ptr+=len; + } + } + return values.gcd(); } #ifdef cimg_mp_func_name @@ -30525,11 +30535,11 @@ namespace cimg_library { } //! Return greatest common diviser of all image values. - cimg_long gcd() const { + T gcd() const { if (is_empty()) return 0; const ulongT siz = size(); - cimg_long res = (cimg_long)*data; - for (ulongT k = 1; k Date: Sun, 11 Feb 2024 22:11:05 +0100 Subject: [PATCH 6/9] . --- CImg.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/CImg.h b/CImg.h index fafa6aab..19416523 100644 --- a/CImg.h +++ b/CImg.h @@ -25762,20 +25762,22 @@ namespace cimg_library { static double mp_gcd(_cimg_math_parser& mp) { const unsigned int i_end = (unsigned int)mp.opcode[2]; - CImg values; + CImg values; if (i_end==5) { // Only a single argument if ((unsigned)mp.opcode[4]==1) return _mp_arg(3); // Real value - else values.assign(&_mp_arg(3),(unsigned int)mp.opcode[4],1,1,1,true); // Vector value - } else { + else values.assign(&_mp_arg(3),(unsigned int)mp.opcode[4]); // Vector value + } else if (i_end==7 && (unsigned int)mp.opcode[4]==1 && (unsigned int)mp.opcode[6]==1) // Two real arguments + return (double)cimg::gcd((cimg_int64)_mp_arg(3),(cimg_int64)_mp_arg(5)); + else { unsigned int siz = 0; for (unsigned int i = 4; i1) std::memcpy(ptr,&_mp_arg(i),len*sizeof(double)); - else *ptr = _mp_arg(i); - ptr+=len; + double *ptrs = &_mp_arg(i); + if (len>1) for (unsigned int k = 0; k Date: Mon, 12 Feb 2024 10:31:52 +0100 Subject: [PATCH 7/9] math_parser(): Add function 'lcm()' that compute the least common divisor between integers. --- CImg.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/CImg.h b/CImg.h index 19416523..46970f96 100644 --- a/CImg.h +++ b/CImg.h @@ -6916,6 +6916,14 @@ namespace cimg_library { return b; } + //! Calculate least common multiple of two integers. + template + inline T lcm(T a, T b) { + if (a<0) a = -a; + if (!a && !b) return 0; + return a*(b/gcd(a,b)); + } + //! Convert character to lower case. inline char lowercase(const char x) { return (char)((x<'A'||x>'Z')?x:x - 'A' + 'a'); @@ -23135,6 +23143,7 @@ namespace cimg_library { !std::strncmp(ss,"sum(",4) || !std::strncmp(ss,"avg(",4) || !std::strncmp(ss,"std(",4) || !std::strncmp(ss,"var(",4) || !std::strncmp(ss,"prod(",5) || !std::strncmp(ss,"gcd(",4) || + !std::strncmp(ss,"lcm(",4) || !std::strncmp(ss,"argmin(",7) || !std::strncmp(ss,"argmax(",7) || !std::strncmp(ss,"argminabs(",10) || !std::strncmp(ss,"argmaxabs(",10) || !std::strncmp(ss,"argkth(",7)) { // Multi-argument functions @@ -23145,6 +23154,7 @@ namespace cimg_library { ss[6]=='('?"Function 'argmax()'": "Function 'argmaxabs()'"): *ss=='g'?"Function 'gcd()'": + *ss=='l'?"Function 'lcm()'": *ss=='s'?(ss[1]=='u'?"Function 'sum()'":"Function 'std()'"): *ss=='k'?"Function 'kth()'": *ss=='p'?"Function 'prod()'": @@ -23160,6 +23170,7 @@ namespace cimg_library { ss[4]=='i'?mp_argminabs: ss[6]=='('?mp_argmax:mp_argmaxabs): *ss=='g'?mp_gcd: + *ss=='l'?mp_lcm: *ss=='s'?(ss[1]=='u'?mp_sum:mp_std): *ss=='k'?mp_kth: *ss=='p'?mp_prod: @@ -26409,6 +26420,29 @@ namespace cimg_library { return kth; } + static double mp_lcm(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg values; + if (i_end==5) { // Only a single argument + if ((unsigned)mp.opcode[4]==1) return _mp_arg(3); // Real value + else values.assign(&_mp_arg(3),(unsigned int)mp.opcode[4]); // Vector value + } else if (i_end==7 && (unsigned int)mp.opcode[4]==1 && (unsigned int)mp.opcode[6]==1) // Two real arguments + return (double)cimg::lcm((cimg_int64)_mp_arg(3),(cimg_int64)_mp_arg(5)); + else { + unsigned int siz = 0; + for (unsigned int i = 4; i1) for (unsigned int k = 0; k Date: Mon, 12 Feb 2024 10:39:26 +0100 Subject: [PATCH 8/9] . --- CImg.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/CImg.h b/CImg.h index 46970f96..659faaa2 100644 --- a/CImg.h +++ b/CImg.h @@ -23137,16 +23137,14 @@ namespace cimg_library { } } - if (!std::strncmp(ss,"max(",4) || !std::strncmp(ss,"min(",4) || - !std::strncmp(ss,"maxabs(",7) || !std::strncmp(ss,"minabs(",7) || - !std::strncmp(ss,"med(",4) || !std::strncmp(ss,"kth(",4) || - !std::strncmp(ss,"sum(",4) || !std::strncmp(ss,"avg(",4) || - !std::strncmp(ss,"std(",4) || !std::strncmp(ss,"var(",4) || - !std::strncmp(ss,"prod(",5) || !std::strncmp(ss,"gcd(",4) || - !std::strncmp(ss,"lcm(",4) || - !std::strncmp(ss,"argmin(",7) || !std::strncmp(ss,"argmax(",7) || - !std::strncmp(ss,"argminabs(",10) || !std::strncmp(ss,"argmaxabs(",10) || - !std::strncmp(ss,"argkth(",7)) { // Multi-argument functions + if (!std::strncmp(ss,"argkth(",7) || !std::strncmp(ss,"avg(",4) || + !std::strncmp(ss,"argmax(",7) || !std::strncmp(ss,"argmin(",7) || + !std::strncmp(ss,"argmaxabs(",10) || !std::strncmp(ss,"argminabs(",10) || + !std::strncmp(ss,"gcd(",4) || !std::strncmp(ss,"kth(",4) || !std::strncmp(ss,"lcm(",4) || + !std::strncmp(ss,"max(",4) || !std::strncmp(ss,"maxabs(",7) || !std::strncmp(ss,"med(",4) || + !std::strncmp(ss,"min(",4) || !std::strncmp(ss,"minabs(",7) || !std::strncmp(ss,"prod(",5) || + !std::strncmp(ss,"std(",4) || !std::strncmp(ss,"sum(",4) || !std::strncmp(ss,"var(",4) + ) { // Multi-argument functions _cimg_mp_op(*ss=='a'?(ss[1]=='v'?"Function 'avg()'": ss[3]=='k'?"Function 'argkth()'": ss[4]=='i' && ss[6]=='('?"Function 'argmin()'": From 2afa3c7aa3dcc430215354ebecb827b465a00921 Mon Sep 17 00:00:00 2001 From: David Tschumperle Date: Mon, 12 Feb 2024 10:57:31 +0100 Subject: [PATCH 9/9] . --- CImg.h | 51 ++++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/CImg.h b/CImg.h index 659faaa2..ca2a4df1 100644 --- a/CImg.h +++ b/CImg.h @@ -23138,44 +23138,41 @@ namespace cimg_library { } if (!std::strncmp(ss,"argkth(",7) || !std::strncmp(ss,"avg(",4) || - !std::strncmp(ss,"argmax(",7) || !std::strncmp(ss,"argmin(",7) || - !std::strncmp(ss,"argmaxabs(",10) || !std::strncmp(ss,"argminabs(",10) || + !std::strncmp(ss,"argmax(",7) || !std::strncmp(ss,"argmaxabs(",10) || + !std::strncmp(ss,"argmin(",7) || !std::strncmp(ss,"argminabs(",10) || !std::strncmp(ss,"gcd(",4) || !std::strncmp(ss,"kth(",4) || !std::strncmp(ss,"lcm(",4) || !std::strncmp(ss,"max(",4) || !std::strncmp(ss,"maxabs(",7) || !std::strncmp(ss,"med(",4) || !std::strncmp(ss,"min(",4) || !std::strncmp(ss,"minabs(",7) || !std::strncmp(ss,"prod(",5) || !std::strncmp(ss,"std(",4) || !std::strncmp(ss,"sum(",4) || !std::strncmp(ss,"var(",4) ) { // Multi-argument functions - _cimg_mp_op(*ss=='a'?(ss[1]=='v'?"Function 'avg()'": - ss[3]=='k'?"Function 'argkth()'": - ss[4]=='i' && ss[6]=='('?"Function 'argmin()'": - ss[4]=='i'?"Function argminabs()'": - ss[6]=='('?"Function 'argmax()'": - "Function 'argmaxabs()'"): + _cimg_mp_op(*ss=='a'?(ss[3]=='k'?"Function 'argkth()'": + ss[1]=='v'?"Function 'avg()'": + ss[4]=='a'?(ss[6]=='('?"Function 'argmax()'":"Function 'argmaxabs()'"): + ss[6]=='('?"Function 'argmin()'":"Function 'argminabs()'"): *ss=='g'?"Function 'gcd()'": - *ss=='l'?"Function 'lcm()'": - *ss=='s'?(ss[1]=='u'?"Function 'sum()'":"Function 'std()'"): *ss=='k'?"Function 'kth()'": + *ss=='l'?"Function 'lcm()'": + *ss=='m'?(ss[1]=='a'?(ss[3]=='('?"Function 'max()'":"Function 'maxabs()'"): + ss[1]=='e'?"Function 'med()'": + ss[3]=='('?"Function 'min()'":"Function 'minabs()'"): *ss=='p'?"Function 'prod()'": - *ss=='v'?"Function 'var()'": - ss[1]=='i'?(ss[3]=='('?"Function 'min()'": - "Function 'minabs()'"): - ss[1]=='a'?(ss[3]=='('?"Function 'max()'": - "Function 'maxabs()'"): - "Function 'med()'"); - op = *ss=='a'?(ss[1]=='v'?mp_avg: - ss[3]=='k'?mp_argkth: - ss[4]=='i' && ss[6]=='('?mp_argmin: - ss[4]=='i'?mp_argminabs: - ss[6]=='('?mp_argmax:mp_argmaxabs): + *ss=='s'?(ss[1]=='t'?"Function 'std()'":"Function 'sum()'"): + "Function 'var()'"); + + op = *ss=='a'?(ss[3]=='k'?mp_argkth: + ss[1]=='v'?mp_avg: + ss[4]=='a'?(ss[6]=='('?mp_argmax:mp_argmaxabs): + ss[6]=='('?mp_argmin:mp_argminabs): *ss=='g'?mp_gcd: - *ss=='l'?mp_lcm: - *ss=='s'?(ss[1]=='u'?mp_sum:mp_std): *ss=='k'?mp_kth: + *ss=='l'?mp_lcm: + *ss=='m'?(ss[1]=='a'?(ss[3]=='('?mp_max:mp_maxabs): + ss[1]=='e'?mp_med: + ss[3]=='('?mp_min:mp_minabs): *ss=='p'?mp_prod: - *ss=='v'?mp_var: - ss[1]=='i'?(ss[3]=='('?mp_min:mp_minabs): - ss[1]=='a'?(ss[3]=='('?mp_max:mp_maxabs): - mp_med; + *ss=='s'?(ss[1]=='t'?mp_std:mp_sum): + mp_var; + is_sth = true; // Tell if all arguments are constant pos = scalar(); CImg::vector((ulongT)op,pos,0).move_to(l_opcode);