Skip to content

Commit e56da52

Browse files
committed
Add tool to evaluate a Lucas polynomial
1 parent bc5ba08 commit e56da52

File tree

14 files changed

+752
-0
lines changed

14 files changed

+752
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Lucas Polynomial
2+
3+
> Evaluate a [Lucas polynomial][fibonacci-polynomials].
4+
5+
6+
<section class="intro">
7+
8+
A [Lucas polynomial][fibonacci-polynomials] is expressed according to the following recurrence relation
9+
10+
<!-- <equation class="equation" label="eq:lucas_polynomial" align="center" raw="L_n(x) = \begin{cases}2 & \textrm{if}\ n = 0\\x & \textrm{if}\ n = 1\\x \cdot L_{n-1}(x) + L_{n-2}(x) & \textrm{if}\ n \geq 2\end{cases}" alt="Lucas polynomial."> -->
11+
12+
<div class="equation" align="center" data-raw-text="L_n(x) = \begin{cases}2 &amp; \textrm{if}\ n = 0\\x &amp; \textrm{if}\ n = 1\\x \cdot L_{n-1}(x) + L_{n-2}(x) &amp; \textrm{if}\ n \geq 2\end{cases}" data-equation="eq:lucas_polynomial">
13+
<img src="" alt="Lucas polynomial.">
14+
<br>
15+
</div>
16+
17+
<!-- </equation> -->
18+
19+
Alternatively, if `L(n,k)` is the coefficient of `x^k` in `L_n(x)`, then
20+
21+
<!-- <equation class="equation" label="eq:lucas_polynomial_sum" align="center" raw="L_n(x) = \sum_{k = 0}^n L(n,k) x^k" alt="Lucas polynomial expressed as a sum."> -->
22+
23+
<div class="equation" align="center" data-raw-text="L_n(x) = \sum_{k = 0}^n L(n,k) x^k" data-equation="eq:lucas_polynomial_sum">
24+
<img src="" alt="Lucas polynomial expressed as a sum.">
25+
<br>
26+
</div>
27+
28+
<!-- </equation> -->
29+
30+
We can extend [Lucas polynomials][fibonacci-polynomials] to negative `n` using the identity
31+
32+
<!-- <equation class="equation" label="eq:negalucas_polynomial" align="center" raw="L_{-n}(x) = (-1)^{n} L_n(x)" alt="NegaLucas polynomial."> -->
33+
34+
<div class="equation" align="center" data-raw-text="L_{-n}(x) = (-1)^{n} L_n(x)" data-equation="eq:negalucas_polynomial">
35+
<img src="" alt="NegaLucas polynomial.">
36+
<br>
37+
</div>
38+
39+
<!-- </equation> -->
40+
41+
</section>
42+
43+
<!-- /.intro -->
44+
45+
46+
<section class="usage">
47+
48+
## Usage
49+
50+
``` javascript
51+
var lucaspoly = require( '@stdlib/math/base/tools/lucaspoly' );
52+
```
53+
54+
#### lucaspoly( n, x )
55+
56+
Evaluates a [Lucas polynomial][fibonacci-polynomials] at a value `x`.
57+
58+
``` javascript
59+
var v = lucaspoly( 5, 2.0 ); // => 2^5 + 5*2^3 + 5*2
60+
// returns 82.0
61+
```
62+
63+
#### lucaspoly.factory( n )
64+
65+
Returns a `function` for evaluating a [Lucas polynomial][fibonacci-polynomials].
66+
67+
``` javascript
68+
var polyval = lucaspoly.factory( 5 );
69+
70+
var v = polyval( 1.0 ); // => 1^5 + 5*1^3 + 5
71+
// returns 11.0
72+
73+
v = polyval( 2.0 ); // => 2^5 + 5*2^3 + 5*2
74+
// returns 82.0
75+
```
76+
77+
</section>
78+
79+
<!-- /.usage -->
80+
81+
82+
<section class="notes">
83+
84+
</section>
85+
86+
<!-- /.notes -->
87+
88+
89+
<section class="examples">
90+
91+
## Examples
92+
93+
``` javascript
94+
var lucaspoly = require( '@stdlib/math/base/tools/lucaspoly' );
95+
96+
var i;
97+
98+
// Compute the negaLucas and Lucas numbers...
99+
for ( i = -76; i < 77; i++ ) {
100+
console.log( 'L_%d = %d', i, lucaspoly( i, 1.0 ) );
101+
}
102+
```
103+
104+
</section>
105+
106+
<!-- /.examples -->
107+
108+
109+
<section class="links">
110+
111+
[fibonacci-polynomials]: https://en.wikipedia.org/wiki/Fibonacci_polynomials
112+
113+
</section>
114+
115+
<!-- /.links -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
'use strict';
2+
3+
// MODULES //
4+
5+
var bench = require( '@stdlib/bench' );
6+
var randu = require( '@stdlib/math/base/random/randu' );
7+
var round = require( '@stdlib/math/base/special/round' );
8+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
9+
var pkg = require( './../package.json' ).name;
10+
var factory = require( './../lib/factory.js' );
11+
12+
13+
// MAIN //
14+
15+
bench( pkg+'::create:factory', function benchmark( b ) {
16+
var n;
17+
var f;
18+
var i;
19+
20+
b.tic();
21+
for ( i = 0; i < b.iterations; i++ ) {
22+
n = round( randu()*172.0 ) - 76;
23+
f = factory( n );
24+
if ( typeof f !== 'function' ) {
25+
b.fail( 'should return a function' );
26+
}
27+
}
28+
b.toc();
29+
if ( typeof f !== 'function' ) {
30+
b.fail( 'should return a function' );
31+
}
32+
b.pass( 'benchmark finished' );
33+
b.end();
34+
});
35+
36+
bench( pkg+'::evaluate:factory', function benchmark( b ) {
37+
var x;
38+
var v;
39+
var f;
40+
var i;
41+
42+
f = factory( 76.0 );
43+
44+
b.tic();
45+
for ( i = 0; i < b.iterations; i++ ) {
46+
x = randu() * 100.0;
47+
v = f( x );
48+
if ( isnan( v ) ) {
49+
b.fail( 'should not return NaN' );
50+
}
51+
}
52+
b.toc();
53+
if ( isnan( v ) ) {
54+
b.fail( 'should not return NaN' );
55+
}
56+
b.pass( 'benchmark finished' );
57+
b.end();
58+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
3+
// MODULES //
4+
5+
var bench = require( '@stdlib/bench' );
6+
var randu = require( '@stdlib/math/base/random/randu' );
7+
var round = require( '@stdlib/math/base/special/round' );
8+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
9+
var pkg = require( './../package.json' ).name;
10+
var lucaspoly = require( './../lib' );
11+
12+
13+
// MAIN //
14+
15+
bench( pkg, function benchmark( b ) {
16+
var n;
17+
var x;
18+
var v;
19+
var i;
20+
21+
b.tic();
22+
for ( i = 0; i < b.iterations; i++ ) {
23+
n = round( randu()*172.0 ) - 76;
24+
x = randu() * 100.0;
25+
v = lucaspoly( n, x );
26+
if ( isnan( v ) ) {
27+
b.fail( 'should not return NaN' );
28+
}
29+
}
30+
b.toc();
31+
if ( isnan( v ) ) {
32+
b.fail( 'should not return NaN' );
33+
}
34+
b.pass( 'benchmark finished' );
35+
b.end();
36+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
2+
{{alias}}( n, x )
3+
Evaluates a Lucas polynomial.
4+
5+
Parameters
6+
----------
7+
n: integer
8+
Lucas polynomial to evaluate.
9+
10+
x: number
11+
Value at which to evaluate the Lucas polynomial.
12+
13+
Returns
14+
-------
15+
out: number
16+
Evaluated Lucas polynomial.
17+
18+
Examples
19+
--------
20+
// 2^5 + 5*2^3 + 5*2
21+
> var v = {{alias}}( 5, 2.0 )
22+
82.0
23+
24+
25+
{{alias}}.factory( n )
26+
Returns a function for evaluating a Lucas polynomial.
27+
28+
Parameters
29+
----------
30+
n: integer
31+
Lucas polynomial to evaluate.
32+
33+
Returns
34+
-------
35+
fcn: Function
36+
Function for evaluating a Lucas polynomial.
37+
38+
Examples
39+
--------
40+
> var polyval = {{alias}}.factory( 5 );
41+
42+
// 1^5 + 5*1^2 + 5
43+
> var v = polyval( 1.0 )
44+
11.0
45+
46+
// 2^5 + 5*2^3 + 5*2
47+
> v = polyval( 2.0 )
48+
82.0
49+
50+
See Also
51+
--------
52+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
var lucaspoly = require( './../lib' );
4+
5+
var i;
6+
7+
// Compute the negaLucas and Lucas numbers...
8+
for ( i = -76; i < 77; i++ ) {
9+
console.log( 'L_%d = %d', i, lucaspoly( i, 1.0 ) );
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
// EXPORTS //
4+
5+
module.exports = {};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use strict';
2+
3+
// MODULES //
4+
5+
var binomcoef = require( '@stdlib/math/base/special/binomcoef' );
6+
var floor = require( '@stdlib/math/base/special/floor' );
7+
var ceil = require( '@stdlib/math/base/special/ceil' );
8+
var cache = require( './cache.js' );
9+
10+
11+
// MAIN //
12+
13+
/**
14+
* Computes polynomial coefficients.
15+
*
16+
* ## Notes
17+
*
18+
* * Coefficients are computed via a (1,2)-Pascal triangle (i.e., Lucas triangle). For more details, see [Lucas polynomials]{@link https://oeis.org/wiki/Lucas_polynomials} and [Lucas triangle]{@link https://oeis.org/wiki/Lucas_triangle}.
19+
*
20+
*
21+
* @private
22+
* @param {NonNegativeInteger} n - Lucas polynomial for which to compute coefficients
23+
* @returns {NonNegativeIntegerArray} polynomial coefficients
24+
*/
25+
function coefficients( n ) {
26+
var coefs;
27+
var half;
28+
var high;
29+
var low;
30+
var p;
31+
var a;
32+
var b;
33+
var m;
34+
var i;
35+
36+
coefs = cache[ n ];
37+
if ( coefs === void 0 ) {
38+
m = n + 1;
39+
coefs = new Array( m );
40+
if ( n === 0 ) {
41+
coefs[ 0 ] = 2.0;
42+
} else {
43+
for ( i = 0; i < m; i++ ) {
44+
coefs[ i ] = 0.0;
45+
}
46+
half = n / 2;
47+
high = ceil( half );
48+
low = floor( half );
49+
for ( i = 0; i <= low; i++ ) {
50+
p = (2*i) + (n%2);
51+
a = 2.0 * binomcoef( high+i-1, low-i-1 );
52+
b = binomcoef( high+i-1, low-i );
53+
coefs[ p ] += a + b;
54+
}
55+
}
56+
// Memoize the coefficients:
57+
cache[ n ] = coefs;
58+
}
59+
return coefs;
60+
} // end FUNCTION coefficients()
61+
62+
63+
// EXPORTS //
64+
65+
module.exports = coefficients;

0 commit comments

Comments
 (0)