[RFC]: add `@stdlib/assert/is-complex-string`
Description
This RFC proposes adding package @stdlib/assert/is-complex-string.
The package should be similar in structure to @stdlib/complex/reviver-float32.
The goal is to assert if an input string is of a complex number format string(a + ib) or (a+bi)
where, a and b are numbers
function isComplexString( str ) => boolean
Eg : isComplexString( "32+12i" ) returns true Eg : isComplexString( "32+i12" ) returns true Eg : isComplexString( null ) returns true Eg : isComplexString( "" ) returns false Eg : isComplexString( "abcd+12i" ) returns false Eg : isComplexString( Infinity ) returns false
Package:
@stdlib/assert/is-complex-stringAlias:isComplexString
Related Issues
Can help with issues #1332 and #1333
Questions
This is my first issue so I'd like to know if the way I have proposed the feature is correct
Other
No response
Checklist
- [X] I have read and understood the Code of Conduct.
- [X] Searched for existing issues and pull requests.
- [X] The issue name begins with
RFC:.
:wave: Hi there! :wave:
And thank you for opening your first issue! We will get back to you shortly. :runner: :dash:
I would like to implement this myself. as a supporting assertion to #1332
ok, so I took the initiative to start implementing this and I figured there would be 2 ways to approach this
one, using a regex
/^[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?[-+]\d*\.?\d*(?:[eE][-+]?\d+)?i$/
This regex is quite popular as I have seen it everywhere on the internet while trying to look for a regex
secondly, I could implement a function to manually parse the string something like this
function isComplexString( str ) {
if ( !isString( str ) ) {
return false;
}
let re = '';
let im = '';
let hasIota = false;
let i = 0;
while (str[i] === ' ') {
i++;
}
while (i < str.length && (str[i] >= '0' && str[i] <= '9' || str[i] === '.'
|| str[i] === '+' || str[i] === '-')) {
if (str[i] === 'i') {
return false; // 'i' must not be in the real part
}
re += str[i++];
}
if (re.length === 0) {
return false; // No real part
}
if (str[i] === '+' || str[i] === '-') {
im += str[i++];
}
while (i < str.length && (str[i] >= '0' && str[i] <= '9' || str[i] === '.'
|| str[i] === 'i')) {
if (str[i] === 'i') {
if (hasIota) {
return false; // Duplicate 'i'
}
hasIota = true;
}
im += str[i++];
}
if (!hasIota) {
return false; // No 'i' in the imaginary part
}
while (i < str.length) {
if (str[i++] !== ' ') {
return false; // non whitespace character after end of the string
}
}
return true;
}
which one of these approaches would be preferable according to the standards of other implementations in the codebas? @Planeshifter @kgryte
You're right to identify that we need to handle exponential notation (see your regex).
1 + 2i
1
2i
-2i
2i
1.523 - 4.234i
-1.5 + 4.2i
1.0e10 -2.0e-10i
1.0E10 + 4.1e+10i
1+2i
1-0i
0+1i
-0.0 + 2.0i
NaN + NaNi
Infinity-Infinityi
These should all be valid. Notice that we should also handle NaNs and infinities.
My initial sense is that I suggest implementing a manual tokenizer/parser, as a regexp is more likely to be fiddly and given the variety of values, signs, etc, likely to become inscrutable.
@marsian83 Perhaps before actually implementing this function and inlining the implementation, you should propose implementing @stdlib/complex/base/parse-string, which implements the tokenizer/parser and, if the string is valid, returns a complex-like object (e.g., { 're': 3.0, 'im': 5.0 }) or, if the string is not valid, returns null.
Then in this package, the implementation is simply
function isComplexString( value ) {
return (
isString( value ) &&
parse( value ) !== null
);
}
@marsian83 Perhaps before actually implementing this function and inlining the implementation, you should propose implementing
@stdlib/complex/base/parse-string, which implements the tokenizer/parser and, if the string is valid, returns a complex-like object (e.g.,{ 're': 3.0, 'im': 5.0 }) or, if the string is not valid, returnsnull.Then in this package, the implementation is simply
function isComplexString( value ) { return ( isString( value ) && parse( value ) !== null ); }
Hi @kgryte , I have implemented the parse function but when trying to lint I have been facing this issue since my first issue
please Can you help me resolve this
Hey there! Can you assign me this issue?
@marsian83 Please run make init, which will initialize the missing ESLint plugin.
@marsian83 Please run
make init, which will initialize the missing ESLint plugin.
Hi, now I am just getting different errors
@marsian83 Please run
make init, which will initialize the missing ESLint plugin.Hi, now I am just getting different errors
I was getting these too. Try running make install-node-modules (after restoring the package.json that you might have lost). In my case, I was running it on WSL and setting up was really slow. If you're on windows, I suggest spinning up a Github Codespace instead of developing locally, it takes like 2 minutes to set up with no problems or errors.
@marsian83 Perhaps before actually implementing this function and inlining the implementation, you should propose implementing
@stdlib/complex/base/parse-string, which implements the tokenizer/parser and, if the string is valid, returns a complex-like object (e.g.,{ 're': 3.0, 'im': 5.0 }) or, if the string is not valid, returnsnull.Then in this package, the implementation is simply
function isComplexString( value ) { return ( isString( value ) && parse( value ) !== null ); }
Hi @kgryte , I have made a PR with a possible implementation for this.
Now that the @stdlib/complex/base/parse has been implemented
This can now be implemented as well. I will get to working on this.
Hi, now I am just getting different errors