@@ -1730,12 +1730,12 @@ function is_prime( n )
1730
1730
//n = Arithmetic.abs(/*N(*/n/*)*/);
1731
1731
ndigits = Arithmetic.digits(n).length;
1732
1732
// try to use fastest algorithm based on size of number (number of digits)
1733
- if ( ndigits <= 8 )
1733
+ if ( ndigits <= 6 )
1734
1734
{
1735
1735
// deterministic test
1736
1736
return wheel_trial_div_test(n);
1737
1737
}
1738
- else if ( ndigits <= 1000 )
1738
+ else if ( ndigits <= 20 )
1739
1739
{
1740
1740
// deterministic test
1741
1741
/*
@@ -1746,11 +1746,11 @@ function is_prime( n )
1746
1746
If n < 3474749660383 is a 2, 3, 5, 7, 11 and 13-SPRP, then n is prime [Jaeschke93].
1747
1747
If n < 341550071728321 is a 2, 3, 5, 7, 11, 13 and 17-SPRP, then n is prime [Jaeschke93].
1748
1748
*/
1749
- /* if ( Arithmetic.lt(n, N(1373653)) )
1749
+ if ( Arithmetic.lt(n, N(1373653)) )
1750
1750
return miller_rabin_test(n, [two, N(3)]);
1751
1751
else if ( Arithmetic.lt(n, N("25326001")) )
1752
1752
return miller_rabin_test(n, [two, N(3), N(5)]);
1753
- else*/ if ( Arithmetic.lt(n, N("25000000000")) )
1753
+ else if ( Arithmetic.lt(n, N("25000000000")) )
1754
1754
return Arithmetic.equ(n, N("3215031751")) ? false : miller_rabin_test(n, [two, N(3), N(5), N(7)]);
1755
1755
else if ( Arithmetic.lt(n, N("2152302898747")) )
1756
1756
return miller_rabin_test(n, [two, N(3), N(5), N(7), N(11)]);
@@ -2704,14 +2704,13 @@ function polyxgcd( /* args */ )
2704
2704
}
2705
2705
function divisors( n, as_generator )
2706
2706
{
2707
- // time+space O(sqrt(n)) to find all distinct divisors of n (including 1 and n itself)
2708
2707
var Arithmetic = Abacus.Arithmetic, O = Arithmetic.O, I = Arithmetic.I,
2709
2708
list = null, D2 = null, D1 = null, L1 = 0, L2 = 0, node, sqrn, i, n_i, next, factors;
2710
2709
//n = Arithmetic.num(n);
2711
2710
n = Arithmetic.abs(n);
2712
2711
if ( true===as_generator )
2713
2712
{
2714
- if ( Arithmetic.gte(n, 1000000 ) )
2713
+ if ( Arithmetic.gte(n, 100000 ) )
2715
2714
{
2716
2715
// for very large numbers,
2717
2716
// compute divisors through prime factorisation
@@ -2727,6 +2726,7 @@ function divisors( n, as_generator )
2727
2726
}
2728
2727
else
2729
2728
{
2729
+ // time+space O(sqrt(n)) to find all distinct divisors of n (including 1 and n itself)
2730
2730
sqrn = isqrt(n);
2731
2731
i = I; next = null;
2732
2732
// return iterator/generator
@@ -2766,6 +2766,7 @@ function divisors( n, as_generator )
2766
2766
}
2767
2767
else
2768
2768
{
2769
+ // time+space O(sqrt(n)) to find all distinct divisors of n (including 1 and n itself)
2769
2770
sqrn = isqrt(n);
2770
2771
for (i=I; Arithmetic.lte(i,sqrn); i=Arithmetic.add(i,I))
2771
2772
{
@@ -3549,8 +3550,8 @@ function factorial( n, m )
3549
3550
// simple factorial = F(n) = n F(n-1) = n!
3550
3551
if ( 12 >= n ) return 0 > n ? O : NUM(([1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600 /*MAX: 2147483647*/])[n]);
3551
3552
3552
- // for very large factorials, use the prime factorisation of n!
3553
- if ( 500 <= n ) return prime_factorial(Nn);
3553
+ // for large factorials, use the prime factorisation of n!
3554
+ if ( 600 <= n ) return prime_factorial(Nn);
3554
3555
3555
3556
key = String(n)/*+'!'*/;
3556
3557
if ( null == factorial.mem1[key] )
@@ -7101,11 +7102,11 @@ Polynomial = Abacus.Polynomial = Class(INumber, {
7101
7102
,primitive: function( and_content ) {
7102
7103
// factorise into content and primitive part
7103
7104
// https://en.wikipedia.org/wiki/Factorization_of_polynomials#Primitive_part%E2%80%93content_factorization
7104
- var self = this, Arithmetic = Abacus.Arithmetic, coeff = self.coeff, coeffp, M , content;
7105
+ var self = this, Arithmetic = Abacus.Arithmetic, coeff = self.coeff, coeffp, LCM , content;
7105
7106
if ( null == self._prim )
7106
7107
{
7107
- M = coeff.reduce (function(M, c){return Arithmetic.mul(M, c.den);}, Arithmetic.I );
7108
- coeffp = coeff.map(function(c){return c.mul(M).num ;});
7108
+ LCM = lcm( coeff.map (function(c){return c.den;}) );
7109
+ coeffp = coeff.map(function(c){return c.mul(LCM).integer() ;});
7109
7110
content = gcd(coeffp);
7110
7111
coeffp = coeffp.map(function(c){return Arithmetic.div(c, content);});
7111
7112
// make positive lead
@@ -7114,7 +7115,7 @@ Polynomial = Abacus.Polynomial = Class(INumber, {
7114
7115
coeffp = coeffp.map(function(c){return Arithmetic.neg(c);});
7115
7116
content = Arithmetic.neg(content);
7116
7117
}
7117
- self._prim = [Polynomial(coeffp, self.symbol), Rational(content, M )];
7118
+ self._prim = [Polynomial(coeffp, self.symbol), Rational(content, LCM )];
7118
7119
}
7119
7120
return true===and_content ? self._prim.slice() : self._prim[0];
7120
7121
}
@@ -7123,7 +7124,7 @@ Polynomial = Abacus.Polynomial = Class(INumber, {
7123
7124
// https://en.wikipedia.org/wiki/Rational_root_theorem
7124
7125
// https://en.wikipedia.org/wiki/Gauss%27s_lemma_(polynomial)
7125
7126
var self = this, Arithmetic = Abacus.Arithmetic, O = Arithmetic.O,
7126
- roots = [], primitive,c, i, d0, dn, iter, comb, root;
7127
+ roots = [], primitive,c, p, i, d0, dn, iter, comb, root, nroot, found ;
7127
7128
7128
7129
if ( 0 === self.deg() ) return roots; // no roots for constant polynomials
7129
7130
@@ -7137,17 +7138,37 @@ Polynomial = Abacus.Polynomial = Class(INumber, {
7137
7138
if ( i+1<c.length )
7138
7139
{
7139
7140
// try all possible rational divisors of c_0(excluding trivial zero terms) and c_n
7140
- d0 = divisors(c[i].num); dn = divisors(c[c.length-1].num);
7141
+ iter = divisors(c[i].num, true);
7142
+ d0 = iter.get(); iter.dispose();
7143
+ iter = divisors(c[c.length-1].num, true);
7144
+ dn = iter.get(); iter.dispose();
7145
+
7141
7146
iter = Tensor([d0.length, dn.length]);
7142
7147
while(iter.hasNext())
7143
7148
{
7144
7149
comb = iter.next();
7145
- // try positive root
7150
+ // positive root
7146
7151
root = Rational(d0[comb[0]], dn[comb[1]]);
7147
- if ( primitive.valueOf(root).equ(O) ) roots.push(root);
7148
- // try negative root
7149
- root = root.neg();
7150
- if ( primitive.valueOf(root).equ(O) ) roots.push(root);
7152
+ // negative root
7153
+ nroot = Rational(Arithmetic.neg(d0[comb[0]]), dn[comb[1]]);
7154
+ p = primitive; found = true;
7155
+ while( found && (0<p.deg()) )
7156
+ {
7157
+ found = false;
7158
+ // try positive root
7159
+ if ( p.valueOf(root).equ(O) )
7160
+ {
7161
+ roots.push(root);
7162
+ found = true;
7163
+ }
7164
+ // try negative root
7165
+ if ( p.valueOf(nroot).equ(O) )
7166
+ {
7167
+ roots.push(nroot);
7168
+ found = true;
7169
+ }
7170
+ if ( found ) p = p.d(); // get derivative to check if roots are multiple
7171
+ }
7151
7172
}
7152
7173
iter.dispose();
7153
7174
}
@@ -7295,6 +7316,29 @@ Polynomial = Abacus.Polynomial = Class(INumber, {
7295
7316
return pow;
7296
7317
}
7297
7318
}
7319
+ ,compose: function( x ) {
7320
+ // functionaly compose one polynomial with another. ie result = P(Q(x))
7321
+ var self = this, Arithmetic = Abacus.Arithmetic, O = Arithmetic.O, px, c, i;
7322
+ if ( x instanceof Matrix ) return null;
7323
+ if ( x instanceof Term ) x = Expr(x);
7324
+ if ( x instanceof Expr ) x = Polynomial.fromExpr(x, self.symbol);
7325
+ if ( x instanceof Complex ) x = x.real;
7326
+ if ( Arithmetic.isNumber(x) || (x instanceof Rational) )
7327
+ {
7328
+ return Polynomial([self.valueOf(x)], self.symbol);
7329
+ }
7330
+ else if ( x instanceof Polynomial )
7331
+ {
7332
+ // Composition through variation of Horner's algorithm for fast evaluation
7333
+ if ( 0 === self.deg() ) return self.clone();
7334
+ if ( 0 === x.deg() ) return Polynomial([self.valueOf(x.c())], x.symbol);
7335
+ c = self.coeff; i = c.length-1;
7336
+ px = Polynomial([c[i]], x.symbol);
7337
+ while(i--) px = Polynomial([c[i]], x.symbol).add(px.mul(x));
7338
+ return px;
7339
+ }
7340
+ return self;
7341
+ }
7298
7342
,shift: function( s ) {
7299
7343
// shift <-> equivalent to multiplication/division by a monomial x^s
7300
7344
var self = this, Arithmetic = Abacus.Arithmetic;
0 commit comments