# 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}"
('"\$1"')
u {`"
st=["{^}"];
const a = \$2<0?(size(st)+\$2):\$2;
const b = (a+\$3)>size(st)?size(st)-a:\$3;
st[a,b]"`}
rm.

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
(’"\$1"’)
u {`" st=["{^}"]; const a = \$2<0?(size(st)+\$2):\$2; const b = (a+\$3)>size(st)?size(st)-a:\$3; st[a,b]"`}
rm.

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.

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}"
('"\$1"')
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);
crop(a,b)"`}
rm.``````

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({’"\$*"’})}
``````

Yes!

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.