Add modulus parameter to toPower

This commit is contained in:
Michael Mclaughlin 2016-03-07 23:10:15 +00:00
parent 2182c5948e
commit 99067bdbf8
6 changed files with 1203 additions and 36 deletions

View File

@ -46,7 +46,7 @@ var BigNumber = require('bignumber.js');
To load with AMD loader libraries such as [requireJS](http://requirejs.org/):
```javascript
require(['path/to/bignumber'], function(BigNumber) {
require(['path/to/bignumber'], function(BigNumber) {
// Use BigNumber here in local scope. No global BigNumber.
});
```
@ -76,10 +76,10 @@ y = new BigNumber('zz.9', 36) // "1295.25"
z = x.plus(y) // "1306.25"
```
A BigNumber is immutable in the sense that it is not changed by its methods.
A BigNumber is immutable in the sense that it is not changed by its methods.
```javascript
0.3 - 0.1 // 0.19999999999999998
0.3 - 0.1 // 0.19999999999999998
x = new BigNumber(0.3)
x.minus(0.1) // "0.2"
x // "0.3"
@ -202,9 +202,9 @@ To test a single method, e.g.
$ node test/toFraction
For the browser, see *every-test.html* and *single-test.html* in the *test/browser* directory.
For the browser, see *every-test.html* and *single-test.html* in the *test/browser* directory.
*bignumber-vs-number.html* enables some of the methods of bignumber.js to be compared with those of JavaScript's number type.
*bignumber-vs-number.html* enables some of the methods of bignumber.js to be compared with those of JavaScript's number type.
## Versions
@ -230,7 +230,7 @@ A source map will also be created in the root directory.
## Feedback
Open an issue, or email
Open an issue, or email
Michael
@ -244,6 +244,10 @@ See [LICENCE](https://github.com/MikeMcl/bignumber.js/blob/master/LICENCE).
## Change Log
####2.3.0
* 07/03/2016
* #86 Add modulus parameter to `toPower`.
####2.2.0
* 03/03/2016
* #91 Permit larger JS integers.
@ -344,7 +348,7 @@ See [LICENCE](https://github.com/MikeMcl/bignumber.js/blob/master/LICENCE).
####1.1.0
* 1/8/2013
* Allow numbers with trailing radix point.
* Allow numbers with trailing radix point.
####1.0.1
* Bugfix: error messages with incorrect method name

View File

@ -7,7 +7,7 @@
bignumber.js v2.2.0
A JavaScript library for arbitrary-precision arithmetic.
https://github.com/MikeMcl/bignumber.js
Copyright (c) 2015 Michael Mclaughlin <M8ch88l@gmail.com>
Copyright (c) 2016 Michael Mclaughlin <M8ch88l@gmail.com>
MIT Expat Licence
*/
@ -2363,50 +2363,85 @@
/*
* Return a BigNumber whose value is the value of this BigNumber raised to the power n.
* If m is present, return the result modulo m.
* If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE.
* If POW_PRECISION is not 0, round to POW_PRECISION using ROUNDING_MODE.
* If POW_PRECISION is non-zero and m is not present, round to POW_PRECISION using
* ROUNDING_MODE.
*
* n {number} Integer, -9007199254740992 to 9007199254740992 inclusive.
* (Performs 54 loop iterations for n of 9007199254740992.)
* The modular power operation works efficiently when x, n, and m are positive integers,
* otherwise it is equivalent to calculating x.toPower(n).modulo(m) (with POW_PRECISION 0).
*
* n {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive.
* [m] {number|string|BigNumber} The modulus.
*
* 'pow() exponent not an integer: {n}'
* 'pow() exponent out of range: {n}'
*
* Performs 54 loop iterations for n of 9007199254740991.
*/
P.toPower = P.pow = function (n) {
var k, y,
P.toPower = P.pow = function ( n, m ) {
var k, y, z,
i = mathfloor( n < 0 ? -n : +n ),
x = this;
if ( m != null ) {
id = 23;
m = new BigNumber(m);
}
// Pass ±Infinity to Math.pow if exponent is out of range.
if ( !isValidInt( n, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER, 23, 'exponent' ) &&
( !isFinite(n) || i > MAX_SAFE_INTEGER && ( n /= 0 ) ||
parseFloat(n) != n && !( n = NaN ) ) ) {
return new BigNumber( Math.pow( +x, n ) );
parseFloat(n) != n && !( n = NaN ) ) || n == 0 ) {
k = Math.pow( +x, n );
return new BigNumber( m ? k % m : k );
}
if (m) {
if ( n > 1 && x.gt(ONE) && x.isInt() && m.gt(ONE) && m.isInt() ) {
x = x.mod(m);
} else {
z = m;
// Nullify m so only a single mod operation is performed at the end.
m = null;
}
} else if (POW_PRECISION) {
// Truncating each coefficient array to a length of k after each multiplication
// equates to truncating significant digits to POW_PRECISION + [28, 41],
// i.e. there will be a minimum of 28 guard digits retained.
// (Using + 1.5 would give [9, 21] guard digits.)
k = mathceil( POW_PRECISION / LOG_BASE + 2 );
}
// Truncating each coefficient array to a length of k after each multiplication equates
// to truncating significant digits to POW_PRECISION + [28, 41], i.e. there will be a
// minimum of 28 guard digits retained. (Using + 1.5 would give [9, 21] guard digits.)
k = POW_PRECISION ? mathceil( POW_PRECISION / LOG_BASE + 2 ) : 0;
y = new BigNumber(ONE);
for ( ; ; ) {
if ( i % 2 ) {
y = y.times(x);
if ( !y.c ) break;
if ( k && y.c.length > k ) y.c.length = k;
if (k) {
if ( y.c.length > k ) y.c.length = k;
} else if (m) {
y = y.mod(m);
}
}
i = mathfloor( i / 2 );
if ( !i ) break;
x = x.times(x);
if ( k && x.c && x.c.length > k ) x.c.length = k;
if (k) {
if ( x.c && x.c.length > k ) x.c.length = k;
} else if (m) {
x = x.mod(m);
}
}
if (m) return y;
if ( n < 0 ) y = ONE.div(y);
return k ? round( y, POW_PRECISION, ROUNDING_MODE ) : y;
return z ? y.mod(z) : k ? round( y, POW_PRECISION, ROUNDING_MODE ) : y;
};

File diff suppressed because one or more lines are too long

2
bignumber.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -590,7 +590,8 @@ BigNumber.config({ MODULO_MODE: 9 }) // equivalent</pre>
Default value: <code>100</code>
</dd>
<dd>
The <i>maximum</i> number of significant digits of the result of the power operation.
The <i>maximum</i> number of significant digits of the result of the power operation
(unless a modulus is specified).
</dd>
<dd>If set to <code>0</code>, the number of signifcant digits will not be limited.</dd>
<dd>See <a href='#pow'><code>toPower</code></a>.</dd>
@ -1601,14 +1602,15 @@ z = new BigNumber(-0)
<h5 id="pow">toPower<code class='inset'>.pow(n) <i>&rArr; BigNumber</i></code></h5>
<h5 id="pow">toPower<code class='inset'>.pow(n [, m]) <i>&rArr; BigNumber</i></code></h5>
<p>
<code>n</code>: <i>number</i>: integer,
<code>-9007199254740991</code> to <code>9007199254740991</code> inclusive
<code>-9007199254740991</code> to <code>9007199254740991</code> inclusive<br />
<code>m</code>: <i>number|string|BigNumber</i>
</p>
<p>
Returns a BigNumber whose value is the value of this BigNumber raised to the power
<code>n</code>.
<code>n</code>, and optionally modulo a modulus <code>m</code>.
</p>
<p>
If <code>n</code> is negative the result is rounded according to the current
@ -1632,7 +1634,7 @@ z = new BigNumber(-0)
e.g. 123.456<sup>10000</sup> has over <code>50000</code> digits, the number of significant
digits calculated is limited to the value of the
<a href='#pow-precision'><code>POW_PRECISION</code></a> setting (default value:
<code>100</code>).
<code>100</code>) unless a modulus <code>m</code> is specified.
</p>
<p>
Set <a href='#pow-precision'><code>POW_PRECISION</code></a> to <code>0</code> for an
@ -1644,6 +1646,13 @@ z = new BigNumber(-0)
<a href='#decimal-places'><code>DECIMAL_PLACES</code></a> (but not to more than
<a href='#pow-precision'><code>POW_PRECISION</code></a> significant digits).
</p>
<p>
If <code>m</code> is specified and the value of <code>m</code>, <code>n</code> and this
BigNumber are positive integers, then a fast modular exponentiation algorithm is used,
otherwise if any of the values is not a positive integer the operation will simply be
performed as <code>x.toPower(n).modulo(m)</code> with a
<a href='#pow-precision'><code>POW_PRECISION</code></a> of <code>0</code>.
</p>
<pre>
Math.pow(0.7, 2) // 0.48999999999999994
x = new BigNumber(0.7)

File diff suppressed because it is too large Load Diff