Class: Symbolic

Inherits:
Object
  • Object
show all
Defined in:
lib/symbolic-math.rb

Overview

Proof-of-concept: symbolic expressions in Ruby (inspired by Sage)

Defined Under Namespace

Classes: Expression

Constant Summary collapse

INFIX_OPERATORS =
{
  :+ => lambda{|x,y| x+y},
  :- => lambda{|x,y| x-y},
  :* => lambda{|x,y| x*y},
  :/ => lambda{|x,y| x/y},
  :^ => lambda{|x,y| x**y}, # nice, but wrong precedence!
  :** => lambda{|x,y| x**y}
}
PREFIX_OPERATORS =
{
  :+ => lambda{|x| +x},
  :- => lambda{|x| -x}
}
FUNCTIONS =
{
  :sin=>lambda{|x| Math.sin(x)},
  :cos=>lambda{|x| Math.cos(x)},
  :tan=>lambda{|x| Math.tan(x)},
  :asin=>lambda{|x| Math.asin(x)},
  :acos=>lambda{|x| Math.acos(x)},
  :atan=>lambda{|x| Math.atan(x)},
  :atan2=>lambda{|y,x| Math.atan2(y,x)},
  :sqrt=>lambda{|x| Math.sqrt(x)},
  :abs=>lambda{|x| x.abs}
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSymbolic

Returns a new instance of Symbolic.



145
146
147
# File 'lib/symbolic-math.rb', line 145

def initialize
  @vars = {}
end

Instance Attribute Details

#varsObject (readonly)

Returns the value of attribute vars.



149
150
151
# File 'lib/symbolic-math.rb', line 149

def vars
  @vars
end

Class Method Details

.fun(name, mthd = nil, &blk) ⇒ Object

Raises:

  • (ArgumentError)


127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/symbolic-math.rb', line 127

def self.fun(name, mthd=nil, &blk)
  raise ArgumentError,"Invalid function definition" unless (mthd || blk) && (!mthd || !blk)
  blk ||= mthd
  name = name.to_sym
  arity = blk.arity
  FUNCTIONS[name] = blk # TODO: local functions (per Symbolic object)
  define_method name do |*args|
  if arity != args.size
    raise ArgumentError,"Invalid number of arguments for  #{name} (#{args.size} for #{arity})"
  end
    Expression.new(name, *args)
  end
end

Instance Method Details

#assign(name, value) ⇒ Object



173
174
175
# File 'lib/symbolic-math.rb', line 173

def assign(name, value)
  @vars[name.to_sym] = value
end

#eval(expr, values = {}) ⇒ Object



185
186
187
# File 'lib/symbolic-math.rb', line 185

def eval(expr, values={})
  expr.eval(@vars.merge(values))
end

#execute(blk) ⇒ Object



177
178
179
180
181
182
183
# File 'lib/symbolic-math.rb', line 177

def execute(blk)
  if blk.arity==1
    blk.call(self)
  else
    self.instance_eval(&blk)
  end
end

#fun(name, mthd = nil, &blk) ⇒ Object



189
190
191
# File 'lib/symbolic-math.rb', line 189

def fun(name, mthd=nil, &blk)
  self.class.fun name, mthd, &blk
end

#macro(name, &blk) ⇒ Object



193
194
195
# File 'lib/symbolic-math.rb', line 193

def macro(name, &blk)
  self.class.class_eval{define_method name, blk}
end

#var(*names) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/symbolic-math.rb', line 151

def var(*names)
  names.each do |name|
    name = name.to_sym
    @vars[name] = nil
    instance_variable_set "@#{name}", Expression.new(name)
    self.class.class_eval{
      attr_reader name
      # can't decide on assignment syntax:
      # 1. assignment operator (requires self) self.x = 1.0;
      define_method :"#{name}=" do |value|
        assign name, value
      end
      # 2. method assign_x 1.0;
      define_method :"assign_#{name}" do |value|
        assign name, value
      end
      # 3. or use assing :x, 1.0;
      # More indecision: rename 'assign' to 'set' ? 'let' ?
    }
  end
end