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