feat: add math/base/special/trunc2f#10673
feat: add math/base/special/trunc2f#10673Aashrith-Vellampalli wants to merge 1 commit intostdlib-js:developfrom
Conversation
|
👋 Hi there! 👋 And thank you for opening your first pull request! We will review it shortly. 🏃 💨 Getting Started
Next Steps
Running Tests LocallyYou can use # Run tests for all packages in the math namespace:
make test TESTS_FILTER=".*/@stdlib/math/.*"
# Run benchmarks for a specific package:
make benchmark BENCHMARKS_FILTER=".*/@stdlib/math/base/special/sin/.*"If you haven't heard back from us within two weeks, please ping us by tagging the "reviewers" team in a comment on this PR. If you have any further questions while waiting for a response, please join our Zulip community to chat with project maintainers and other community members. We appreciate your contribution! Documentation Links |
|
I noticed your PR description contains closing keywords ("Resolves", "Closes", or "Fixes") referencing a "Tracking Issue". Why this matters: Required action: Thank you for your contribution to the project! |
Planeshifter
left a comment
There was a problem hiding this comment.
Thanks for opening a PR!
Left a bunch of comments; overall, the PR will require significant clean-up, mainly ensuring to use single-precision variants of all dependencies.
|
|
||
| --> | ||
|
|
||
| # trunc2 |
There was a problem hiding this comment.
H1 should be trunc2f, not trunc2.
| # trunc2 | |
| # trunc2f |
| double y = stdlib_base_trunc2f( -4.2 ); | ||
| // returns -4.0 |
There was a problem hiding this comment.
This is a single-precision (float) function. The C usage example should use float, not double, and the literal should have the f suffix. See floor2f for reference.
| double y = stdlib_base_trunc2f( -4.2 ); | |
| // returns -4.0 | |
| float y = stdlib_base_trunc2f( -4.2f ); | |
| // returns -4.0f |
| int main( void ) { | ||
| const double x[] = { 3.14, -3.14, 0.0, 0.0 / 0.0 }; | ||
|
|
||
| double y; | ||
| int i; | ||
| for ( i = 0; i < 4; i++ ) { | ||
| y = stdlib_base_trunc2f( x[ i ] ); | ||
| printf( "trunc2f(%lf) = %lf\n", x[ i ], y ); | ||
| } | ||
| } |
There was a problem hiding this comment.
The C example section uses double throughout but this is a float function. Array should be const float x[] with f-suffixed literals, y should be float, and printf should use %f not %lf. Compare with floor2f.
| int main( void ) { | |
| const double x[] = { 3.14, -3.14, 0.0, 0.0 / 0.0 }; | |
| double y; | |
| int i; | |
| for ( i = 0; i < 4; i++ ) { | |
| y = stdlib_base_trunc2f( x[ i ] ); | |
| printf( "trunc2f(%lf) = %lf\n", x[ i ], y ); | |
| } | |
| } | |
| int main( void ) { | |
| const float x[] = { 3.14f, -3.14f, 0.0f, 0.0f / 0.0f }; | |
| float y; | |
| int i; | |
| for ( i = 0; i < 4; i++ ) { | |
| y = stdlib_base_trunc2f( x[ i ] ); | |
| printf( "trunc2f(%f) = %f\n", x[ i ], y ); | |
| } | |
| } |
| var isnan = require( '@stdlib/math/base/assert/is-nan' ); | ||
| var isInfinite = require( '@stdlib/math/base/assert/is-infinite' ); | ||
| var pow = require( '@stdlib/math/base/special/pow' ); | ||
| var floor = require( '@stdlib/math/base/special/floor' ); | ||
| var log2 = require( '@stdlib/math/base/special/log2' ); | ||
|
|
||
|
|
||
| // MAIN // | ||
|
|
||
| /** | ||
| * Rounds a numeric value to the nearest power of two toward zero. | ||
| * | ||
| * @param {number} x - input value | ||
| * @returns {number} rounded value | ||
| * | ||
| * @example | ||
| * var v = trunc2f( 3.141592653589793 ); | ||
| * // returns 2.0 | ||
| * | ||
| * @example | ||
| * var v = trunc2f( 13.0 ); | ||
| * // returns 8.0 | ||
| * | ||
| * @example | ||
| * var v = trunc2f( -0.314 ); | ||
| * // returns -0.25 | ||
| */ | ||
| function trunc2f( x ) { | ||
| var sign; | ||
| if ( | ||
| isnan( x ) || | ||
| isInfinite( x ) || | ||
| x === 0.0 | ||
| ) { | ||
| return x; | ||
| } | ||
| if ( x < 0 ) { | ||
| x = -x; | ||
| sign = -1.0; | ||
| } else { | ||
| sign = 1.0; | ||
| } | ||
| return sign * pow( 2.0, floor( log2( x ) ) ); |
There was a problem hiding this comment.
This is a single-precision function but the implementation operates entirely in double precision. Compare with floor2f/lib/main.js which uses isnanf, isInfinitef, powf, floorf, f32() wrappers, and float32 constants.
At minimum you need:
isnanf/isInfinitefinstead ofisnan/isInfinitepowfinstead ofpowfloorfinstead offloorf32()conversions at key points to ensure single-precision semantics- Float32 constants (
ZERO,TWO,ONE) likefloor2fdoes
Without these, the function produces double-precision results, which defeats the purpose of the f suffix.
| if ( stdlib_base_is_nan( x ) || stdlib_base_is_infinite( x ) || x == 0.0f ) { | ||
| return x; | ||
| } | ||
|
|
||
| if ( x < 0.0f ) { | ||
| sign = -1.0f; | ||
| } else { | ||
| sign = 1.0f; | ||
| } | ||
| ax = stdlib_base_absf( x ); | ||
| stdlib_base_frexpf( x,&frac ,&exp ); | ||
|
|
||
| return sign * stdlib_base_ldexpf( 1.0f, exp-1 ); |
There was a problem hiding this comment.
Two issues here:
-
stdlib_base_is_nanandstdlib_base_is_infiniteare double-precision checks. For afloatfunction, usestdlib_base_is_nanfandstdlib_base_is_infinitef(fromis_nanf.h/is_infinitef.h). -
axis computed but never used --frexpfis called withx(which can be negative) instead ofax. Either useaxas the argument tofrexpf, or removeaxand theabsfinclude entirely sincefrexpfhandles the sign via the exponent anyway.
Also, spacing: &frac ,&exp should be &frac, &exp.
| "dependencies": [ | ||
| "@stdlib/math/base/napi/unary", | ||
| "@stdlib/math/base/special/frexpf", | ||
| "@stdlib/math/base/special/ldexpf", | ||
| "@stdlib/math/base/assert/is-nan", | ||
| "@stdlib/math/base/assert/is-infinite" | ||
| ] | ||
| }, | ||
| { | ||
| "task": "benchmark", | ||
| "src": [ | ||
| "./src/main.c" | ||
| ], | ||
| "include": [ | ||
| "./include" | ||
| ], | ||
| "libraries": [ | ||
| "-lm" | ||
| ], | ||
| "libpath": [], | ||
| "dependencies": [ | ||
| "@stdlib/math/base/napi/unary", | ||
| "@stdlib/math/base/special/frexpf", | ||
| "@stdlib/math/base/special/ldexpf", | ||
| "@stdlib/math/base/assert/is-nan", | ||
| "@stdlib/math/base/assert/is-infinite" | ||
| ] |
There was a problem hiding this comment.
The manifest.json dependencies don't match what src/main.c actually uses. Currently listed: frexpf, ldexpf, is-nan, is-infinite. But main.c also includes absf and float32/base/exponent (unused). And is-nan/is-infinite should be is-nanf/is-infinitef once main.c is fixed.
Please reconcile these -- the deps should exactly match what the C code #includes. Also, benchmark and examples tasks should not include @stdlib/math/base/napi/unary (that's only needed for the build task). See floor2f/manifest.json for reference.
| v = trunc2f( Math.fround(x + Math.fround(x/3.0)) ); | ||
| t.strictEqual( v, expected, 'returns expected value' ); | ||
|
|
||
| expected = -SMALLEST_SUBNORMAL |
There was a problem hiding this comment.
Missing semicolon:
| expected = -SMALLEST_SUBNORMAL | |
| expected = -SMALLEST_SUBNORMAL; |
| t.end(); | ||
| }); | ||
|
|
||
| tape( 'the function returns the minimum double-precision floating-point value if provided the minimum double-precision floating-point value', function test( t ) { |
There was a problem hiding this comment.
This says "double-precision" but should be "single-precision" since this is a float32 function. Also, the reference package uses isnanf instead of isnan.
| tape( 'the function returns the minimum double-precision floating-point value if provided the minimum double-precision floating-point value', function test( t ) { | |
| tape( 'the function returns the minimum single-precision floating-point value if provided the minimum single-precision floating-point value', function test( t ) { |
| t.end(); | ||
| }); | ||
|
|
||
| tape( 'the function returns the minimum double-precision floating-point value if provided the minimum double-precision floating-point value', opts, function test( t ) { |
There was a problem hiding this comment.
Same as test.js -- "double-precision" should be "single-precision".
| tape( 'the function returns the minimum double-precision floating-point value if provided the minimum double-precision floating-point value', opts, function test( t ) { | |
| tape( 'the function returns the minimum single-precision floating-point value if provided the minimum single-precision floating-point value', opts, function test( t ) { |
| #include "stdlib/number/float32/base/exponent.h" | ||
| #include "stdlib/math/base/special/frexpf.h" |
There was a problem hiding this comment.
float32/base/exponent is included but never used. Remove this unused include.
| #include "stdlib/number/float32/base/exponent.h" | |
| #include "stdlib/math/base/special/frexpf.h" | |
| #include "stdlib/math/base/special/frexpf.h" |
Resolves #649.
Description
This pull request:
math/base/special/trunc2f, including tests and benchmarks.Related Issues
This pull request has the following related issues:
Questions
No.
Other
No.
Checklist
AI Assistance
If you answered "yes" above, how did you use AI assistance?
Disclosure
I used ChatGPT to better understand the stdlib codebase and for guidance on Git and Make workflows. All implementation changes were authored manually.
@stdlib-js/reviewers