GreycLab/gmic

v2s() might be not working properly.

Reptorian1125 opened this issue · 4 comments

It seems that rep_find_factors_of is broken for some number. For instance 756.

Pay attention to the data, and the echo output near "G'MIC Interpreter". They're different for this number and some few other number. But, yet 256,100, and many other numbers work fine. This points to v2s() issues.

C:\Windows\System32>gmic echo ${rep_find_factors_of\ 756}
[gmic]-0./ Start G'MIC interpreter.
[gmic]-1./*substitute/rep_find_factors_of/*if#94/ Display image [0] = '[unnamed]', from point (0,1,0).
[0] = '[unnamed]':
  size = (1,3,1,3) [36 b of float32].
  data = (2;3;7 ^ 2;3;1 ^ 0;0;0).
  min = 0, max = 7, mean = 2, std = 2.23607, coords_min = (0,0,0,2), coords_max = (0,2,0,0).
[gmic]-2./*substitute/rep_find_factors_of/*if#94/ Display images [0,1] = '[unnamed], [begin( const num_of_primes(...)_of_primes,0); modulo_list[0]=tv=1; r', from point (0,1,0).
[0] = '[unnamed]':
  size = (1,3,1,3) [36 b of float32].
  data = (2;3;7 ^ 2;3;1 ^ 0;0;0).
  min = 0, max = 7, mean = 2, std = 2.23607, coords_min = (0,0,0,2), coords_max = (0,2,0,0).
[1] = '[begin( const num_of_primes=h#-(...)primes,0); modulo_list[0]=tv=1; repea:
  size = (24,1,1,1) [96 b of float32].
  data = (1,2,4,3,6,12,9,18,36,27,54,108,7,14,28,21,42,84,63,126,252,189,378,756).
  min = 1, max = 756, mean = 93.3333, std = 168.36, coords_min = (0,0,0,0), coords_max = (23,0,0,0).
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2
[gmic]-0./ End G'MIC interpreter.

Here's the modified command for rep_find_factors_of for testing purpose only.

#@cli rep_find_factors_of: num_0...
#@cli : Return the factors found in all numbers at once.
#@cli :
#@cli : Author : Reptorian.
#@cli : $ echo ${rep_find_factors_of\ 256}
#@cli : $ echo ${rep_find_factors_of\ 256,100}
#@cli : $ echo ${rep_find_factors_of\ 256,100,50}
rep_find_factors_of:
if !$# error ("\$\#">0)==F fi

if $#==1
 v=$1

 if $v<0 error inv_inp
 elif $v>5000000000000000 error exc_lim
 elif $v!=int($v) error inv_inp
 elif $v<2 u $v return
 fi

else

 if $#>2 v=${rep_gcd_multiple_numbers\ $*}
 else v={gcd(${1-2})}
 fi

 if $v<2 u $v return fi

fi

1,1,1,3 # Prime Value, Base, Error

eval "
 start_v=v=$v;
 square=int(sqrt(v));

 for(n=2,n<=square&&n<=v,++n,

  isPrime=1;

  for(p=0,p<da_size(#-1),++p,

   prime=(I[#-1,p])[0]-(I[#-1,p])[2];

   if(sqr(prime)>n,
    break();
   );

   if(!(n%prime),
    isPrime=0;
    break();
   );

  );

  if(isPrime,

   count=0;

   while(!(v%n),
     ++count;
     v/=n;
   );

   if(count,
    da_push(#-1,[n,count,0]);
    diff=(da_back(#-1))[0]-n;
    if(diff,I[#-1,da_size(#-1)-1]=[n,count,diff]);
    square=int(sqrt(v));
   );

  );

 );

 if(v!=1,
  da_push(#-1,[v,1,0]);
  diff=(da_back(#-1))[0]-v;
  if(diff,I[#-1,da_size(#-1)-1]=[v,1,diff]);
 );

 output=da_size(#-1)==1&&v==start_v?v:0;
 da_freeze(#-1);

 if(output,
  set('pv',v);
 );

 output;"
 
if ${}
 remove.
 status 1,$pv
else
 display
 {prod(crop(0,0,0,1,1,h,1,1)+1)},1,1,1,"begin(
   const num_of_primes=h#-1;
   primes_freq_choices=crop(#-1,0,0,0,1,1,num_of_primes,1,1)+1;
   primes_list=crop(#-1,0,0,0,0,1,num_of_primes,1,1)-crop(#-1,0,0,0,2,1,num_of_primes,1,1);
   modulo_list=vector(#num_of_primes,0);
   modulo_list[0]=tv=1;
   repeat(num_of_primes-1,p,
    tv*=primes_freq_choices[p];
    modulo_list[p+1]=tv;
   );
   result=vector(#w,0);
  );
  m=int(x/modulo_list)%primes_freq_choices;
  result[x]=prod(primes_list^m);
  end(
   set('{}',v2s(sort(result)));
  );
  "
 display
 remove[-2,-1]
fi

Note that in the last display instance, it appears there's all the numbers which are the factor of 756. However, it doesn't show up with ${} for some reason. Another number which is wrong is 1110. This only happens with some numbers. In many cases, it works as expected.

Please find a minimal use case when v2s() exhibits a strange behavior. It's not possible for me to spend 1h trying to understand what is your issue.

Here's a minimal use case:

foo:

100,1,1,1,:"
 begin(
  v=vectorw(0);
 );
 v[x]=int(u(0,100));
 end(
  set('{}',v2s(v,0));
 );"

echo ${}

Output of ${} differs from image values.

It's not a problem with v2s(). It's because in the end() bloc, the value of v is not what you expect, as print(v) can tell you. This is due to the multi-threaded evaluation of your expression (replace : by >, and it will work).
Code put in begin() and end() is always executed by thread0 (main thread). In your case, what the evaluation does is:

  • thread0 creates a vector v of size 100 and fill it with 0.
  • As the evaluation is multi-threaded, this vector is then duplicated among N threads.
  • Each thread fills a part of this vector (particularly thread0 fills the beginning of this vector, i.e. only the first M values).
  • In the end() block, the v that is referred to is the one from thread0, so it has only the first coefficient filled with something.

You have to understand that there are actually as many independent v vector-valued variables as they are running threads. If you want to "merge" all these resulting v into something, you must explicitly tell the evaluator, by adding for instance

merge(v,+)

at the beginning of the end() block.
Another solution is to disable the multi-threading evaluation, by adding > at the beginning of the expression.

Okay, now I understand why my original find_factors_of didn't work. I was thinking of avoiding to have multiple independent vector at first and it worked for a good time and lost sight at how the code runs. Anyways, I amended the suggested change here - GreycLab/gmic-community@99a7b0c . And it works as expected.