lib/polynomials.rb in polynomials-0.2.0 vs lib/polynomials.rb in polynomials-0.3.0
- old
+ new
@@ -1,145 +1,19 @@
-require 'set'
-require_relative 'term'
-require_relative 'core_ext/math'
+$LOAD_PATH << File.join(File.dirname(File.expand_path(__FILE__)), 'polynomials')
-class Polynomial
+require 'active_support/inflector'
- MinMaxMapping = { 1.0 => :max, -1.0 => :min }
- AfterextremaCurvatureMapping = { max: :right, min: :left }
- NegPosMinMaxExtremumMapping = {[1.0,-1.0] => :max,[-1.0,1.0] => :min}
+ActiveSupport::Inflector.inflections do |inflect|
+ inflect.plural /mum$/, '\1ma'
+ inflect.singular /ma$/, '\1mum'
+end
- attr_accessor :terms
+require 'polynomial'
+require 'set'
+require 'term'
+require 'point'
+require 'formulas'
+require 'exceptions'
- def self.parse(string)
- polynomial = self.new
- string.split(/(?=[-+])/).each do |term|
- parsed = Term.parse(term)
- polynomial.terms[parsed.exponent].coefficient += parsed.coefficient
- end
- return polynomial
- end
- def initialize(*args)
- self.terms = Hash.new { |hash, key| hash[key] = Term.new(key) }
- unless args.empty?
- args.reverse.each.with_index do |coefficient,exponent|
- self.terms[exponent].coefficient += coefficient
- end
- end
- end
-
- def calculate(x)
- self.terms.values.inject(0.0) do |acc,t|
- acc + (t.coefficient.to_f * (x**t.exponent))
- end
- end
-
- def derivative
- new_function = self.alter do |nf, term|
- nf.terms[term.exponent - 1].coefficient += term.exponent * term.coefficient
- end
- new_function.terms.reject! { |_,t| t.coefficient == 0 }
- return new_function
- end
-
- def roots
- if !terms.empty? and terms.keys.none?(&:zero?)
- self.alter { |nf, term| nf.terms[term.exponent-self.lt.exponent].coefficient = term.coefficient }.roots << 0.0
- else
- case self.degree
- when 1
- Set[-self.terms[0].coefficient / self.terms[1].coefficient]
- when 2
- Math.roots_of_quadratic_function(*coefficients_till(2))
- when 3
- Math.roots_of_cubic_function(*coefficients_till(3))
- when 4
- Math.roots_of_quartic_function(*coefficients_till(4))
- else
- Set[]
- end
- end
- end
-
- def local_extrema
- derivative = self.derivative
- max_min_extremum = Hash.new { |hash,key| hash[key] = Set.new }
- possible_extrema = derivative.roots.sort
- unless possible_extrema.empty?
- samples = ([possible_extrema.first - 1] + possible_extrema.sort + [possible_extrema.last + 1]).each_cons(2).map do |before,after|
- (before + after)/2
- end
-
- possible_extrema.zip(samples.each_cons(2)).each do |pe,(after,before)|
- yafter = derivative.calculate(after)
- ybefore = derivative.calculate(before)
- kind_of_extremum = NegPosMinMaxExtremumMapping[[yafter/yafter.abs,ybefore/ybefore.abs]]
- max_min_extremum[kind_of_extremum] << pe if kind_of_extremum
- end
- end
- return max_min_extremum
- end
-
- def curvature_behaviour
- hash = Hash.new {|h,k|h[k]=Set.new}
- return hash if self.degree > 5
- extrema = self.derivative.extrema
- all_extremas = extrema.values.inject(Set[],&:|).sort
- all_extremas.each_cons(2).map { |s,e| Range.new(s,e) }.group_by do |range|
- kind_of_curvature = AfterextremaCurvatureMapping[extrema.find { |k,v| v.include?(range.begin) }.first]
- end
- end
-
- def degree
- self.terms.keys.max || 0
- end
-
- def to_s
- terms.sort_by { |_,t| -t.exponent }.inject("") do |string,(_,term)|
- string << term.to_s unless term.coefficient.zero? && !term.exponent.zero?
- string
- end.strip.sub(/\A\+\s/, '')
- end
-
- def ==(other)
- delete_zeros = proc{ |_,t| t.coefficient.zero? }
- self.terms.delete_if(&delete_zeros) == other.terms.delete_if(&delete_zeros)
- end
-
- def extrema
- extrema = local_extrema
- unless self.degree == 0
- a = self.gt.coefficient
- max_or_min = (self.degree.even? ? [1.0,1.0] : [-1.0,1.0]).map { |n| (n * a)/a.abs }
- extrema[MinMaxMapping[max_or_min.first]] << -1.0/0
- extrema[MinMaxMapping[max_or_min.last]] << 1.0/0
- end
- return extrema
- end
-
- def gt
- self.terms[self.degree]
- end
-
- def lt
- self.terms[self.terms.min_by{ |_,t| t.exponent}.first]
- end
-
- def coefficients_till(n)
- coefficients = []
- (0..n).each do |e|
- coefficients << self.terms[e].coefficient
- end
- return coefficients.reverse
- end
- private :coefficients_till
-
- def alter
- new_function = self.class.new
- self.terms.values.each do |term|
- yield new_function, term
- end
- return new_function
- end
- protected :alter
+module Polynomials
end