keisan 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +49 -1
  3. data/keisan.gemspec +1 -0
  4. data/lib/keisan.rb +30 -0
  5. data/lib/keisan/ast/assignment.rb +44 -17
  6. data/lib/keisan/ast/block.rb +60 -0
  7. data/lib/keisan/ast/boolean.rb +5 -5
  8. data/lib/keisan/ast/builder.rb +10 -207
  9. data/lib/keisan/ast/cell.rb +60 -0
  10. data/lib/keisan/ast/constant_literal.rb +9 -0
  11. data/lib/keisan/ast/exponent.rb +6 -6
  12. data/lib/keisan/ast/function.rb +12 -8
  13. data/lib/keisan/ast/indexing.rb +25 -15
  14. data/lib/keisan/ast/line_builder.rb +230 -0
  15. data/lib/keisan/ast/list.rb +28 -1
  16. data/lib/keisan/ast/literal.rb +0 -8
  17. data/lib/keisan/ast/logical_and.rb +1 -1
  18. data/lib/keisan/ast/logical_or.rb +1 -1
  19. data/lib/keisan/ast/multi_line.rb +28 -0
  20. data/lib/keisan/ast/node.rb +32 -24
  21. data/lib/keisan/ast/number.rb +31 -31
  22. data/lib/keisan/ast/operator.rb +12 -4
  23. data/lib/keisan/ast/parent.rb +4 -4
  24. data/lib/keisan/ast/plus.rb +10 -10
  25. data/lib/keisan/ast/string.rb +3 -3
  26. data/lib/keisan/ast/times.rb +8 -8
  27. data/lib/keisan/ast/unary_identity.rb +1 -1
  28. data/lib/keisan/ast/unary_inverse.rb +7 -7
  29. data/lib/keisan/ast/unary_minus.rb +5 -5
  30. data/lib/keisan/ast/unary_operator.rb +2 -2
  31. data/lib/keisan/ast/unary_plus.rb +2 -2
  32. data/lib/keisan/ast/variable.rb +26 -10
  33. data/lib/keisan/context.rb +5 -5
  34. data/lib/keisan/evaluator.rb +15 -8
  35. data/lib/keisan/function.rb +24 -6
  36. data/lib/keisan/functions/cbrt.rb +1 -1
  37. data/lib/keisan/functions/cos.rb +1 -1
  38. data/lib/keisan/functions/cosh.rb +1 -1
  39. data/lib/keisan/functions/cot.rb +1 -1
  40. data/lib/keisan/functions/coth.rb +1 -1
  41. data/lib/keisan/functions/csc.rb +1 -1
  42. data/lib/keisan/functions/csch.rb +1 -1
  43. data/lib/keisan/functions/default_registry.rb +53 -74
  44. data/lib/keisan/functions/diff.rb +18 -14
  45. data/lib/keisan/functions/erf.rb +15 -0
  46. data/lib/keisan/functions/exp.rb +1 -1
  47. data/lib/keisan/functions/expression_function.rb +15 -21
  48. data/lib/keisan/functions/filter.rb +13 -15
  49. data/lib/keisan/functions/if.rb +14 -20
  50. data/lib/keisan/functions/let.rb +36 -0
  51. data/lib/keisan/functions/map.rb +11 -13
  52. data/lib/keisan/functions/math_function.rb +2 -2
  53. data/lib/keisan/functions/proc_function.rb +10 -6
  54. data/lib/keisan/functions/rand.rb +2 -1
  55. data/lib/keisan/functions/range.rb +74 -0
  56. data/lib/keisan/functions/reduce.rb +12 -14
  57. data/lib/keisan/functions/registry.rb +7 -7
  58. data/lib/keisan/functions/replace.rb +8 -8
  59. data/lib/keisan/functions/sample.rb +2 -1
  60. data/lib/keisan/functions/sec.rb +1 -1
  61. data/lib/keisan/functions/sech.rb +1 -1
  62. data/lib/keisan/functions/sin.rb +1 -1
  63. data/lib/keisan/functions/sinh.rb +1 -1
  64. data/lib/keisan/functions/sqrt.rb +1 -1
  65. data/lib/keisan/functions/tan.rb +1 -1
  66. data/lib/keisan/functions/tanh.rb +1 -1
  67. data/lib/keisan/functions/while.rb +46 -0
  68. data/lib/keisan/parser.rb +121 -79
  69. data/lib/keisan/parsing/assignment.rb +1 -1
  70. data/lib/keisan/parsing/bitwise_and.rb +1 -1
  71. data/lib/keisan/parsing/bitwise_not.rb +1 -1
  72. data/lib/keisan/parsing/bitwise_not_not.rb +1 -1
  73. data/lib/keisan/parsing/bitwise_or.rb +1 -1
  74. data/lib/keisan/parsing/bitwise_xor.rb +1 -1
  75. data/lib/keisan/parsing/curly_group.rb +6 -0
  76. data/lib/keisan/parsing/divide.rb +1 -1
  77. data/lib/keisan/parsing/exponent.rb +1 -1
  78. data/lib/keisan/parsing/function.rb +1 -1
  79. data/lib/keisan/parsing/group.rb +1 -1
  80. data/lib/keisan/parsing/indexing.rb +1 -1
  81. data/lib/keisan/parsing/line_separator.rb +6 -0
  82. data/lib/keisan/parsing/logical_and.rb +1 -1
  83. data/lib/keisan/parsing/logical_equal.rb +1 -1
  84. data/lib/keisan/parsing/logical_greater_than.rb +1 -1
  85. data/lib/keisan/parsing/logical_greater_than_or_equal_to.rb +1 -1
  86. data/lib/keisan/parsing/logical_less_than.rb +1 -1
  87. data/lib/keisan/parsing/logical_less_than_or_equal_to.rb +1 -1
  88. data/lib/keisan/parsing/logical_not.rb +1 -1
  89. data/lib/keisan/parsing/logical_not_equal.rb +1 -1
  90. data/lib/keisan/parsing/logical_not_not.rb +1 -1
  91. data/lib/keisan/parsing/logical_or.rb +1 -1
  92. data/lib/keisan/parsing/minus.rb +1 -1
  93. data/lib/keisan/parsing/modulo.rb +1 -1
  94. data/lib/keisan/parsing/operator.rb +1 -1
  95. data/lib/keisan/parsing/plus.rb +1 -1
  96. data/lib/keisan/parsing/times.rb +1 -1
  97. data/lib/keisan/parsing/unary_minus.rb +1 -1
  98. data/lib/keisan/parsing/unary_operator.rb +1 -1
  99. data/lib/keisan/parsing/unary_plus.rb +1 -1
  100. data/lib/keisan/repl.rb +1 -1
  101. data/lib/keisan/tokenizer.rb +4 -9
  102. data/lib/keisan/tokens/group.rb +3 -1
  103. data/lib/keisan/tokens/line_separator.rb +11 -0
  104. data/lib/keisan/variables/default_registry.rb +0 -5
  105. data/lib/keisan/variables/registry.rb +7 -7
  106. data/lib/keisan/version.rb +1 -1
  107. metadata +27 -2
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- -Keisan::AST::Function.new([argument], "sin")
11
+ -AST::Function.new([argument], "sin")
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- Keisan::AST::Function.new([argument], "sinh")
11
+ AST::Function.new([argument], "sinh")
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- -Keisan::AST::Exponent.new([Keisan::AST::Function.new([argument], "sin"), -2])
11
+ -AST::Exponent.new([AST::Function.new([argument], "sin"), -2])
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- -Keisan::AST::Exponent.new([Keisan::AST::Function.new([argument], "sinh"), -2])
11
+ -AST::Exponent.new([AST::Function.new([argument], "sinh"), -2])
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- -Keisan::AST::Function.new([argument], "cos") * Keisan::AST::Exponent.new([Keisan::AST::Function.new([argument], "sin"), -2])
11
+ -AST::Function.new([argument], "cos") * AST::Exponent.new([AST::Function.new([argument], "sin"), -2])
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- -Keisan::AST::Function.new([argument], "cosh") * Keisan::AST::Exponent.new([Keisan::AST::Function.new([argument], "sinh"), -2])
11
+ -AST::Function.new([argument], "cosh") * AST::Exponent.new([AST::Function.new([argument], "sinh"), -2])
12
12
  end
13
13
  end
14
14
  end
@@ -1,6 +1,10 @@
1
+ require_relative "let"
2
+
1
3
  require_relative "if"
4
+ require_relative "while"
2
5
  require_relative "diff"
3
6
  require_relative "replace"
7
+ require_relative "range"
4
8
  require_relative "map"
5
9
  require_relative "filter"
6
10
  require_relative "reduce"
@@ -8,6 +12,7 @@ require_relative "rand"
8
12
  require_relative "sample"
9
13
  require_relative "math_function"
10
14
  require_relative "cmath_function"
15
+ require_relative "erf"
11
16
  require_relative "exp"
12
17
  require_relative "log"
13
18
  require_relative "sin"
@@ -40,43 +45,27 @@ module Keisan
40
45
  private
41
46
 
42
47
  def self.register_defaults!(registry)
43
- registry.register!(:if, Keisan::Functions::If.new, force: true)
44
- registry.register!(:diff, Keisan::Functions::Diff.new, force: true)
45
- registry.register!(:replace, Keisan::Functions::Replace.new, force: true)
46
- registry.register!(:map, Keisan::Functions::Map.new, force: true)
47
- registry.register!(:collect, Keisan::Functions::Map.new, force: true)
48
- registry.register!(:filter, Keisan::Functions::Filter.new, force: true)
49
- registry.register!(:select, Keisan::Functions::Filter.new, force: true)
50
- registry.register!(:reduce, Keisan::Functions::Reduce.new, force: true)
51
- registry.register!(:inject, Keisan::Functions::Reduce.new, force: true)
52
-
53
- register_builtin_math!(registry)
48
+ registry.register!(:let, Let.new, force: true)
49
+
50
+ registry.register!(:if, If.new, force: true)
51
+ registry.register!(:while, While.new, force: true)
52
+ registry.register!(:diff, Diff.new, force: true)
53
+ registry.register!(:replace, Replace.new, force: true)
54
+ registry.register!(:map, Map.new, force: true)
55
+ registry.register!(:collect, Map.new, force: true)
56
+ registry.register!(:filter, Filter.new, force: true)
57
+ registry.register!(:select, Filter.new, force: true)
58
+ registry.register!(:reduce, Reduce.new, force: true)
59
+ registry.register!(:inject, Reduce.new, force: true)
60
+
61
+ register_math!(registry)
54
62
  register_array_methods!(registry)
55
63
  register_random_methods!(registry)
64
+ end
56
65
 
57
- registry.register!(:exp, Keisan::Functions::Exp.new, force: true)
58
- registry.register!(:log, Keisan::Functions::Log.new, force: true)
59
-
60
- registry.register!(:sin, Keisan::Functions::Sin.new, force: true)
61
- registry.register!(:cos, Keisan::Functions::Cos.new, force: true)
62
- registry.register!(:tan, Keisan::Functions::Tan.new, force: true)
63
- registry.register!(:cot, Keisan::Functions::Cot.new, force: true)
64
- registry.register!(:sec, Keisan::Functions::Sec.new, force: true)
65
- registry.register!(:csc, Keisan::Functions::Csc.new, force: true)
66
-
67
- registry.register!(:sinh, Keisan::Functions::Sinh.new, force: true)
68
- registry.register!(:cosh, Keisan::Functions::Cosh.new, force: true)
69
- registry.register!(:tanh, Keisan::Functions::Tanh.new, force: true)
70
- registry.register!(:coth, Keisan::Functions::Coth.new, force: true)
71
- registry.register!(:sech, Keisan::Functions::Sech.new, force: true)
72
- registry.register!(:csch, Keisan::Functions::Csch.new, force: true)
73
-
74
- registry.register!(:sqrt, Keisan::Functions::Sqrt.new, force: true)
75
- registry.register!(:cbrt, Keisan::Functions::Cbrt.new, force: true)
76
-
77
- registry.register!(:abs, Keisan::Functions::Abs.new, force: true)
78
- registry.register!(:real, Keisan::Functions::Real.new, force: true)
79
- registry.register!(:imag, Keisan::Functions::Imag.new, force: true)
66
+ def self.register_math!(registry)
67
+ register_builtin_math!(registry)
68
+ register_custom_math!(registry)
80
69
  end
81
70
 
82
71
  def self.register_builtin_math!(registry)
@@ -92,54 +81,44 @@ module Keisan
92
81
  end
93
82
  end
94
83
 
84
+ CUSTOM_MATH_FUNCTIONS = %i(erf exp log sin cos tan cot sec csc sinh cosh tanh coth sech csch sqrt cbrt abs real imag).freeze
85
+
86
+ def self.register_custom_math!(registry)
87
+ factorial = Proc.new {|n|
88
+ (1..n).inject(1) do |res, i|
89
+ res * i
90
+ end
91
+ }
92
+ nPk = Proc.new {|n, k|
93
+ factorial.call(n) / factorial.call(n-k)
94
+ }
95
+ nCk = Proc.new {|n, k|
96
+ factorial.call(n) / factorial.call(k) / factorial.call(n-k)
97
+ }
98
+
99
+ registry.register!(:factorial, factorial, force: true)
100
+ registry.register!(:nPk, nPk, force: true)
101
+ registry.register!(:permute, nPk, force: true)
102
+ registry.register!(:nCk, nCk, force: true)
103
+ registry.register!(:choose, nCk, force: true)
104
+
105
+ CUSTOM_MATH_FUNCTIONS.each do |method|
106
+ klass = Keisan::Functions.const_get(method.to_s.capitalize)
107
+ registry.register!(method, klass.new, force: true)
108
+ end
109
+ end
110
+
95
111
  def self.register_array_methods!(registry)
96
112
  %i(min max size flatten reverse).each do |method|
97
113
  registry.register!(method, Proc.new {|a| a.send(method)}, force: true)
98
114
  end
99
115
 
100
- # range(10) => Integers from 0 inclusive to 10 exclusively
101
- # range(5, 15) => Integers from 5 inclusive to 15 exclusive
102
- # range(10, -1, -2) => Integers from 10 inclusive to -1 exclusive, decreasing by twos
103
- # i.e.: [10, 8, 6, 4, 2, 0]
104
- registry.register!("range", Proc.new {|*args|
105
- case args.count
106
- when 1
107
- (0...args[0]).to_a
108
- when 2
109
- (args[0]...args[1]).to_a
110
- when 3
111
- current = args[0]
112
- final = args[1]
113
- shift = args[2]
114
-
115
- if shift == 0 or !shift.is_a?(Integer)
116
- raise Keisan::Exceptions::InvalidFunctionError.new("range's 3rd argument must be non-zero integer")
117
- end
118
-
119
- result = []
120
-
121
- if shift > 0
122
- while current < final
123
- result << current
124
- current += shift
125
- end
126
- else
127
- while current > final
128
- result << current
129
- current += shift
130
- end
131
- end
132
-
133
- result
134
- else
135
- raise Keisan::Exceptions::InvalidFunctionError.new("range takes 1 to 3 arguments")
136
- end
137
- }, force: true)
116
+ registry.register!("range", Functions::Range.new, force: true)
138
117
  end
139
118
 
140
119
  def self.register_random_methods!(registry)
141
- registry.register!(:rand, Keisan::Functions::Rand.new, force: true)
142
- registry.register!(:sample, Keisan::Functions::Sample.new, force: true)
120
+ registry.register!(:rand, Rand.new, force: true)
121
+ registry.register!(:sample, Sample.new, force: true)
143
122
  end
144
123
  end
145
124
  end
@@ -1,23 +1,26 @@
1
1
  module Keisan
2
2
  module Functions
3
- class Diff < Keisan::Function
3
+ class Diff < Function
4
4
  def initialize
5
+ super("diff", -1)
5
6
  @name = "diff"
6
7
  end
7
8
 
8
9
  def value(ast_function, context = nil)
9
- context ||= Keisan::Context.new
10
+ validate_arguments!(ast_function.children.count)
11
+ context ||= Context.new
10
12
  evaluation = evaluate(ast_function, context)
11
13
 
12
14
  if is_ast_derivative?(evaluation)
13
- raise Keisan::Exceptions::NonDifferentiableError.new
15
+ raise Exceptions::NonDifferentiableError.new
14
16
  else
15
17
  evaluation.value(context)
16
18
  end
17
19
  end
18
20
 
19
21
  def evaluate(ast_function, context = nil)
20
- context ||= Keisan::Context.new
22
+ validate_arguments!(ast_function.children.count)
23
+ context ||= Context.new
21
24
  function, variables = function_and_variables(ast_function)
22
25
  local = context_from(variables, context)
23
26
 
@@ -30,7 +33,7 @@ module Keisan
30
33
  end
31
34
 
32
35
  case result
33
- when Keisan::AST::Function
36
+ when AST::Function
34
37
  result.name == "diff" ? result : result.simplify(context)
35
38
  else
36
39
  result.simplify(context)
@@ -38,9 +41,10 @@ module Keisan
38
41
  end
39
42
 
40
43
  def simplify(ast_function, context = nil)
41
- raise Keisan::Exceptions::InternalError.new("received non-diff function") unless ast_function.name == "diff"
44
+ validate_arguments!(ast_function.children.count)
45
+ raise Exceptions::InternalError.new("received non-diff function") unless ast_function.name == "diff"
42
46
  function, variables = function_and_variables(ast_function)
43
- context ||= Keisan::Context.new
47
+ context ||= Context.new
44
48
  local = context_from(variables, context)
45
49
 
46
50
  result = variables.inject(function.simplify(local)) do |result, variable|
@@ -52,7 +56,7 @@ module Keisan
52
56
  end
53
57
 
54
58
  case result
55
- when Keisan::AST::Function
59
+ when AST::Function
56
60
  result.name == "diff" ? result : result.simplify(context)
57
61
  else
58
62
  result.simplify(context)
@@ -62,7 +66,7 @@ module Keisan
62
66
  private
63
67
 
64
68
  def is_ast_derivative?(node)
65
- node.is_a?(Keisan::AST::Function) && node.name == name
69
+ node.is_a?(AST::Function) && node.name == name
66
70
  end
67
71
 
68
72
  def differentiate(node, variable, context)
@@ -71,7 +75,7 @@ module Keisan
71
75
  else
72
76
  return AST::Number.new(0)
73
77
  end
74
- rescue Keisan::Exceptions::NonDifferentiableError => e
78
+ rescue Exceptions::NonDifferentiableError => e
75
79
  return AST::Function.new(
76
80
  [node, variable],
77
81
  "diff"
@@ -79,14 +83,14 @@ module Keisan
79
83
  end
80
84
 
81
85
  def function_and_variables(ast_function)
82
- unless ast_function.is_a?(Keisan::AST::Function) && ast_function.name == name
83
- raise Keisan::Exceptions::InvalidFunctionError.new("Must receive diff function")
86
+ unless ast_function.is_a?(AST::Function) && ast_function.name == name
87
+ raise Exceptions::InvalidFunctionError.new("Must receive diff function")
84
88
  end
85
89
 
86
90
  variables = ast_function.children[1..-1]
87
91
 
88
92
  unless variables.all? {|var| var.is_a?(AST::Variable)}
89
- raise Keisan::Exceptions::InvalidFunctionError.new("Diff must differentiate with respect to variables")
93
+ raise Exceptions::InvalidFunctionError.new("Diff must differentiate with respect to variables")
90
94
  end
91
95
 
92
96
  [
@@ -96,7 +100,7 @@ module Keisan
96
100
  end
97
101
 
98
102
  def context_from(variables, context = nil)
99
- context ||= Keisan::Context.new(shadowed: variables.map(&:name))
103
+ context ||= Context.new(shadowed: variables.map(&:name))
100
104
  context.spawn_child(shadowed: variables.map(&:name))
101
105
  end
102
106
  end
@@ -0,0 +1,15 @@
1
+ module Keisan
2
+ module Functions
3
+ class Erf < MathFunction
4
+ def initialize
5
+ super("erf")
6
+ end
7
+
8
+ protected
9
+
10
+ def self.derivative(argument)
11
+ 2/Math.sqrt(Math::PI) * AST::Function.new([-argument**2], "exp")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- Keisan::AST::Function.new([argument], "exp")
11
+ AST::Function.new([argument], "exp")
12
12
  end
13
13
  end
14
14
  end
@@ -1,17 +1,17 @@
1
1
  module Keisan
2
2
  module Functions
3
- class ExpressionFunction < Keisan::Function
3
+ class ExpressionFunction < Function
4
4
  attr_reader :arguments, :expression
5
5
 
6
6
  def initialize(name, arguments, expression, transient_definitions)
7
- super(name)
7
+ super(name, arguments.count)
8
8
  @expression = expression.deep_dup
9
9
  @arguments = arguments
10
10
  @transient_definitions = transient_definitions
11
11
  end
12
12
 
13
13
  def call(context, *args)
14
- verify_argument_size!(args.count)
14
+ validate_arguments!(args.count)
15
15
 
16
16
  local = local_context_for(context)
17
17
  arguments.each.with_index do |arg_name, i|
@@ -22,17 +22,17 @@ module Keisan
22
22
  end
23
23
 
24
24
  def value(ast_function, context = nil)
25
- verify_argument_size!(ast_function.children.count)
25
+ validate_arguments!(ast_function.children.count)
26
26
 
27
- context ||= Keisan::Context.new
27
+ context ||= Context.new
28
28
  argument_values = ast_function.children.map {|child| child.value(context)}
29
29
  call(context, *argument_values)
30
30
  end
31
31
 
32
32
  def evaluate(ast_function, context = nil)
33
- verify_argument_size!(ast_function.children.count)
33
+ validate_arguments!(ast_function.children.count)
34
34
 
35
- context ||= Keisan::Context.new
35
+ context ||= Context.new
36
36
  local = local_context_for(context)
37
37
 
38
38
  argument_values = ast_function.children.map {|child| child.evaluate(context)}
@@ -41,18 +41,18 @@ module Keisan
41
41
  local.register_variable!(arg_name, argument_values[i].evaluate(context))
42
42
  end
43
43
 
44
- expression.evaluate(local)
44
+ expression.evaluated(local)
45
45
  end
46
46
 
47
47
  def simplify(ast_function, context = nil)
48
- verify_argument_size!(ast_function.children.count)
48
+ validate_arguments!(ast_function.children.count)
49
49
 
50
50
  ast_function.instance_variable_set(
51
51
  :@children,
52
52
  ast_function.children.map {|child| child.evaluate(context)}
53
53
  )
54
54
 
55
- if ast_function.children.all? {|child| child.is_a?(Keisan::AST::ConstantLiteral)}
55
+ if ast_function.children.all? {|child| child.is_a?(AST::ConstantLiteral)}
56
56
  value(ast_function, context).to_node.simplify(context)
57
57
  else
58
58
  ast_function
@@ -66,7 +66,7 @@ module Keisan
66
66
  # dx(t)/dt * f_x(x(t), y(t)) + dy(t)/dt * f_y(x(t), y(t)),
67
67
  # where f_x and f_y are the x and y partial derivatives respectively.
68
68
  def differentiate(ast_function, variable, context = nil)
69
- verify_argument_size!(ast_function.children.count)
69
+ validate_arguments!(ast_function.children.count)
70
70
 
71
71
  local = local_context_for(context)
72
72
 
@@ -78,10 +78,10 @@ module Keisan
78
78
  child.differentiate(variable, context)
79
79
  end
80
80
 
81
- Keisan::AST::Plus.new(
81
+ AST::Plus.new(
82
82
  argument_derivatives.map.with_index {|argument_derivative, i|
83
83
  partial_derivative = partial_derivatives[i].replace(argument_variables[i], argument_values[i])
84
- Keisan::AST::Times.new([argument_derivative, partial_derivative])
84
+ AST::Times.new([argument_derivative, partial_derivative])
85
85
  }
86
86
  )
87
87
  end
@@ -89,7 +89,7 @@ module Keisan
89
89
  private
90
90
 
91
91
  def argument_variables
92
- @argument_variables ||= arguments.map {|argument| Keisan::AST::Variable.new(argument)}
92
+ @argument_variables ||= arguments.map {|argument| AST::Variable.new(argument)}
93
93
  end
94
94
 
95
95
  def partial_derivatives
@@ -98,14 +98,8 @@ module Keisan
98
98
  end
99
99
  end
100
100
 
101
- def verify_argument_size!(argument_size)
102
- unless @arguments.count == argument_size
103
- raise Keisan::Exceptions::InvalidFunctionError.new("Invalid number of arguments for #{name} function")
104
- end
105
- end
106
-
107
101
  def local_context_for(context = nil)
108
- context ||= Keisan::Context.new
102
+ context ||= Context.new
109
103
  context.spawn_child(definitions: @transient_definitions, shadowed: @arguments, transient: true)
110
104
  end
111
105
  end