! Copyright (C) 2008 Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: arrays combinators fry kernel macros make math math.bits math.order math.vectors sequences splitting vectors ; IN: math.polynomials : powers ( n x -- seq ) 1 [ * ] accumulate nip ; : p= ( p q -- ? ) pextend = ; : ptrim ( p -- q ) dup length 1 = [ [ zero? ] trim-tail ] unless ; : 2ptrim ( p q -- p' q' ) [ ptrim ] bi@ ; : p+ ( p q -- r ) pextend v+ ; : p- ( p q -- r ) pextend v- ; ALIAS: n*p n*v : pextend-conv ( p q -- p' q' ) 2dup [ length ] bi@ + 1 - 2pad-tail ; : p* ( p q -- r ) 2unempty pextend-conv [ drop length [ iota ] keep ] [ nip ] [ drop ] 2tri '[ _ _ _ v* sum ] map reverse ; : p-sq ( p -- p^2 ) dup p* ; inline ERROR: negative-power-polynomial p n ; : (p^) ( p n -- p^n ) make-bits { 1 } [ [ over p* ] when [ p-sq ] dip ] reduce nip ; : p^ ( p n -- p^n ) dup 0 >= [ (p^) ] [ negative-power-polynomial ] if ; vector dup pop* swap rest-slice ; PRIVATE> : p/mod ( p q -- z w ) p/mod-setup [ [ (p/mod) ] times ] V{ } make reverse nip swap 2ptrim pextend ; : pgcd ( p q -- a d ) [ V{ 0 } clone V{ 1 } clone ] 2dip swap (pgcd) [ >array ] bi@ ; : pdiff ( p -- p' ) dup length iota v* rest ; : polyval ( x p -- p[x] ) [ length swap powers ] [ nip ] 2bi v. ; MACRO: polyval* ( p -- ) reverse [ 1 tail [ \ * swap \ + [ ] 3sequence ] map ] [ first \ drop swap [ ] 2sequence ] bi prefix \ cleave [ ] 2sequence ;