class Musicality::Function::Piecewise
Combine functions that are each applicable for a non-overlapping domain.
@author James Tunnell
Attributes
pieces[R]
Public Class Methods
new()
click to toggle source
Take an array of points (each point is a two-element array pair) and create a piecewise function to calculate values in-between.
# File lib/musicality/notation/util/piecewise_function.rb, line 12 def initialize @pieces = { } end
Public Instance Methods
==(other)
click to toggle source
# File lib/musicality/notation/util/piecewise_function.rb, line 16 def ==(other) @pieces == other.pieces end
add_piece(domain, func)
click to toggle source
Add a function piece, which covers the given domain (includes domain start but not the end). @param [Range] domain The function domain. If this overlaps an existing domain,
the existing domain will be split with the non- overlapping pieces kept and the overlapping old piece discarded.
# File lib/musicality/notation/util/piecewise_function.rb, line 26 def add_piece domain, func raise ArgumentError, "domain is not a Range" unless domain.is_a? Range raise ArgumentError, "func is not a Function" unless func.is_a? Function contains_domain_completely = @pieces.select { |d,f| d.include?(domain.begin) && d.include?(domain.end) } if contains_domain_completely.any? contains_domain_completely.each do |d,f| l = d.begin...domain.begin if d.exclude_end? r = domain.end...d.end else r = domain.end..d.end end @pieces.delete d if domain.begin != d.begin @pieces[l] = f end if domain.end == d.end @pieces[domain.begin..domain.end] = func else @pieces[domain.begin...domain.end] = func @pieces[r] = f end end else delete_completely = @pieces.select { |d,f| domain.include?(d.begin) && domain.include?(d.end) } delete_completely.each do |d,f| @pieces.delete d end # should only be one move_end = @pieces.select { |d,f| domain.include?(d.end) } move_end.each do |d,f| @pieces.delete d @pieces[d.begin...domain.begin] = f end # should only be one move_begin = @pieces.select { |d,f| domain.include?(d.begin) } move_begin.each do |d,f| @pieces.delete d if d.exclude_end? @pieces[domain.end...d.end] = f else @pieces[domain.end..d.end] = f end end if move_begin.any? @pieces[domain.begin...domain.end] = func else @pieces[domain] = func end end end
at(x)
click to toggle source
Evaluate the piecewise function by finding a function piece whose domain includes the given independent value.
# File lib/musicality/notation/util/piecewise_function.rb, line 91 def at x @pieces.each do |domain, func| if domain.include? x return func.at(x) end end raise DomainError, "The input #{x} is not in the domain." end
domain_include?(x)
click to toggle source
# File lib/musicality/notation/util/piecewise_function.rb, line 85 def domain_include? x !@pieces.keys.detect {|domain| domain.include?(x)}.nil? end