Skip to content

Commit 3a11e54

Browse files
feat: add math/base/special/factoriallnf
PR-URL: #7817 Ref: #649 Reviewed-by: Philipp Burckhardt <[email protected]>
1 parent 0e9bfc8 commit 3a11e54

File tree

30 files changed

+2212
-0
lines changed

30 files changed

+2212
-0
lines changed
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2025 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# factoriallnf
22+
23+
> Natural logarithm of the [factorial][factorial-function] of a single-precision floating-point number.
24+
25+
<section class="intro">
26+
27+
The natural logarithm of the factorial function may be expressed
28+
29+
<!-- <equation class="equation" label="eq:factorialln_function" align="center" raw="f(n)=\ln (n!)" alt="Equation of the natural logarithm of the factorial."> -->
30+
31+
```math
32+
f(n)=\ln (n!)
33+
```
34+
35+
<!-- </equation> -->
36+
37+
The [factorial function][factorial-function] may be defined as the product
38+
39+
<!-- <equation class="equation" label="eq:factorial_function" align="center" raw="n! = \prod_{k=1}^n k" alt="Factorial function definition"> -->
40+
41+
```math
42+
n! = \prod_{k=1}^n k
43+
```
44+
45+
<!-- </equation> -->
46+
47+
or according to the recurrence relation
48+
49+
<!-- <equation class="equation" label="eq:factorial_recurrence_relation" align="center" raw="n! = \begin{cases}1 & \textrm{if } n = 0,\\(n-1)! \times n & \textrm{if } n > 1\end{cases}" alt="Factorial function recurrence relation"> -->
50+
51+
```math
52+
n! = \begin{cases}1 & \textrm{if } n = 0,\\(n-1)! \times n & \textrm{if } n > 1\end{cases}
53+
```
54+
55+
<!-- </equation> -->
56+
57+
Following the convention for an [empty product][empty-product], in all definitions,
58+
59+
<!-- <equation class="equation" label="eq:zero_factorial" align="center" raw="0! = 1" alt="Zero factorial"> -->
60+
61+
```math
62+
0! = 1
63+
```
64+
65+
<!-- </equation> -->
66+
67+
The [Gamma][gamma-function] function extends the [factorial function][factorial-function] for non-integer values.
68+
69+
<!-- <equation class="equation" label="eq:factorial_function_and_gamma" align="center" raw="n! = \Gamma(n+1)" alt="Factorial function extension via the Gamma function"> -->
70+
71+
```math
72+
n! = \Gamma(n+1)
73+
```
74+
75+
<!-- </equation> -->
76+
77+
The [factorial][factorial-function] of a **negative** integer is not defined.
78+
79+
Evaluating the natural logarithm of [factorial function][factorial-function] is useful as the [factorial function][factorial-function] can overflow for large `n`. Thus, `factoriallnf( n )` is generally preferred to `lnf( n! )`.
80+
81+
</section>
82+
83+
<!-- /.intro -->
84+
85+
<section class="usage">
86+
87+
## Usage
88+
89+
```javascript
90+
var factoriallnf = require( '@stdlib/math/base/special/factoriallnf' );
91+
```
92+
93+
#### factoriallnf( x )
94+
95+
Evaluates the natural logarithm of the [factorial][factorial-function] of a single-precision floating-point number. For input values other than negative integers, the function returns `ln( x! ) = ln( Γ(x+1) )`, where `Γ` is the [Gamma][gamma-function] function. For negative integers, the function returns `NaN`.
96+
97+
```javascript
98+
var v = factoriallnf( 3.0 );
99+
// returns ~1.792
100+
101+
v = factoriallnf( 2.4 );
102+
// returns ~1.092
103+
104+
v = factoriallnf( -1.0 );
105+
// returns NaN
106+
107+
v = factoriallnf( -1.5 );
108+
// returns ~1.266
109+
```
110+
111+
If provided `NaN`, the function returns `NaN`.
112+
113+
```javascript
114+
var v = factoriallnf( NaN );
115+
// returns NaN
116+
```
117+
118+
</section>
119+
120+
<!-- /.usage -->
121+
122+
<section class="examples">
123+
124+
## Examples
125+
126+
<!-- eslint no-undef: "error" -->
127+
128+
```javascript
129+
var uniform = require( '@stdlib/random/array/uniform' );
130+
var logEachMap = require( '@stdlib/console/log-each-map' );
131+
var factoriallnf = require( '@stdlib/math/base/special/factoriallnf' );
132+
133+
var opts = {
134+
'dtype': 'float32'
135+
};
136+
var x = uniform( 100, -10.0, 50.0, opts );
137+
138+
logEachMap( 'factoriallnf(%0.4f) = %0.4f', x, factoriallnf );
139+
```
140+
141+
</section>
142+
143+
<!-- /.examples -->
144+
145+
<!-- C interface documentation. -->
146+
147+
* * *
148+
149+
<section class="c">
150+
151+
## C APIs
152+
153+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
154+
155+
<section class="intro">
156+
157+
</section>
158+
159+
<!-- /.intro -->
160+
161+
<!-- C usage documentation. -->
162+
163+
<section class="usage">
164+
165+
### Usage
166+
167+
```c
168+
#include "stdlib/math/base/special/factoriallnf.h"
169+
```
170+
171+
#### stdlib_base_factoriallnf( x )
172+
173+
Evaluates the natural logarithm of the [factorial][factorial-function] of a single-precision floating-point number. For input values other than negative integers, the function returns `ln( x! ) = ln( Γ(x+1) )`, where `Γ` is the [Gamma][gamma-function] function. For negative integers, the function returns `NaN`.
174+
175+
```c
176+
float out = stdlib_base_factoriallnf( 3.0f );
177+
// returns ~1.792f
178+
179+
out = stdlib_base_factoriallnf( -1.5f );
180+
// returns ~1.266f
181+
```
182+
183+
The function accepts the following arguments:
184+
185+
- **x**: `[in] float` input value.
186+
187+
```c
188+
float stdlib_base_factoriallnf( const float x );
189+
```
190+
191+
</section>
192+
193+
<!-- /.usage -->
194+
195+
<!-- C API usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
196+
197+
<section class="notes">
198+
199+
</section>
200+
201+
<!-- /.notes -->
202+
203+
<!-- C API usage examples. -->
204+
205+
<section class="examples">
206+
207+
### Examples
208+
209+
```c
210+
#include "stdlib/math/base/special/factoriallnf.h"
211+
#include <stdio.h>
212+
213+
int main( void ) {
214+
const float x[] = { 2.0f, 3.0f, 5.0f, 8.0f };
215+
216+
float y;
217+
int i;
218+
for ( i = 0; i < 4; i++ ) {
219+
y = stdlib_base_factoriallnf( x[ i ] );
220+
printf( "factoriallnf(%f) = %f\n", x[ i ], y );
221+
}
222+
}
223+
```
224+
225+
</section>
226+
227+
<!-- /.examples -->
228+
229+
</section>
230+
231+
<!-- /.c -->
232+
233+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
234+
235+
<section class="related">
236+
237+
</section>
238+
239+
<!-- /.related -->
240+
241+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
242+
243+
<section class="links">
244+
245+
[gamma-function]: https://en.wikipedia.org/wiki/Gamma_Function
246+
247+
[factorial-function]: https://en.wikipedia.org/wiki/Factorial
248+
249+
[empty-product]: https://en.wikipedia.org/wiki/Empty_product
250+
251+
<!-- <related-links> -->
252+
253+
<!-- </related-links> -->
254+
255+
</section>
256+
257+
<!-- /.links -->
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var uniform = require( '@stdlib/random/array/uniform' );
25+
var floorf = require( '@stdlib/math/base/special/floorf' );
26+
var isnanf = require( '@stdlib/math/base/assert/is-nanf' );
27+
var pkg = require( './../package.json' ).name;
28+
var factoriallnf = require( './../lib' );
29+
30+
31+
// MAIN //
32+
33+
bench( pkg+'::integers', function benchmark( b ) {
34+
var x;
35+
var y;
36+
var i;
37+
38+
x = uniform( 100, 1.0, 35.0, {
39+
'dtype': 'float32'
40+
});
41+
42+
b.tic();
43+
for ( i = 0; i < b.iterations; i++ ) {
44+
y = factoriallnf( floorf( x[ i%x.length ] ) );
45+
if ( isnanf( y ) ) {
46+
b.fail( 'should not return NaN' );
47+
}
48+
}
49+
b.toc();
50+
if ( isnanf( y ) ) {
51+
b.fail( 'should not return NaN' );
52+
}
53+
b.pass( 'benchmark finished' );
54+
b.end();
55+
});
56+
57+
bench( pkg+'::decimals', function benchmark( b ) {
58+
var x;
59+
var y;
60+
var i;
61+
62+
x = uniform( 100, 1.0, 35.0, {
63+
'dtype': 'float32'
64+
});
65+
66+
b.tic();
67+
for ( i = 0; i < b.iterations; i++ ) {
68+
y = factoriallnf( x[ i%x.length ] );
69+
if ( isnanf( y ) ) {
70+
b.fail( 'should not return NaN' );
71+
}
72+
}
73+
b.toc();
74+
if ( isnanf( y ) ) {
75+
b.fail( 'should not return NaN' );
76+
}
77+
b.pass( 'benchmark finished' );
78+
b.end();
79+
});

0 commit comments

Comments
 (0)