On the road to G'MIC 3.4

I tested the some of the new functions, and they are great so far with only one issue I noted. Only tested rand() and permute().

Issue: The srand() before rand doesn’t seem to do anything to rand. I don’t see that the values are “seeded”. I tested with one srand(), and two rand(), and then I tested with srand(),rand()x2 to see if srand() can change instances of rand().

Issue #2: permute() could have been allowed on a image indexes. However, I think as it is now, I can create a simple command to reorder color according to channels value with crop(#-1).

Also, I think performance has returned back to old G’MIC. That’s appreciated.

Finally, I got something with the new math parser feature:

#@cli rep_sort_colors_by_channels_values:
#@cli : Sort images accordingly to channel values.
rep_sort_colors_by_channels_values:
    foreach {
        eval "
            new_image=permute(crop(#-1),w#-1,h#-1,d#-1,s#-1,'cxyz');
            new_image=sort(new_image,1,whd#-1,s#-1);
            new_image=permute(new_image,s#-1,w#-1,h#-1,d#-1,'yzcx');
            copy(i(#-1,0,0,0,0),new_image[0],whds#-1,1,1);
            "
    }

So. How about another whirl on the Wurlitzer?: 1791890

Something mysterious in the land of widths…

circtest: -skip ${1=30},${2=0},${3=34}
   foreach {
             thick,tstren,angle=$*
             =>. canvas
	     # 100 Circular plots,
	     # centered on w/2,w/2
             100,1,1,2,cexp([0,2*pi*x/(w-1)])
             =>. plots
             f[plots] ">
                        begin(
                        mat=eye(3);
                        scale=0.375*w#0;
                        mat[0]=scale;
                        mat[2]=w#0/2;
                        mat[4]=-scale;
                        mat[5]=w#0/2
		                     );
	     (mat*[I(#$plots,x),1])[0,2]"
	     # curve plot
             curve[canvas] [plots],$thick,$angle,$tstren,1,1,255
	     rm[plots]
   }

Test run. Change tilt strength

gosgood@bertha $gmic run '-m circtest.gmic                         \
                          version                                  \
                          256,256,1,1 =>. canvas                   \
			              +circtest[canvas] 60,0,45    \
			              +circtest[canvas] 60,0.25,45 \
			              +circtest[canvas] 60,0.50,45 \
			              +circtest[canvas] 60,0.75,45 \
			              +circtest[canvas] 60,1.00,45 \
			              keep[^0] append x r2dx. 50%  o. /dev/shm/circtest.jpg'

Obtains:
circtest

Reading the test images backwards, with lessening tilt_strength I would expect a gradual infilling of the two thin areas as the edge of the virtual pen grows thicker/less elliptical, arriving at the image on the left. Two endpoints are fine (tilt_strength = 0/1) but fractional strengths seem strange, with the strangest response at tilt_strength= 0.5.

Have done no spelunking (too busy cleaning up my own messes). Might have time to do traces today. The City calls, but not as stridently as yesterday.

1 Like

Hi,

it seems i don’t get the expected result when applying the filter :


Is there a workaround?

And i tried the same settings on my laptop ( previous settings were on desktop ) and got something different :

1 Like

You are perfectly right. I’ll check and try to fix that.
Also, I’ve already fixed the ‘hole’ in the curve happening in the first case (w/o tilt), that was due to a rounding error in the computed point coordinates.

1 Like

Related to what I posted immediately before you – the thinning pattern is irregular for fractional tilt_strengths. Immediate workaround is to work with tilt strengths of zero or one.

The key bit that I am contemplating stems from remarks in post 16 in the ABN thread. For ±N in the pink area for tilt_strengths<0.5, we obtain thickness indirectly from the green quadrilateral whose height has not entirely vanished. But that configuration still admits the segment P–Pp aligning with ±N at some other orientation, in particular orientations that approach tilt_angle+90° as tilt_strength approaches 0.5.

For tilt_strength > 0.5 ±T orientation dominates and the thin parts thicken, but only at one orientation, tilt_angle+90° and at tilt_strength = 1.0 ±N wholly coincides with ±T and the calligraphic effect is turned off.

Not clear to me yet the reconfiguration approach that needs to be worked out. A cuppa coffee or two, and a few relaxing meetings with assistant commissioners, and it might be clear to me.

Try running ABN Filigrees at reduced opacity, say 0.2, and just one spinner, rather large and look at the preview image. Because of slight overlap between successive plotting of quadrilaterals (two triangles, actually, but same difference) you can actually see how the orientation of ±N varies. You may get a eureka insight from it.

Here’s a better problem statement (maybe). This entails a circular dataset and we are plotting it clockwise. Have the diagram in front of you.

  1. For tilt_strength<0.5 ±N is almost, but not quite, aligned with S and so too is the segment P–Pn.
  2. Say, for successive segments, P–Pp rotates clockwise a certain angle ψ. Necessarily, the perpendicular ±T also rotates at ψ.
  3. But ±N will only rotate at a fraction of ψ, being a blend of (mostly) of the fixed orientation S and (a little bit of) rotating ±T±N rotates at a slower angular rate than either P–Pp or its perpendicular ±T.
  4. Because of this, at some new orientation, P–Pp will “catch up” and align with ±N. That makes a new thin region. This is the issue which is tossing a spanner into the works.

Won’t be able to touch any of this until evening descends on the American North Atlantic seaboard.

OK, not totally fixed, but I’m progressing in the right direction.
I’ve partially recoded command curve to fix a few additional problems your example made me realize (like when curve has very close consecutive points, normal estimation can go really wrong).

Probably some work remains, but this looks better than before.

1 Like

Feature request for v2s(). Can there be a option to set where the numbers goes? Default seems to be starting from the left, but what if I want to set to the right instead? The reason I’d like it is to add {_'0'} or 48 onto 0s, and have the numbers start on the right as a option. So, I can print the remaining zeros.

Also, srand() before rand() still don’t work. Different values every time.

OK @grosgood , I think the tilt issue is now fixed for real!

Lot of things were not being done correctly, that was a very nice trip to find all the quirks.
Now, the tilt angle corresponds to what’s expected (so you won’t need to add 90° to your tilt parameter in your filter).

If you have some time to test and tell me what you think about it, that would be cool :slight_smile:

Not right now, but a couple of hours from now.

Of course. Bugs are almost always more interesting than production code. I’ve frequently felt a let-down after deploying a solution. I’m not talking about routine bugs that are sins of omission or commission, but the kind that force some sort of paradigm shift in how I’ve modeled a problem and conceived a solution. “I’ve found the bug. It’s in my head.” Those are the most entertaining kind.

1 Like

circtest

Yes!

test_abn

As you noted, a few minor adjustments in ABN Filigrees, and that would be that.

2 Likes
  • 2024/01/12: Release of version 3.3.3.
2 Likes

I forgot to mention this, but remember the conversation about u() in the math parser, and you added the _include_(min/max) thing?

I wonder if that needs to be done with rand() as well. Also, there’s the issue of srand() not affecting rand() though.

C:\Windows\System32>gmic echo {srand(50);rand(#5,0,1);}
[gmic]./ Start G'MIC interpreter (v.3.3.3).
0.13243688389948496,0.0086219562237667743,0.93690020589551426,0.34747295043139553,0.34000822746660753
[gmic]./ End G'MIC interpreter.

C:\Windows\System32>gmic echo {srand(50);rand(#5,0,1);}
[gmic]./ Start G'MIC interpreter (v.3.3.3).
0.51519300009012059,0.03471523361157515,0.49972651910496096,0.77842243103739395,0.88865798406504515
[gmic]./ End G'MIC interpreter.

C:\Windows\System32>gmic echo {srand(50);rand(#5,0,1);}
[gmic]./ Start G'MIC interpreter (v.3.3.3).
0.60273454375628721,0.096547843910881281,0.0002792875748777966,0.92015480876903855,0.98068178584349386
[gmic]./ End G'MIC interpreter.

C:\Windows\System32>gmic echo {srand(50);rand(#5,0,1);}
[gmic]./ Start G'MIC interpreter (v.3.3.3).
0.77207849192714284,0.12469581587349433,0.8424506082298352,0.10056414387667648,0.31335092808896464
[gmic]./ End G'MIC interpreter.

About this: I’m actually a bit to blame for agreeing to implement this feature.
in practice, if you want to have a random value in an open range ]a,b[, it’s better (and faster) to write for instance u(a+eps,b-eps) with eps=1e-5 rather than u(a,b,0,0).
At the end, what the algo does is indeed add/subtract an epsilon to the specified bounds, but it does this every time you call the function, while the bounds can often be precalculated as constant values.
So in practice it’s not that interesting to use.
I prefer not to add these options to the new functions rand() then.

Concerning the srand() problem. I will see what I can do, but in any case, remind that for large vectors, the filling with random values will be done in parallel, and in this case, there are no ways to ensure the ordering of the filling is always the same.
So, in the multi-threaded case, srand() is practically useless.

1 Like

Ah, I understand.

Regarding epsilon value. Wouldn’t it be nice to implement C++ nextafter, and the backward version of that? There’s also use in case of modulo operation here, so you can preserve the value to modulo by.

OK so I confirm what I’ve said.
I’ve done a patch to force the rand() function to be sensible to srand() .
And I get this:

foo : check "isint(${1=10}) && $1>0"
  eval "
    srand(10);
    U = round(rand(#$1,0,100));
    srand(10);
    V = round(rand(#$1,0,100));
    print(U,V);
  "

And for small N, I indeed get similar vectors:

$ ./gmic foo 10
[gmic]./ Start G'MIC interpreter (v.3.3.3).
[gmic_math_parser] U = (uninitialized) (mem[36]: vector10)
[gmic_math_parser] V = (uninitialized) (mem[48]: vector10)
[gmic_math_parser] U = [ 24,47,31,92,31,3,26,14,67,43 ] (size: 10)
[gmic_math_parser] V = [ 24,47,31,92,31,3,26,14,67,43 ] (size: 10)
[gmic]./ End G'MIC interpreter.

But for large vectors, the multi-threading evaluation starts and you can’t get equivalent vectors:

$ ./gmic foo 1e6
[gmic]./ Start G'MIC interpreter (v.3.3.3).
[gmic_math_parser] U = (uninitialized) (mem[1000038]: vector1000000)
[gmic_math_parser] V = (uninitialized) (mem[3000041]: vector1000000)
[gmic_math_parser] U = [ 2,1,31,52,28,86,3,93,32,53,88,14,39,83,88,36,59,79,9,25,62,86,31,33,11,52,27,18,45,88,68,12,6,29,39,88,63,82,63,59,69,41,96,0,47,88,41,86,18,15,13,78,77,34,28,0,20,54,3,98,50,69,15,63,...,44,98,99,94,99,28,79,81,71,98,25,9,62,43,26,22,76,64,0,85,85,72,14,43,81,62,12,81,38,2,95,86,23,68,49,13,41,69,18,15,83,59,65,70,32,9,61,33,35,96,13,80,48,25,13,38,12,2,50,11,23,24,47,31 ] (size: 1000000)
[gmic_math_parser] V = [ 54,53,24,6,47,78,79,90,62,76,79,22,39,27,21,55,40,55,16,50,78,19,18,44,29,31,50,63,63,50,56,49,84,41,51,41,76,10,59,37,85,35,43,33,75,68,83,0,59,71,47,54,78,18,60,35,84,69,72,88,46,99,78,28,...,28,79,81,71,98,25,9,62,43,26,22,76,64,0,85,85,72,14,43,81,62,12,81,38,2,95,86,23,68,49,13,41,69,18,15,83,59,65,70,32,9,61,33,35,96,13,80,48,25,13,38,12,2,50,11,23,24,47,31,92,31,3,26,14 ] (size: 1000000)
[gmic]./ End G'MIC interpreter.

Note that you have the same kind of behavior “outside” the math evaluator, when you use the commands rand or noise:

$ gmic 1e6 srand 0 rand 0,255 srand 0 +rand. 0,255

So, my advice here is not to apply a patch that will make srand() works only for small vectors but not for large ones. There is clearly an undefined behavior here, and it’s the kind of nightmare a developer don’t want to have to deal with.

Searching for ‘0x’ yields no result on Math Expression documentation. It would be nice if there was some points about hexadecimal literal, and binary literal there.

2024/02/19: Release of G’MIC 3.3.4.