Math processor problem

I’d like to write a custom command substring, say

_karo_substr : skip “${2=0} ${3=3}”
(’"$1"’) u {`st=[{^}];a=$2<0?(size(st)+$2):$2;b=(a+$3)>size(st)?size(st)-a:$3;st[a,b,1]`} rm.

where the first parameter is the string, 2nd the start location either positive or negative (from end) and the 3rd the length.

I get aen error, not just understandable:

gmic _karo_substr qwertzui,2,5 e \${}
[gmic]-0./ Start G’MIC interpreter.
[gmic] *** Error in ./_karo_substr/ (file ‘/Users/karo/.gmic’, line #1909) *** Item substitution ‘{st=[113,119,101,114,116,122,1(...)e(st)?size(st)-a:5;st[a,b,1]}’: Value accessor ‘[]’: Second argument (of type ‘scalar’) is not a strictly positive integer constant, in expression ‘…st[a,b,1]’.

If I replace st[a,b,1] by st[a,$3,1] no error occurs!

gmic _karo_substr qwertzui,2,5 e \${}
[gmic]-0./ Start G’MIC interpreter.
[gmic]-0./ ertzu
[gmic]-0./ End G’MIC interpreter.

Any Idea?

But here, b=size(st)-a which is probably negative in your case. Check by adding with print(b) somewhere.

It’s not! I tried it with max(b,0) as well as with print()! It is a compilation error independent on the value. I think it is the usage of a variable as second param.

Ha yes, actually, b must be defined as a constant value, because its value has to be known at compilation (in math parser, size of vectors are determined at compilation time).
This means a must be declared as a const too, so:

_karo_substr : skip "${2=0} ${3=3}"
  u {`"
    const a = $2<0?(size(st)+$2):$2;
    const b = (a+$3)>size(st)?size(st)-a:$3;

test :
  _karo_substr qwertzui,2,5
  e ${}

Thank you David!

However, that is tricky, I have not registered the existence of const declaration.

I finished now with

_karo_substr : skip “{1=} {2=0} ${3=3}” check isnum($2)&&$2>=0?$2<narg({’"$1"’}):-$2<=narg({’"$1"’})&&isnum($3)&&$3>0
u {" st=["{^}"]; const a = $2<0?(size(st)+$2):$2; const b = (a+$3)>size(st)?size(st)-a:$3; st[a,b]"}

May be it could serve as a pattern for some “strsub” standard custom function to accomplish strlen, str(upper|lower)case functions.

  • strlen is same as size(), e.g. size(['this is a string']);.
  • uppercase() and lowercase() already exist and works with strings.

Okay, now I have a question. What does {^} mean? I get that text input are treated as numbers in ($1), and the respective number to the characters are inserted. I checked with g’mic reference, it tells me nothing.

Also, one could remove the " character inside ('"$1"').

{^} is actually a shortcut for {@^}, which means the value subset ‘^’ of last image.
A selection or subset of ^something means everything except ‘something’, and here, as something is empty, then it means all values.
So at the end, {^} means all values of the last image.

1 Like

Note that in that case, it’s probably better to write:

"st = crop(); ..."

rather than:

"st = ["{^}"]; ..."

because {^} will be substituted prior to the compilation of the math expression, and if the image is large, this string substitution may take time (whereas using crop() does not imply any prior substitution).

It is also more understandable. Going off what @David_Tschumperle, I read ^all as nothing even though it means all values of last image and before he responded, I was thinking when I see “{^}”, the exception to what?. With st=crop(#-1); it’s pretty clear that the values are from the last image.

David, my English is bad.

I meant substring, possibly named as strsub would be a helpful addition to the other str* custom functions!

crop: yeah, another possibility for substring, I’ll try.

Here is it:

#@cli karo_substr : string,_start(=0),_anz(=3)
#@cli : No test for exceeded _anz! Returning remaining number of chars. If _anz==-1 all remaining chars are returned.
#@cli : Negative _start counts from the end!
karo_substr : skip "${1=This is a string!} ${2=0} ${3=3}" 
  check "isnum($2) && inrange($2,-w,w,1) && isnum($3) && $3>=-1"
  u {`"
    const a = $2<0?(w+$2):$2;
    const b = $3<0?w:((a+$3)>w?w-a:$3);

Still bothering around with strings in gmic script and math. processor !

Custom command strlen: with strings e.g. returned from files (strings with comma!) it returns the length of the string up to the first comma! May be $1 could be replaced by $* in custom command strlen?

Not for me:

foo :
  e {"s = ['this is, really bad!'];
      print(strlen = size(s))"}

displays 20.

I meant the wrapper strlen!

strlen : skip “${1=}” u {narg({’"$1"’})}

It should be probably:

strlen : skip “${1=}” u {narg({’"$*"’})}


Another question: Are the double quotes for these “variables” $1, $* etc. necessary?

Yes they are, if you remove them you won’t be able to deal with strings containing spaces.