GreycLab / gmic

GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing
Other
69 stars 12 forks source link

v2s() might be not working properly. #8

Closed Reptorian1125 closed 1 year ago

Reptorian1125 commented 1 year ago

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.

dtschump commented 1 year ago

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.

Reptorian1125 commented 1 year ago

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.

dtschump commented 1 year ago

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:

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.

Reptorian1125 commented 1 year ago

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 - https://github.com/GreycLab/gmic-community/commit/99a7b0ca97e3efd3350fbad4e2fe5cfcb3ef4f37 . And it works as expected.