G'MIC uncaught exception.

It seems like I ran into a error I have never seen before. And it’s supposed to work. By executing this:

$ sp cat _rep_calc_product_of_image

I get this output:

D:\Programs\G'MIC\gmic-community>gmic sp cat _rep_calc_product_of_image
[gmic]./ Start G'MIC interpreter (v.3.5.1).
[gmic]./ Input sample image 'cat' (1 image 600x550x1x3).
[gmic_math_parser] accumulative_coeff = (uninitialized) (mem[35]: scalar)
[gmic_math_parser] accumulative_exponent = (uninitialized) (mem[36]: scalar)libc++abi: terminating due to uncaught exception of type gmic_library::CImgArgumentException: [instance(18,1,1,1,0000024B92E9C850,shared)] CImg<float64>::operator*(): Invalid multiplication of instance by specified matrix (18,1,1,1,0000024B92E9D490).

And the code in question:

_rep_calc_product_of_image:
check $!==1
eval[-1] "begin(
		convert_to_scientific_notation(value)=(
			value?(
				current_exponent=floor(log10(abs(value)));
				current_coeff=value/(10^current_exponent);
			):(
				current_exponent=0;
				current_coeff=0;
			);
		);
		accumulate()=(
			accumulative_exponent+=current_exponent;
			t_prod=current_coeff*accumulative_coeff;
			abs(t_prod)>10?(
				t_prod=t_prod/10;
				++accumulative_exponent;
			);
			accumulative_coeff=t_prod;
		);
		accumulative_coeff=1;
		accumulative_exponent=0;
	);
	current_scientific_notation=convert_to_scientific_notation(i);
	accumulate();
	i;
	end(
		merge('accumulative_coeff',*);
		merge('accumulative_exponent',+);
		accumulative_coeff?(
			current_exponent=floor(log10(abs(accumulative_coeff)));
			accumulative_exponent+=current_exponent;
			accumulative_coeff=accumulative_coeff/(10^current_exponent);
		):(
			accumulative_coeff=0;
			accumulative_exponent=0;
		);
		print(accumulative_coeff);
		print(accumulative_exponent);
	);
	"

And last time I checked with > at beginning. It’s fits in double and it works.

Proof:

D:\Programs\G'MIC\gmic-community>gmic sp cat _rep_calc_product_of_image
[gmic]./ Start G'MIC interpreter (v.3.5.1).
[gmic]./ Input sample image 'cat' (1 image 600x550x1x3).
[gmic_math_parser] accumulative_coeff = (uninitialized) (mem[35]: scalar)
[gmic_math_parser] accumulative_exponent = (uninitialized) (mem[36]: scalar)
[gmic_math_parser] accumulative_coeff = 9.6579518150798673
[gmic_math_parser] accumulative_exponent = 1894028
[gmic]./ Display image [0] = 'cat'.
[0] = 'cat':
  size = (600,550,1,3) [3867.2 Kio of float32].
  data = (202,212,212,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,212,219,212,212,212,212,212,212,212,212,212,202,202,202,202,202,202,202,212,212,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,193,193,193,193,193,193,193,188,188,188, ... ,140,128,95,95,79,80,70,81,89,95,117,115,95,70,62,70,70,51,46,45,79,99,117,128,133,128,117,59,16,19,70,80,81,89,99,79,70,79,81,115,128,128,95,59,79,106,117,117,128,128,79,79,95,103,103,95,70,79,128,147,146,117,59,13).
  min = 4, max = 244, mean = 113.418, std = 66.7982, coords_min = (293,0,0,0), coords_max = (144,29,0,0).
[gmic]./ End G'MIC interpreter.

It should be:

    merge(accumulative_coeff,*);
    merge(accumulative_exponent,+);

(why did you add '') ?

Oh, I used set() before, and made a mistake. That’s all.

@Reptorian , it’s interesting because your “bug report” made me realize that there was indeed a problem with merge() and more generally with how multi-threading is enabled when evaluating math expression. So, there is indeed a bug in the math expression evaluator.

Basically, if you force the multi-threaded evaluation of a math expression on an image (using fill or eval) where the number of image values is less than the number of available threads (N), then N threads were created anyway, which makes merge() returns a wrong result.

This is something that needs to be investigated!

There are times when I did wanted to use multi-threading on empty indice eval. But, I have my workarounds to that.

OK, so that was actually another bug.
Commit: . · GreycLab/CImg@9c50bdd · GitHub allow to evaluate a math expression, even when the corresponding image is empty (so that code in begin() and end() is evaluated). For instance,

0 eval. "begin(print(pi))"

will now print the value of pi on the console.

What about this? eval :print(t)

That code doesn’t print multiple threads.

You meant 10 eval. :print(t) ?

No, I didn’t. That is what I mean.

I asked, because eval "sth" is actually never done in parallel.

What can be parallelized when using eval and fill is the loop that traverse image values, that why you always need a math expression related to a loop over an image to enable parallelization (so fill or eval[selection], but not eval without a selection).

I’ve posted new pre-release binaries today, with the latest fixes.