Class: Musicality::Function::Piecewise

Inherits:
Musicality::Function show all
Defined in:
lib/musicality/notation/util/piecewise_function.rb

Overview

Combine functions that are each applicable for a non-overlapping domain.

Author:

  • James Tunnell

Direct Known Subclasses

Transition, ValueComputer

Instance Attribute Summary collapse

Attributes inherited from Musicality::Function

#domain

Instance Method Summary collapse

Methods inherited from Musicality::Function

#sample, transform_domains

Constructor Details

#initializePiecewise

Take an array of points (each point is a two-element array pair) and create a piecewise function to calculate values in-between.



12
13
14
# File 'lib/musicality/notation/util/piecewise_function.rb', line 12

def initialize
  @pieces = { }
end

Instance Attribute Details

#piecesObject (readonly)

Returns the value of attribute pieces.



8
9
10
# File 'lib/musicality/notation/util/piecewise_function.rb', line 8

def pieces
  @pieces
end

Instance Method Details

#==(other) ⇒ Object



16
17
18
# File 'lib/musicality/notation/util/piecewise_function.rb', line 16

def ==(other)
  @pieces == other.pieces
end

#add_piece(domain, func) ⇒ Object

Add a function piece, which covers the given domain (includes domain start but not the end).

Parameters:

  • domain (Range)

    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.

Raises:

  • (ArgumentError)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 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) ⇒ Object

Evaluate the piecewise function by finding a function piece whose domain includes the given independent value.

Raises:



91
92
93
94
95
96
97
98
# 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) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/musicality/notation/util/piecewise_function.rb', line 85

def domain_include? x
  !@pieces.keys.detect {|domain| domain.include?(x)}.nil?
end