qlang 0.0.27182000 → 0.0.27182100
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/README.md +17 -1
- data/Rakefile +16 -3
- data/bin/qlang +7 -1
- data/ext/qlang/QMatrix/q_matrix.c +0 -0
- data/ext/qlang/extconf.rb +3 -0
- data/ext/qlang/qlang.c +65 -0
- data/ext/qlang/qlang.h +6 -0
- data/{spec → legacy_rspec}/langs/Haskell/ex1_after.hs +0 -0
- data/{spec → legacy_rspec}/langs/Haskell/ex1_before.hs +0 -0
- data/{spec → legacy_rspec}/langs/Python/ex1_after.py +0 -0
- data/{spec → legacy_rspec}/langs/Python/ex1_before.py +0 -0
- data/{spec → legacy_rspec}/langs/R/ex1_after.R +0 -0
- data/{spec → legacy_rspec}/langs/R/ex1_before.R +0 -0
- data/{spec → legacy_rspec}/objects/list_spec.rb +0 -0
- data/{spec → legacy_rspec}/objects/matrix_spec.rb +0 -0
- data/{spec → legacy_rspec}/objects/vector_spec.rb +0 -0
- data/lib/qlang.rb +21 -18
- data/lib/qlang/api/func_api.rb +1 -1
- data/lib/qlang/api/integral_api.rb +1 -1
- data/lib/qlang/api/list_api.rb +1 -1
- data/lib/qlang/api/matrix_api.rb +1 -1
- data/lib/qlang/api/vector_api.rb +1 -1
- data/lib/qlang/iq.rb +5 -2
- data/lib/qlang/lexer.rb +2 -2
- data/lib/qlang/lexer/base.rb +31 -14
- data/lib/qlang/lexer/formula_lexer.rb +20 -0
- data/lib/qlang/lexer/main_lexer.rb +25 -0
- data/lib/qlang/lexer/tokens.rb +27 -15
- data/lib/qlang/parser.rb +29 -41
- data/lib/qlang/parser/formula_parser.rb +25 -25
- data/lib/qlang/parser/func_parser.rb +2 -2
- data/lib/qlang/parser/integral_parser.rb +2 -2
- data/lib/qlang/parser/matrix_parser.rb +3 -3
- data/lib/qlang/parser/vector_parser.rb +4 -4
- data/lib/qlang/version.rb +1 -1
- data/{q_lang.gemspec → qlang.gemspec} +4 -2
- data/test/internal/test_tokens.rb +36 -0
- data/test/interpreter/base.rb +17 -0
- data/test/interpreter/test_differential.rb +44 -0
- data/test/interpreter/test_function.rb +45 -0
- data/test/interpreter/test_general.rb +13 -0
- data/test/interpreter/test_integral.rb +39 -0
- data/test/interpreter/test_matrix.rb +71 -0
- data/test/interpreter/test_vector.rb +29 -0
- data/test/langs/test_r.rb +33 -0
- data/test/langs/test_ruby.rb +10 -0
- data/{spec/spec_helper.rb → test/minitest_helper.rb} +4 -4
- data/test/q_matrix/test_q_matrix.rb +13 -0
- data/test/test_qlang.rb +25 -0
- metadata +65 -43
- data/.rspec +0 -2
- data/lib/qlang/lexer/cont_lexer.rb +0 -20
- data/lib/qlang/lexer/func_lexer.rb +0 -13
- data/lib/qlang/lexer/wrap_lexer.rb +0 -25
- data/spec/iq_spec.rb +0 -141
- data/spec/lexer/regular_expressions_spec.rb +0 -45
- data/spec/objects/function_spec.rb +0 -33
- data/spec/objects/integral_spec.rb +0 -21
- data/spec/q_lang_spec.rb +0 -47
data/lib/qlang/lexer/tokens.rb
CHANGED
@@ -6,15 +6,18 @@ module Qlang
|
|
6
6
|
FLO = /[0-9]+\.[0-9]+/
|
7
7
|
E = /e/
|
8
8
|
PI = /pi/
|
9
|
-
NUM = /(
|
9
|
+
NUM = /(?:#{FLO}|#{INT}|#{E}|#{PI})/
|
10
10
|
|
11
11
|
# FUNCTION
|
12
|
-
|
12
|
+
LPRN = /\(/
|
13
|
+
RPRN = /\)/
|
14
|
+
EMBEDDED_FUNC = /(?:sin|cos|tan|log)/
|
13
15
|
USER_FUNC = /[a-zA-Z]/
|
14
|
-
|
16
|
+
# h(x + y) != h * (x + y)
|
17
|
+
FUNCV = /(?:#{EMBEDDED_FUNC}|#{USER_FUNC})(?=#{LPRN})/
|
15
18
|
|
16
19
|
# VARIABLE
|
17
|
-
VAR = /([a-d]|[f-z])/
|
20
|
+
VAR = /(?:[a-d]|[f-z])/
|
18
21
|
#VAR_MUL2 = /(?!pi)#{VAR}{2}/
|
19
22
|
# #VAR_MUL3 = /(?!#{EMBEDDED_FUNC})#{VAR}{3}/
|
20
23
|
# # FIX:
|
@@ -30,30 +33,39 @@ module Qlang
|
|
30
33
|
MUL = /\*/
|
31
34
|
DIV = /\//
|
32
35
|
EXP = /(\*\*|\^)/
|
33
|
-
OPE = /(
|
36
|
+
OPE = /(?:#{PLS}|#{SUB}|#{MUL}|#{DIV}|#{EXP})/
|
34
37
|
|
35
|
-
VARNUM = /(
|
38
|
+
VARNUM = /(?:#{NUM}|#{VAR})/
|
36
39
|
ANYSP = ' *'
|
37
40
|
ANYSTR = /.+/
|
38
41
|
NONL = /[^\r\n]/
|
39
42
|
|
40
|
-
LPRN = /\(/
|
41
|
-
RPRN = /\)/
|
42
|
-
PRN = /(#{LPRN}|#{RPRN})/
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
PRN = /(?:#{LPRN}|#{RPRN})/
|
45
|
+
|
46
|
+
LBRCS = /\{/
|
47
|
+
RBRCS = /\}/
|
48
|
+
BRCS = /(?:#{LBRCS}|#{RBRCS})/
|
49
|
+
|
50
|
+
LBRCT = /\[/
|
51
|
+
RBRCT = /\]/
|
52
|
+
BRCT = /(?:#{LBRCT}|#{RBRCT})/
|
47
53
|
|
48
54
|
CLN = /\:/
|
49
55
|
SCLN = /;/
|
50
56
|
CMA = /\,/
|
57
|
+
EQL = /\=/
|
51
58
|
SP = / /
|
59
|
+
NLIN = /(\r|\n)/
|
60
|
+
|
61
|
+
ITGRLSYM = 'S'
|
62
|
+
# FIXIT
|
63
|
+
SCLN_OR_NELN = /(?:#{SCLN}|#{NLIN})/
|
52
64
|
|
53
65
|
# TODO: what is better
|
54
66
|
class Util
|
55
67
|
def self.string_out(str, partition)
|
56
|
-
/#{ANYSP}#{str}(
|
68
|
+
/#{ANYSP}#{str}(?:#{ANYSP}#{partition}#{ANYSP}#{str})*#{ANYSP}/
|
57
69
|
end
|
58
70
|
|
59
71
|
def self.func_call(args)
|
@@ -70,9 +82,9 @@ module Qlang
|
|
70
82
|
FUNCCV = Util.func_call(VARS_BY_CMA)
|
71
83
|
FUNCCVN = Util.func_call(VARNUMS_BY_CMA)
|
72
84
|
|
73
|
-
|
85
|
+
NUMS_BY_SP_BY_SCLN_OR_NELN = Util.string_out(NUMS_BY_SP, SCLN_OR_NELN)
|
74
86
|
|
75
|
-
FORMULA = /(
|
87
|
+
FORMULA = /(?:#{OPE}|#{FUNCV}|#{VAR}|#{NUM}|#{PRN}|#{ANYSP})+/
|
76
88
|
end
|
77
89
|
end
|
78
90
|
end
|
data/lib/qlang/parser.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
require 'qlang/api'
|
2
2
|
|
3
|
-
require 'qlang/lexer/cont_lexer'
|
4
|
-
require 'qlang/lexer/func_lexer'
|
5
|
-
|
6
3
|
require 'qlang/parser/base'
|
7
4
|
require 'qlang/parser/matrix_parser'
|
8
5
|
require 'qlang/parser/vector_parser'
|
@@ -18,43 +15,42 @@ module Qlang
|
|
18
15
|
ONEHASH = "#{ANYSP}#{SYM}#{CLN}#{ANYSP}#{VARNUM}#{ANYSP}" # sdf: 234
|
19
16
|
def execute(lexed)
|
20
17
|
time = Time.now
|
21
|
-
until lexed.token_str =~ /\A(
|
18
|
+
until lexed.token_str =~ /\A:(NLIN|R)\d+\z/
|
22
19
|
fail "I'm so sorry, something wrong. Please feel free to report this." if Time.now > time + 10
|
23
20
|
|
24
21
|
case lexed.token_str
|
25
|
-
when
|
26
|
-
|
27
|
-
token_position = $2.to_i
|
28
|
-
token_val = lexed.lexeds[token_position][token_sym]
|
22
|
+
when /:(vector)(\d+)/, /:(matrix)(\d+)/, /:(tmatrix)(\d+)/, /:(integral)(\d+)/, /:(def_func)(\d+)/, /:(differential)(\d+)/
|
23
|
+
token_els = lexed[$2][:els]
|
29
24
|
|
30
|
-
parsed = case
|
31
|
-
when
|
32
|
-
VectorParser.execute(
|
33
|
-
when
|
34
|
-
MatrixParser.execute(
|
35
|
-
when
|
36
|
-
MatrixParser.execute(
|
37
|
-
when
|
38
|
-
IntegralParser.execute(
|
39
|
-
when
|
40
|
-
FuncParser.execute(
|
25
|
+
parsed = case $1
|
26
|
+
when 'vector'
|
27
|
+
VectorParser.execute(token_els)
|
28
|
+
when 'matrix'
|
29
|
+
MatrixParser.execute(token_els)
|
30
|
+
when 'tmatrix'
|
31
|
+
MatrixParser.execute(token_els, trans: true)
|
32
|
+
when 'integral'
|
33
|
+
IntegralParser.execute(token_els)
|
34
|
+
when 'def_func'
|
35
|
+
FuncParser.execute(token_els)
|
36
|
+
when 'differential'
|
37
|
+
del_var, formula = token_els
|
38
|
+
"d/d#{del_var}(#{FormulaParser.execute(formula)})"
|
41
39
|
end
|
42
|
-
lexed.parsed!(parsed,
|
40
|
+
lexed.parsed!(parsed, $2)
|
43
41
|
|
44
|
-
when /:LPRN(\d):CONT\d:RPRN(\d)/
|
45
|
-
tokens_range = $1.to_i..$
|
46
|
-
token_val = lexed
|
42
|
+
when /:LPRN(\d+):CONT(\d+):RPRN(\d+)/
|
43
|
+
tokens_range = $1.to_i..$3.to_i
|
44
|
+
token_val = lexed[$2][:CONT]
|
47
45
|
|
48
|
-
|
49
|
-
cont = cont_lexed.values.join(' ')
|
50
|
-
lexed.parsed!(cont.parentheses, tokens_range)
|
46
|
+
lexed.parsed!(token_val.parentheses, tokens_range)
|
51
47
|
|
52
|
-
when /:
|
53
|
-
tokens_range = $1.to_i..$
|
54
|
-
token_val = lexed
|
48
|
+
when /:LBRCS(\d+):CONT(\d+):RBRCS(\d+)/
|
49
|
+
tokens_range = $1.to_i..$3.to_i
|
50
|
+
token_val = lexed[$2][:CONT]
|
55
51
|
|
56
52
|
cont = case token_val
|
57
|
-
when
|
53
|
+
when /#{ONEHASH}(#{CMA}#{ONEHASH})*/
|
58
54
|
ListParser.execute(token_val)
|
59
55
|
else
|
60
56
|
token_val
|
@@ -62,22 +58,14 @@ module Qlang
|
|
62
58
|
|
63
59
|
lexed.parsed!(cont, tokens_range)
|
64
60
|
|
65
|
-
when /:
|
61
|
+
when /:FUNCCN(\d+)/
|
66
62
|
token_val = lexed.get_value($1)
|
67
63
|
lexed.parsed!(token_val.parentheses, $1)
|
68
64
|
|
69
|
-
when /:
|
70
|
-
token_position = $1.to_i
|
71
|
-
cont = lexed.get_value(token_position)
|
72
|
-
cont =~ /(d\/d[a-zA-Z]) (.*)/
|
73
|
-
cont = "#{$1}(#{FormulaParser.execute($2)})"
|
74
|
-
# FIX: Refactor
|
75
|
-
#cont.gsub!(/(d\/d[a-zA-Z]) (.*)/, "\1(\2)")
|
76
|
-
lexed.parsed!(cont.parentheses, token_position)
|
77
|
-
when /:CONT(\d)/
|
65
|
+
when /:CONT(\d+)/
|
78
66
|
lexed.parsed!(lexed.get_value($1), $1)
|
79
67
|
end
|
80
|
-
lexed.squash!(($1.to_i)..($1.to_i+1)) if lexed.token_str =~
|
68
|
+
lexed.squash!(($1.to_i)..($1.to_i+1)) if lexed.token_str =~ /:(?:CONT|R)(\d+):(?:CONT|R)(\d+)/
|
81
69
|
end
|
82
70
|
|
83
71
|
LangEqualizer.execute(
|
@@ -1,36 +1,36 @@
|
|
1
|
+
require 'qlang/lexer/formula_lexer'
|
2
|
+
|
1
3
|
module Qlang
|
2
4
|
module Parser
|
3
|
-
# FIX:
|
4
5
|
module FormulaParser
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
ary.join(' * ')
|
23
|
-
else
|
24
|
-
ss[0]
|
6
|
+
include Lexer::Tokens
|
7
|
+
|
8
|
+
def self.execute(str)
|
9
|
+
lexed = Lexer::FormulaLexer.new(str)
|
10
|
+
time = Time.now
|
11
|
+
loop do
|
12
|
+
fail "I'm so sorry, something wrong. Please feel free to report this." if Time.now > time + 10
|
13
|
+
case lexed.token_str
|
14
|
+
when /:EXP(\d+)/
|
15
|
+
new_ope = $meta_info.lang == :ruby ? '**' : '^'
|
16
|
+
lexed.parsed!(new_ope, $1)
|
17
|
+
when /:MUL(\d+)/
|
18
|
+
sss = StringScanner.new(lexed.get_value($1))
|
19
|
+
ary = []
|
20
|
+
until sss.eos?
|
21
|
+
[/pi/, /[1-9a-z]/].each do |rgx2|
|
22
|
+
ary << sss[0] if sss.scan(rgx2)
|
25
23
|
end
|
26
|
-
result += item
|
27
|
-
break
|
28
24
|
end
|
25
|
+
parsed = ary.join(' * ')
|
26
|
+
|
27
|
+
lexed.parsed!(parsed, $1)
|
28
|
+
else
|
29
|
+
break
|
29
30
|
end
|
30
31
|
end
|
31
|
-
|
32
|
+
lexed.values.join
|
32
33
|
end
|
33
|
-
module_function :execute
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -4,8 +4,8 @@ module Qlang
|
|
4
4
|
module FuncParser
|
5
5
|
include Base
|
6
6
|
include Lexer::Tokens
|
7
|
-
def execute(
|
8
|
-
def_func, formula =
|
7
|
+
def execute(els)
|
8
|
+
def_func, formula = els[0], els[1]
|
9
9
|
def_func =~ /(#{USER_FUNC})#{LPRN}#{ANYSP}(#{VARS_BY_CMA})#{ANYSP}#{RPRN}/
|
10
10
|
FuncApi.execute($1, $2.split(' *,'), FormulaParser.execute(formula))
|
11
11
|
end
|
@@ -2,9 +2,9 @@ module Qlang
|
|
2
2
|
module Parser
|
3
3
|
module MatrixParser
|
4
4
|
include Base
|
5
|
-
def execute(
|
6
|
-
|
7
|
-
rows =
|
5
|
+
def execute(els, opts={trans: false})
|
6
|
+
trans = opts[:trans]
|
7
|
+
rows = els.first.split(/ *(?:;|\n) */).map(&:split_by_sp)
|
8
8
|
rows.all? { |row| row.count == rows.first.count }
|
9
9
|
if trans
|
10
10
|
rows = rows.transpose
|
@@ -2,10 +2,10 @@ module Qlang
|
|
2
2
|
module Parser
|
3
3
|
module VectorParser
|
4
4
|
include Base
|
5
|
-
def execute(
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def execute(els)
|
6
|
+
VectorApi.execute(
|
7
|
+
els.first.rm(/\A +/).rm(/ +\z/).split_by_sp
|
8
|
+
)
|
9
9
|
end
|
10
10
|
module_function :execute
|
11
11
|
end
|
data/lib/qlang/version.rb
CHANGED
@@ -8,6 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Qlang::VERSION
|
9
9
|
spec.authors = ['gogotanaka']
|
10
10
|
spec.email = ['mail@tanakakazuki.com']
|
11
|
+
spec.extensions = ["ext/qlang/extconf.rb"]
|
11
12
|
spec.summary = %q{Enjoy MATH!}
|
12
13
|
spec.description = %q{Enjoy MATH!}
|
13
14
|
spec.homepage = 'http://q-language.org/'
|
@@ -20,7 +21,8 @@ Gem::Specification.new do |spec|
|
|
20
21
|
|
21
22
|
spec.add_dependency "dydx", '~> 0.1.41421'
|
22
23
|
|
23
|
-
spec.add_development_dependency "bundler"
|
24
|
+
spec.add_development_dependency "bundler"
|
24
25
|
spec.add_development_dependency "rake"
|
25
|
-
spec.add_development_dependency "
|
26
|
+
spec.add_development_dependency "rake-compiler"
|
27
|
+
spec.add_development_dependency "minitest"
|
26
28
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
class TestTokens < MiniTest::Unit::TestCase
|
4
|
+
include Qlang::Lexer::Tokens
|
5
|
+
def setup
|
6
|
+
|
7
|
+
end
|
8
|
+
|
9
|
+
def full_match(rgx, str)
|
10
|
+
assert_equal(0, rgx =~ str)
|
11
|
+
assert_equal(str, $&)
|
12
|
+
end
|
13
|
+
|
14
|
+
def not_match(rgx, str)
|
15
|
+
assert_equal(nil, rgx =~ str)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_nums
|
19
|
+
full_match(NUM, '1')
|
20
|
+
full_match(NUM, '234987423')
|
21
|
+
full_match(NUM, '23423948.298743')
|
22
|
+
full_match(NUM, 'e')
|
23
|
+
full_match(NUM, 'pi')
|
24
|
+
not_match(NUM, 'a')
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_function
|
28
|
+
full_match(/[fgh]\(\w( ?, ?\w)*\) ?= ?[^\r\n]+/, 'f(x) = xy')
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_differentiate
|
32
|
+
rgx = /d\/d[a-zA-Z] .*/
|
33
|
+
full_match(rgx, 'd/dx sin(x)')
|
34
|
+
full_match(rgx, 'd/dz z^2')
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'qlang/iq'
|
2
|
+
|
3
|
+
class TestInterpreterBase < MiniTest::Unit::TestCase
|
4
|
+
# TODO: opposite
|
5
|
+
def assert_iq_equal(input, output)
|
6
|
+
assert_equal(Qlang::Iq.execute(input), output)
|
7
|
+
end
|
8
|
+
|
9
|
+
def assert_def_func(input, output)
|
10
|
+
assert_equal(Qlang::Iq.execute(input), output)
|
11
|
+
end
|
12
|
+
|
13
|
+
def assert_cal_func(input, output)
|
14
|
+
assert_equal(Qlang::Iq.execute(input), output)
|
15
|
+
reset
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
class TestDifferential < TestInterpreterBase
|
4
|
+
def setup
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_general
|
9
|
+
assert_iq_equal(
|
10
|
+
'd/dx(e ** x)',
|
11
|
+
'e ^ x'
|
12
|
+
)
|
13
|
+
|
14
|
+
assert_iq_equal(
|
15
|
+
'd/dx(x ** 2)',
|
16
|
+
'2x'
|
17
|
+
)
|
18
|
+
|
19
|
+
assert_iq_equal(
|
20
|
+
'd/dx(x * 2)',
|
21
|
+
'2'
|
22
|
+
)
|
23
|
+
|
24
|
+
assert_iq_equal(
|
25
|
+
'd/dx( sin(x) )',
|
26
|
+
'cos( x )'
|
27
|
+
)
|
28
|
+
|
29
|
+
assert_iq_equal(
|
30
|
+
'd/dx(log( x ))',
|
31
|
+
'1 / x'
|
32
|
+
)
|
33
|
+
|
34
|
+
assert_iq_equal(
|
35
|
+
'd/dx cos(x)',
|
36
|
+
'- sin( x )'
|
37
|
+
)
|
38
|
+
|
39
|
+
assert_iq_equal(
|
40
|
+
'd/dx xx',
|
41
|
+
'2x'
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
class TestFunction < TestInterpreterBase
|
4
|
+
def setup
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_general
|
9
|
+
assert_def_func('f(x, y) = x + y', 'x + y')
|
10
|
+
assert_cal_func('f( 4, 5 )', '9.0')
|
11
|
+
|
12
|
+
assert_def_func('f( x , y) = xy', 'x * y')
|
13
|
+
assert_cal_func('f( 3, 9 )', '27.0')
|
14
|
+
|
15
|
+
assert_def_func('f(x, y) = xy^2', 'x * ( y ** 2 )')
|
16
|
+
assert_cal_func('f( 3, 2 )', '12.0')
|
17
|
+
|
18
|
+
assert_def_func('f(x, y) = xy^2', 'x * ( y ** 2 )')
|
19
|
+
assert_cal_func('df/dx', 'y ^ 2')
|
20
|
+
|
21
|
+
assert_def_func('g(x) = x ^ 2', 'x ** 2')
|
22
|
+
assert_cal_func('g(2)', '4.0')
|
23
|
+
|
24
|
+
assert_def_func('h(x) = e ^ 2', 'e ** 2')
|
25
|
+
assert_cal_func('h(2)', '7.3890560989306495')
|
26
|
+
|
27
|
+
assert_def_func('h(x) = pix', 'pi * x')
|
28
|
+
assert_cal_func('h(3)', '9.42477796076938')
|
29
|
+
|
30
|
+
assert_def_func('h(x) = pie', 'pi * e')
|
31
|
+
assert_cal_func('h(2)', '8.539734222673566')
|
32
|
+
|
33
|
+
assert_def_func('h(x) = ( 1 / ( 2pi ) ^ ( 1 / 2.0 ) ) * e ^ ( - x ^ 2 / 2 )', '( ( 4503599627370496 / 6369051672525773 ) / ( pi ** 0.5 ) ) * ( e ** ( ( - ( x ** 2 ) ) / 2 ) )')
|
34
|
+
assert_cal_func('S( h(x)dx )[-oo..oo]', '1.0')
|
35
|
+
|
36
|
+
assert_def_func('f(x) = sin(x)', 'sin( x )')
|
37
|
+
assert_cal_func('f(pi)', '0.0')
|
38
|
+
|
39
|
+
assert_def_func('f(x) = cos(x)', 'cos( x )')
|
40
|
+
assert_cal_func('f(pi)', '-1.0')
|
41
|
+
|
42
|
+
assert_def_func('f(x) = log(x)', 'log( x )')
|
43
|
+
assert_cal_func('f(e)', '1.0')
|
44
|
+
end
|
45
|
+
end
|