Skip to content

Commit 248ba46

Browse files
gunjjoshikgryte
andauthored
refactor!: modify C implementation to accept double values instead of int64 in math/base/special/binomcoef
This commit updates the signature of the C API to accept a double rather than int32. The rationale was so that users get the same results/behavior in both JavaScript and C. This arose in the context of ufuncs, where the diverging type signatures meant differences in what dtypes would be permissible. Instead, we decided to unify and ensure the behavior is consistent. BREAKING CHANGE: update signature to accept doubles User code should behave similarly in the primary case of providing integer-valued input values. However, no longer will real-values truncate. Now, real-valued inputs will result in `NaN`, which is, arguably, better behavior, as real-to-integer truncation can be a source of silent bugs. PR-URL: #7945 Co-authored-by: Athan Reines <[email protected]> Reviewed-by: Athan Reines <[email protected]>
1 parent 72d37f3 commit 248ba46

File tree

7 files changed

+40
-35
lines changed

7 files changed

+40
-35
lines changed

lib/node_modules/@stdlib/math/base/special/binomcoef/README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,17 @@ logEachMap( '%d choose %d = %d', n, k, binomcoef );
172172
Evaluates the [binomial coefficient][binomial-coefficient] of two integers `n` and `k`.
173173

174174
```c
175-
double v = stdlib_base_binomcoef( 8, 2 );
175+
double v = stdlib_base_binomcoef( 8.0, 2.0 );
176176
// returns 28.0
177177
```
178178

179179
The function accepts the following arguments:
180180

181-
- **n**: `[in] int64_t` input value.
182-
- **k**: `[in] int64_t` input value.
181+
- **n**: `[in] double` input value.
182+
- **k**: `[in] double` input value.
183183

184184
```c
185-
double stdlib_base_binomcoef( const int64_t n, const int64_t k );
185+
double stdlib_base_binomcoef( const double n, const double k );
186186
```
187187
188188
</section>
@@ -206,18 +206,16 @@ double stdlib_base_binomcoef( const int64_t n, const int64_t k );
206206
```c
207207
#include "stdlib/math/base/special/binomcoef.h"
208208
#include <stdio.h>
209-
#include <stdint.h>
210-
#include <inttypes.h>
211209
212210
int main( void ) {
213-
const int64_t a[] = { 24, 32, 48, 116, 33 };
214-
const int64_t b[] = { 12, 6, 15, 52, 22 };
211+
const double a[] = { 24.0, 32.0, 48.0, 116.0, 33.0 };
212+
const double b[] = { 12.0, 6.0, 15.0, 52.0, 22.0 };
215213
216214
double out;
217215
int i;
218216
for ( i = 0; i < 5; i++ ) {
219217
out = stdlib_base_binomcoef( a[ i ], b[ i ] );
220-
printf( "binomcoef(%" PRId64 ", %" PRId64 ") = %lf\n", a[ i ], b[ i ], out );
218+
printf( "binomcoef(%lf, %lf) = %lf\n", a[ i ], b[ i ], out );
221219
}
222220
}
223221
```

lib/node_modules/@stdlib/math/base/special/binomcoef/benchmark/c/native/benchmark.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,16 @@ static double rand_double( void ) {
9090
* @return elapsed time in seconds
9191
*/
9292
static double benchmark( void ) {
93-
int64_t n[ 100 ];
94-
int64_t k[ 100 ];
93+
double n[ 100 ];
94+
double k[ 100 ];
9595
double elapsed;
9696
double y;
9797
double t;
9898
int i;
9999

100100
for ( i = 0; i < 100; i++ ) {
101-
n[ i ] = (int64_t)round( 500.0 * rand_double() );
102-
k[ i ] = (int64_t)round( 500.0 * rand_double() );
101+
n[ i ] = round( 500.0 * rand_double() );
102+
k[ i ] = round( 500.0 * rand_double() );
103103
}
104104

105105
t = tic();

lib/node_modules/@stdlib/math/base/special/binomcoef/examples/c/example.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,15 @@
1818

1919
#include "stdlib/math/base/special/binomcoef.h"
2020
#include <stdio.h>
21-
#include <stdint.h>
22-
#include <inttypes.h>
2321

2422
int main( void ) {
25-
const int64_t a[] = { 24, 32, 48, 116, 33 };
26-
const int64_t b[] = { 12, 6, 15, 52, 22 };
23+
const double a[] = { 24.0, 32.0, 48.0, 116.0, 33.0 };
24+
const double b[] = { 12.0, 6.0, 15.0, 52.0, 22.0 };
2725

2826
double out;
2927
int i;
3028
for ( i = 0; i < 5; i++ ) {
3129
out = stdlib_base_binomcoef( a[ i ], b[ i ] );
32-
printf( "binomcoef(%" PRId64 ", %" PRId64 ") = %lf\n", a[ i ], b[ i ], out );
30+
printf( "binomcoef(%lf, %lf) = %lf\n", a[ i ], b[ i ], out );
3331
}
3432
}

lib/node_modules/@stdlib/math/base/special/binomcoef/include/stdlib/math/base/special/binomcoef.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
#ifndef STDLIB_MATH_BASE_SPECIAL_BINOMCOEF_H
2020
#define STDLIB_MATH_BASE_SPECIAL_BINOMCOEF_H
2121

22-
#include <stdint.h>
23-
2422
/*
2523
* If C++, prevent name mangling so that the compiler emits a binary file having undecorated names, thus mirroring the behavior of a C compiler.
2624
*/
@@ -31,7 +29,7 @@ extern "C" {
3129
/**
3230
* Computes the binomial coefficient of two integers.
3331
*/
34-
double stdlib_base_binomcoef( const int64_t n, const int64_t k );
32+
double stdlib_base_binomcoef( const double n, const double k );
3533

3634
#ifdef __cplusplus
3735
}

lib/node_modules/@stdlib/math/base/special/binomcoef/manifest.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@
4242
"@stdlib/math/base/special/floor",
4343
"@stdlib/math/base/special/gcd",
4444
"@stdlib/constants/float64/pinf",
45-
"@stdlib/constants/float64/max-safe-integer"
45+
"@stdlib/constants/float64/max-safe-integer",
46+
"@stdlib/math/base/assert/is-integer",
47+
"@stdlib/math/base/assert/is-odd"
4648
]
4749
},
4850
{
@@ -61,7 +63,9 @@
6163
"@stdlib/math/base/special/floor",
6264
"@stdlib/math/base/special/gcd",
6365
"@stdlib/constants/float64/pinf",
64-
"@stdlib/constants/float64/max-safe-integer"
66+
"@stdlib/constants/float64/max-safe-integer",
67+
"@stdlib/math/base/assert/is-integer",
68+
"@stdlib/math/base/assert/is-odd"
6569
]
6670
},
6771
{
@@ -80,7 +84,9 @@
8084
"@stdlib/math/base/special/floor",
8185
"@stdlib/math/base/special/gcd",
8286
"@stdlib/constants/float64/pinf",
83-
"@stdlib/constants/float64/max-safe-integer"
87+
"@stdlib/constants/float64/max-safe-integer",
88+
"@stdlib/math/base/assert/is-integer",
89+
"@stdlib/math/base/assert/is-odd"
8490
]
8591
}
8692
]

lib/node_modules/@stdlib/math/base/special/binomcoef/src/addon.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919
#include "stdlib/math/base/special/binomcoef.h"
2020
#include "stdlib/math/base/napi/binary.h"
2121

22-
STDLIB_MATH_BASE_NAPI_MODULE_LL_D( stdlib_base_binomcoef )
22+
STDLIB_MATH_BASE_NAPI_MODULE_DD_D( stdlib_base_binomcoef )

lib/node_modules/@stdlib/math/base/special/binomcoef/src/main.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717
*/
1818

1919
#include "stdlib/math/base/special/binomcoef.h"
20+
#include "stdlib/math/base/assert/is_integer.h"
21+
#include "stdlib/math/base/assert/is_odd.h"
2022
#include "stdlib/math/base/special/floor.h"
2123
#include "stdlib/math/base/special/gcd.h"
2224
#include "stdlib/constants/float64/pinf.h"
2325
#include "stdlib/constants/float64/max_safe_integer.h"
24-
#include <stdint.h>
2526

2627
/**
2728
* Computes the binomial coefficient of two integers.
@@ -31,28 +32,32 @@
3132
* @return function value
3233
*
3334
* @example
34-
* double out = stdlib_base_binomcoef( 8, 2 );
35+
* double out = stdlib_base_binomcoef( 8.0, 2.0 );
3536
* // returns 28.0
3637
*/
37-
double stdlib_base_binomcoef( const int64_t n, const int64_t k ) {
38+
double stdlib_base_binomcoef( const double n, const double k ) {
3839
double res;
3940
double sgn;
40-
int64_t nc;
41-
int64_t kc;
42-
int64_t d;
41+
double nc;
42+
double kc;
43+
double d;
4344
double b;
4445
double c;
4546
double g;
4647
double s;
4748

49+
if ( !stdlib_base_is_integer( n ) || !stdlib_base_is_integer( k ) ) {
50+
return 0.0 / 0.0; // NaN
51+
}
52+
4853
if ( k < 0 ) {
4954
return 0.0;
5055
}
5156
sgn = 1.0;
5257
nc = n;
5358
if ( nc < 0 ) {
5459
nc = -nc + k - 1;
55-
if ( k & 1 ) {
60+
if ( stdlib_base_is_odd( k ) ) {
5661
sgn *= -1.0;
5762
}
5863
}
@@ -63,19 +68,19 @@ double stdlib_base_binomcoef( const int64_t n, const int64_t k ) {
6368
return sgn;
6469
}
6570
if ( k == 1 || k == nc - 1 ) {
66-
return sgn * (double)nc;
71+
return sgn * nc;
6772
}
6873

6974
// Minimize the number of computed terms by leveraging symmetry:
7075
kc = k;
7176
if ( nc - kc < kc ) {
7277
kc = nc - kc;
7378
}
74-
s = stdlib_base_floor( (double)STDLIB_CONSTANT_FLOAT64_MAX_SAFE_INTEGER / (double)nc );
79+
s = stdlib_base_floor( (double)STDLIB_CONSTANT_FLOAT64_MAX_SAFE_INTEGER / nc );
7580

7681
// Use a standard algorithm for computing the binomial coefficient
7782
res = 1.0;
78-
for ( d = 1; d <= kc; d++ ) {
83+
for ( d = 1.0; d <= kc; d++ ) {
7984
// Check for potential overflow...
8085
if ( res > s ) {
8186
break;

0 commit comments

Comments
 (0)