feat: add `math/base/special/cinvf`
Resolves a part of #649
Description
What is the purpose of this pull request?
This pull request:
- resolves part of #649
Related Issues
Does this pull request have any related issues?
This pull request:
- resolves a part of #649
Questions
Any questions for reviewers of this pull request?
No.
Other
Any other information relevant to this pull request? This may include screenshots, references, and/or implementation notes.
Need help with overflow case.
Checklist
Please ensure the following tasks are completed before submitting this pull request.
- [x] Read, understood, and followed the contributing guidelines.
@stdlib-js/reviewers
tape( 'the function may overflow', function test( t ) {
var v;
v = cinvf( new Complex64( 5.0e-324, 5.0e-324 ) );
t.strictEqual( real( v ), PINF, 'real component is +infinity' );
t.strictEqual( imag( v ), NINF, 'imaginary component is -infinity' );
v = cinvf( new Complex64( -5.0e-324, 5.0e-324 ) );
t.strictEqual( real( v ), NINF, 'real component is -infinity' );
t.strictEqual( imag( v ), NINF, 'imaginary component is -infinity' );
v = cinvf( new Complex64( -5.0e-324, -5.0e-324 ) );
t.strictEqual( real( v ), NINF, 'real component is -infinity' );
t.strictEqual( imag( v ), PINF, 'imaginary component is +infinity' );
v = cinvf( new Complex64( 5.0e-324, -5.0e-324 ) );
t.strictEqual( real( v ), PINF, 'real component is +infinity' );
t.strictEqual( imag( v ), PINF, 'imaginary component is +infinity' );
v = cinvf( new Complex64( 0.0, 5.0e-324 ) );
t.strictEqual( real( v ), 0.0, 'real component is 0' );
t.strictEqual( imag( v ), NINF, 'imaginary component is -infinity' );
v = cinvf( new Complex64( 0.0, -5.0e-324 ) );
t.strictEqual( real( v ), 0.0, 'real component is 0' );
t.strictEqual( imag( v ), PINF, 'imaginary component is +infinity' );
v = cinvf( new Complex64( 5.0e-324, 0.0 ) );
t.strictEqual( real( v ), PINF, 'real component is +infinity' );
t.strictEqual( imag( v ), 0.0, 'imaginary component is 0' );
v = cinvf( new Complex64( -5.0e-324, 0.0 ) );
t.strictEqual( real( v ), NINF, 'real component is -infinity' );
t.strictEqual( imag( v ), 0.0, 'imaginary component is 0' );
t.end();
});
Good Afternoon, @gunjjoshi can you please help me out in adding the overflow testcase in test.js and test.native.js as it is not there in this PR right now, i tried various values for this but the complex number real( v ) imag( v ) turns out to be NaN NaN and not Infinity or -Infinity as expected. how did you arrive at the number 5.0e-324?
@aayush0325 Tried the following test on your branch, and it works:
tape( 'the function may produce very large values for very small inputs', function test( t ) {
var v;
v = cinvf( new Complex64( FLOAT32_SMALLEST_NORMAL, FLOAT32_SMALLEST_NORMAL ) );
t.ok( real( v ) > 1e37, 'real component is very large' );
t.ok( imag( v ) < -1e37, 'imaginary component is very large and negative' );
v = cinvf( new Complex64( -FLOAT32_SMALLEST_NORMAL, FLOAT32_SMALLEST_NORMAL ) );
t.ok( real( v ) < -1e37, 'real component is very large and negative' );
t.ok( imag( v ) < -1e37, 'imaginary component is very large and negative' );
v = cinvf( new Complex64( -FLOAT32_SMALLEST_NORMAL, -FLOAT32_SMALLEST_NORMAL ) );
t.ok( real( v ) < -1e37, 'real component is very large and negative' );
t.ok( imag( v ) > 1e37, 'imaginary component is very large and positive' );
v = cinvf( new Complex64( FLOAT32_SMALLEST_NORMAL, -FLOAT32_SMALLEST_NORMAL ) );
t.ok( real( v ) > 1e37, 'real component is very large and positive' );
t.ok( imag( v ) > 1e37, 'imaginary component is very large and positive' );
v = cinvf( new Complex64( 0.0, FLOAT32_SMALLEST_NORMAL ) );
t.strictEqual( real( v ), 0.0, 'real component is 0' );
t.ok( imag( v ) < -1e37, 'imaginary component is very large and negative' );
v = cinvf( new Complex64( 0.0, -FLOAT32_SMALLEST_NORMAL ) );
t.strictEqual( real( v ), 0.0, 'real component is 0' );
t.ok( imag( v ) > 1e37, 'imaginary component is very large and positive' );
v = cinvf( new Complex64( FLOAT32_SMALLEST_NORMAL, 0.0 ) );
t.ok( real( v ) > 1e37, 'real component is very large and positive' );
t.strictEqual( imag( v ), 0.0, 'imaginary component is 0' );
v = cinvf( new Complex64( -FLOAT32_SMALLEST_NORMAL, 0.0 ) );
t.ok( real( v ) < -1e37, 'real component is very large and negative' );
t.strictEqual( imag( v ), 0.0, 'imaginary component is 0' );
t.end();
});
You can try this. I think there might be a loss of precision as we are handling single-precision floating-point numbers and as we are not explicitly returning PINF or NINF in our implementation, so, we are not comparing with exactly PINF and NINF here.
You can declare separate variables for tiny and huge, such as:
var tiny = -1e37;
var huge = 1e37;
and then use them in the tests.
thanks @gunjjoshi! i'll push these changes soon, anything else to add? i'll make all the changes together then.
thanks @gunjjoshi! i'll push these changes soon, anything else to add? i'll make all the changes together then.
Nothing for now, once you've added these tests in both test.js and test.native.js, we can review it.
updated the tests, kindly review @gunjjoshi.
@gunjjoshi even after using stdlib_base_maxf from math/base/special/maxf the tests are failing for C files. i think we should try to write runner.jl to have more accurate data for single-precision floating-point numbers and then see if the same tolerance is working. how should i proceed with this?
@aayush0325 As mentioned above, you should make sure that the fixtures generated fall within the range of single-precision floating-point numbers.
For example, compare the range of fixtures in math/base/special/ln, with that in its single-precision equivalent, i.e., math/base/special/lnf. Notice that we scale down from ~308 to ~38, when we go from double to single-precision.
Something similar needs to be followed here as well.
I have updated the tests with new tolerances and matching data, is this alright @gunjjoshi ?
Coverage Report
| Package | Statements | Branches | Functions | Lines |
|---|---|---|---|---|
| math/base/special/cinvf | $\color{green}213/213$ $\color{green}+100.00\%$ |
$\color{green}10/10$ $\color{green}+100.00\%$ |
$\color{green}2/2$ $\color{green}+100.00\%$ |
$\color{green}213/213$ $\color{green}+100.00\%$ |
The above coverage report was generated for the changes in this PR.
I've updated the benchmarks with the pre-computation as requested, not sure as to why the tests are failing.
The failing tests might be originating from https://github.com/stdlib-js/stdlib/blob/1b6e72293a7bb85803ce5f66ae705f9476fc7cb0/.github/workflows/run_tests_coverage.yml#L213 as we're not declaring botComment, if it is a bot comment.
cc: @Planeshifter
I see, anything else I can do in this PR @gunjjoshi?
The tests seem to be running fine locally for both test.js and test.native.js, not sure why there's an error here.
/stdlib merge
not sure why there's an error here
Test coverage build errors should be resolved now, given recent fixes by @Planeshifter to our CI.
/stdlib merge
@gunjjoshi kindly give this a review!
good morning, i've added a test with hardcoded values where magnitude of the real and imaginary component exceeds LARGE_THRESHOLD so that the code reaches the mentioned block, i have taken these values from the numpy implementation using the following code:
import numpy as np
# Function to compute the inverse of a complex number using single-precision floating-point numbers
def compute_inverse_single_precision(real, imag):
complex_number = np.complex64(real + imag * 1j)
inverse = 1 / complex_number
return inverse
# Given complex numbers
complex_numbers = [
(2e+38, 200),
(-2e+38, 200),
(200, 2e+38),
(200, -2e+38)
]
# Compute inverses
for real, imag in complex_numbers:
inverse = compute_inverse_single_precision(real, imag)
print(f"The inverse of {real} + {imag}I is {inverse}")
which gave me the output:
The inverse of 2e+38 + 200I is (4.999999675228202e-39-0j)
The inverse of -2e+38 + 200I is (-4.999999675228202e-39-0j)
The inverse of 200 + 2e+38I is -4.999999675228202e-39j
The inverse of 200 + -2e+38I is 4.999999675228202e-39j
if there's anything else that i should do then please let me know!
hey is this implementation complete, I was trying to do this one as I did not find it in the source code?
Sorry @kgryte and @aayush0325, I moved on to create a fresh PR for this: https://github.com/stdlib-js/stdlib/pull/7007. I thought that would be more appropriate here.
Thank you for working on this pull request. However, we cannot accept your contribution as the issue this pull request seeks to resolve has already been addressed in a different pull request or commit.
Thank you again for your interest in stdlib, and we look forward to reviewing your future contributions.