@@ -499,31 +499,24 @@ roots(poly([1,2,3,4])) # [1.0,2.0,3.0,4.0]
499
499
function roots {T} (p:: Poly{T} )
500
500
R = promote_type (T, Float64)
501
501
length (p) == 0 && return zeros (R, 0 )
502
-
503
502
num_leading_zeros = 0
504
503
while abs (p[num_leading_zeros]) <= 2 * eps (T)
505
504
if num_leading_zeros == length (p)- 1
506
505
return zeros (R, 0 )
507
506
end
508
507
num_leading_zeros += 1
509
508
end
510
-
511
509
num_trailing_zeros = 0
512
510
while abs (p[end - num_trailing_zeros]) <= 2 * eps (T)
513
511
num_trailing_zeros += 1
514
512
end
515
-
516
513
n = endof (p)- (num_leading_zeros + num_trailing_zeros)
517
-
518
514
n < 1 && return zeros (R, length (p) - num_trailing_zeros - 1 )
519
515
520
- companion = zeros ( R, n, n )
516
+ companion = diagm ( ones ( R, n- 1 ), - 1 )
521
517
an = p[end - num_trailing_zeros]
522
- for i = 1 : n- 1
523
- companion[i,n] = - p[num_leading_zeros + i - 1 ] / an
524
- companion[i+ 1 ,i] = 1 ;
525
- end
526
- companion[end ,end ] = - p[end - num_trailing_zeros- 1 ] / an
518
+ companion[1 ,:] = - p[(end - num_trailing_zeros- 1 ): - 1 : num_leading_zeros] / an
519
+
527
520
D = eigvals (companion)
528
521
r = zeros (eltype (D),length (p)- num_trailing_zeros- 1 )
529
522
r[1 : n] = D
@@ -571,13 +564,29 @@ polyfit(xs, ys, 2)
571
564
```
572
565
573
566
Original by [ggggggggg](https://github.com/Keno/Polynomials.jl/issues/19)
567
+ More robust version by Marek Peca <[email protected] >
568
+ (1. no exponentiation in system matrix construction, 2. QR least squares)
574
569
"""
575
570
function polyfit (x, y, n:: Int = length (x)- 1 , sym:: Symbol = :x )
576
571
length (x) == length (y) || throw (DomainError)
577
572
1 <= n <= length (x) - 1 || throw (DomainError)
578
573
579
- A = [ float (x[i])^ p for i = 1 : length (x), p = 0 : n ]
580
- Poly (A \ y, sym)
574
+ #
575
+ # here unsure, whether similar(float(x[1]),...), or similar(x,...)
576
+ # however similar may yield unwanted surprise in case of e.g. x::Int
577
+ #
578
+ A= similar (float (x[1 : 1 ]), length (x), n+ 1 )
579
+ #
580
+ # TODO : add support for poly coef bitmap
581
+ # (i.e. polynomial with some terms fixed to zero)
582
+ #
583
+ A[:,1 ]= 1
584
+ for i= 1 : n
585
+ A[:,i+ 1 ]= A[:,i] .* x # cumulative product more precise than x.^n
586
+ end
587
+ Aqr= qrfact (A) # returns QR object, not a matrix
588
+ p= Aqr\ y # least squares solution via QR
589
+ Poly (p, sym)
581
590
end
582
591
polyfit (x,y,sym:: Symbol ) = polyfit (x,y,length (x)- 1 , sym)
583
592
0 commit comments