plurimath 0.11.0 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rubocop_todo.yml +311 -58
- data/Gemfile +3 -2
- data/README.adoc +331 -15
- data/lib/plurimath/asciimath/parse.rb +6 -1
- data/lib/plurimath/asciimath/transform.rb +2 -0
- data/lib/plurimath/base_number_prefix.rb +43 -0
- data/lib/plurimath/configuration.rb +9 -1
- data/lib/plurimath/deprecation.rb +2 -1
- data/lib/plurimath/errors/configuration_error.rb +5 -1
- data/lib/plurimath/errors/deprecation_error.rb +2 -1
- data/lib/plurimath/errors/evaluation/division_by_zero_error.rb +13 -0
- data/lib/plurimath/errors/evaluation/error.rb +9 -0
- data/lib/plurimath/errors/evaluation/invalid_binding_error.rb +14 -0
- data/lib/plurimath/errors/evaluation/invalid_binding_key_error.rb +14 -0
- data/lib/plurimath/errors/evaluation/math_domain_error.rb +9 -0
- data/lib/plurimath/errors/evaluation/missing_variable_error.rb +13 -0
- data/lib/plurimath/errors/evaluation/non_finite_result_error.rb +13 -0
- data/lib/plurimath/errors/evaluation/unsupported_expression_error.rb +13 -0
- data/lib/plurimath/errors/evaluation.rb +18 -0
- data/lib/plurimath/errors/invalid_number.rb +17 -0
- data/lib/plurimath/errors/unsupported_base.rb +18 -0
- data/lib/plurimath/errors/{formatter/unsupported_locale.rb → unsupported_locale.rb} +1 -1
- data/lib/plurimath/errors.rb +9 -0
- data/lib/plurimath/formatter/numbers/base_notation.rb +55 -27
- data/lib/plurimath/formatter/numbers/format_options.rb +123 -17
- data/lib/plurimath/formatter/numbers/formatted_notation.rb +62 -0
- data/lib/plurimath/formatter/numbers/formatted_number.rb +87 -0
- data/lib/plurimath/formatter/numbers/fraction.rb +8 -17
- data/lib/plurimath/formatter/numbers/integer.rb +3 -0
- data/lib/plurimath/formatter/numbers/mathml_renderer.rb +56 -0
- data/lib/plurimath/formatter/numbers/notation_renderer.rb +58 -28
- data/lib/plurimath/formatter/numbers/number_renderer.rb +26 -13
- data/lib/plurimath/formatter/numbers/omml_renderer.rb +74 -0
- data/lib/plurimath/formatter/numbers/precision_resolver.rb +16 -3
- data/lib/plurimath/formatter/numbers/sign_renderer.rb +2 -1
- data/lib/plurimath/formatter/numbers/significant.rb +4 -2
- data/lib/plurimath/formatter/numbers/source.rb +46 -6
- data/lib/plurimath/formatter/numbers/text_renderer.rb +52 -0
- data/lib/plurimath/formatter/numbers.rb +6 -2
- data/lib/plurimath/formatter/standard.rb +6 -0
- data/lib/plurimath/formatter/supported_locales.rb +1 -1
- data/lib/plurimath/formatter.rb +0 -2
- data/lib/plurimath/html/parse.rb +5 -0
- data/lib/plurimath/html/transform.rb +26 -12
- data/lib/plurimath/latex/parse.rb +5 -0
- data/lib/plurimath/latex/transform.rb +2 -0
- data/lib/plurimath/math/core.rb +69 -14
- data/lib/plurimath/math/evaluation/evaluator.rb +147 -0
- data/lib/plurimath/math/evaluation/expression_parser.rb +215 -0
- data/lib/plurimath/math/evaluation/iteration.rb +63 -0
- data/lib/plurimath/math/evaluation.rb +13 -0
- data/lib/plurimath/math/formula.rb +9 -0
- data/lib/plurimath/math/function/abs.rb +4 -0
- data/lib/plurimath/math/function/arccos.rb +4 -0
- data/lib/plurimath/math/function/arcsin.rb +4 -0
- data/lib/plurimath/math/function/arctan.rb +4 -0
- data/lib/plurimath/math/function/ceil.rb +4 -0
- data/lib/plurimath/math/function/cos.rb +4 -0
- data/lib/plurimath/math/function/cosh.rb +4 -0
- data/lib/plurimath/math/function/cot.rb +4 -0
- data/lib/plurimath/math/function/coth.rb +4 -0
- data/lib/plurimath/math/function/csc.rb +4 -0
- data/lib/plurimath/math/function/csch.rb +4 -0
- data/lib/plurimath/math/function/exp.rb +4 -0
- data/lib/plurimath/math/function/fenced.rb +4 -0
- data/lib/plurimath/math/function/floor.rb +4 -0
- data/lib/plurimath/math/function/frac.rb +7 -0
- data/lib/plurimath/math/function/gcd.rb +9 -0
- data/lib/plurimath/math/function/lcm.rb +9 -0
- data/lib/plurimath/math/function/lg.rb +4 -0
- data/lib/plurimath/math/function/ln.rb +4 -0
- data/lib/plurimath/math/function/log.rb +19 -0
- data/lib/plurimath/math/function/max.rb +4 -0
- data/lib/plurimath/math/function/min.rb +4 -0
- data/lib/plurimath/math/function/mod.rb +15 -0
- data/lib/plurimath/math/function/overleftrightarrow.rb +2 -2
- data/lib/plurimath/math/function/power.rb +10 -0
- data/lib/plurimath/math/function/prod.rb +10 -0
- data/lib/plurimath/math/function/root.rb +7 -0
- data/lib/plurimath/math/function/sec.rb +4 -0
- data/lib/plurimath/math/function/sech.rb +4 -0
- data/lib/plurimath/math/function/sin.rb +4 -0
- data/lib/plurimath/math/function/sinh.rb +4 -0
- data/lib/plurimath/math/function/sqrt.rb +4 -0
- data/lib/plurimath/math/function/sum.rb +10 -0
- data/lib/plurimath/math/function/tan.rb +4 -0
- data/lib/plurimath/math/function/tanh.rb +4 -0
- data/lib/plurimath/math/function/text.rb +17 -0
- data/lib/plurimath/math/number.rb +44 -23
- data/lib/plurimath/math/symbols/cdot.rb +4 -0
- data/lib/plurimath/math/symbols/div.rb +4 -0
- data/lib/plurimath/math/symbols/hat.rb +4 -0
- data/lib/plurimath/math/symbols/minus.rb +4 -0
- data/lib/plurimath/math/symbols/pi.rb +5 -1
- data/lib/plurimath/math/symbols/plus.rb +4 -0
- data/lib/plurimath/math/symbols/slash.rb +4 -0
- data/lib/plurimath/math/symbols/symbol.rb +45 -0
- data/lib/plurimath/math/symbols/times.rb +4 -0
- data/lib/plurimath/math.rb +5 -1
- data/lib/plurimath/mathml/constants.rb +18 -0
- data/lib/plurimath/number_formatter.rb +63 -3
- data/lib/plurimath/omml/formula_transformation.rb +2 -1
- data/lib/plurimath/omml/translator.rb +4 -1
- data/lib/plurimath/setup/opal.rb.erb +13 -0
- data/lib/plurimath/unicode_math/parse.rb +98 -54
- data/lib/plurimath/unicode_math/parser.rb +7 -4
- data/lib/plurimath/unicode_math/parsing_rules/absence_rules.rb +33 -21
- data/lib/plurimath/unicode_math/parsing_rules/common_rules.rb +28 -16
- data/lib/plurimath/unicode_math/parsing_rules/constants_rules.rb +18 -7
- data/lib/plurimath/unicode_math/parsing_rules/masked.rb +35 -15
- data/lib/plurimath/unicode_math/parsing_rules/sub_sup.rb +98 -72
- data/lib/plurimath/unicode_math/transform.rb +1 -0
- data/lib/plurimath/utility.rb +1 -1
- data/lib/plurimath/version.rb +1 -1
- data/lib/plurimath.rb +2 -0
- metadata +24 -5
- data/lib/plurimath/errors/formatter/unsupported_base.rb +0 -21
- data/lib/plurimath/formatter/numbers/parts_renderer.rb +0 -30
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Plurimath
|
|
4
|
+
module Math
|
|
5
|
+
module Evaluation
|
|
6
|
+
# Evaluates bounded Sum/Prod iterations: parses the `i=1` lower bound,
|
|
7
|
+
# validates the integer bounds and step limit, then folds the body with
|
|
8
|
+
# the index temporarily bound.
|
|
9
|
+
class Iteration
|
|
10
|
+
def initialize(evaluator, lower, upper, body)
|
|
11
|
+
@evaluator = evaluator
|
|
12
|
+
@lower = lower
|
|
13
|
+
@upper = upper
|
|
14
|
+
@body = body
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def accumulate(initial, operation)
|
|
18
|
+
name, from = index_definition
|
|
19
|
+
to = evaluator.evaluate_node(upper)
|
|
20
|
+
validate_bounds(from, to)
|
|
21
|
+
|
|
22
|
+
(from..to).reduce(initial) do |accumulator, index|
|
|
23
|
+
accumulator.public_send(operation, body_value(name, index))
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
attr_reader :evaluator, :lower, :upper, :body
|
|
30
|
+
|
|
31
|
+
# Parses `i=1` style lower bounds into the index name and its start.
|
|
32
|
+
def index_definition
|
|
33
|
+
tokens = lower.is_a?(Formula) ? lower.value : Array(lower)
|
|
34
|
+
index = tokens.first
|
|
35
|
+
if index.is_a?(Core) && index.reserved_constant
|
|
36
|
+
evaluator.unsupported("reserved constant as iteration index")
|
|
37
|
+
end
|
|
38
|
+
name = index.is_a?(Core) ? index.variable_name : nil
|
|
39
|
+
unless name && tokens[1].is_a?(Symbols::Equal)
|
|
40
|
+
evaluator.unsupported("malformed iteration bounds")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
[name, evaluator.evaluate_nodes(tokens[2..])]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def validate_bounds(from, to)
|
|
47
|
+
unless from.is_a?(Integer) && to.is_a?(Integer)
|
|
48
|
+
raise Errors::Evaluation::MathDomainError, "iteration bounds must be integers"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
limit = Plurimath.configuration.evaluation_max_iterations
|
|
52
|
+
return if limit.nil? || (to - from + 1) <= limit
|
|
53
|
+
|
|
54
|
+
evaluator.unsupported("iteration range larger than #{limit} steps")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def body_value(name, index)
|
|
58
|
+
evaluator.with_binding(name, index) { evaluator.evaluate_node(body) }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "plurimath/errors/evaluation"
|
|
4
|
+
|
|
5
|
+
module Plurimath
|
|
6
|
+
module Math
|
|
7
|
+
module Evaluation
|
|
8
|
+
autoload :Evaluator, "#{__dir__}/evaluation/evaluator"
|
|
9
|
+
autoload :ExpressionParser, "#{__dir__}/evaluation/expression_parser"
|
|
10
|
+
autoload :Iteration, "#{__dir__}/evaluation/iteration"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -54,6 +54,15 @@ module Plurimath
|
|
|
54
54
|
object.left_right_wrapper == left_right_wrapper
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
def evaluate(bindings = {})
|
|
58
|
+
hash = bindings.to_hash if bindings.respond_to?(:to_hash)
|
|
59
|
+
unless hash.is_a?(Hash)
|
|
60
|
+
raise ArgumentError, "bindings must be a Hash-like object"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
Evaluation::Evaluator.new(self, hash).evaluate
|
|
64
|
+
end
|
|
65
|
+
|
|
57
66
|
def to_asciimath(formatter: nil, unitsml: {}, options: nil)
|
|
58
67
|
options ||= { formatter: formatter, unitsml: unitsml }.compact
|
|
59
68
|
options[:formula] ||= self
|
|
@@ -39,6 +39,10 @@ module Plurimath
|
|
|
39
39
|
"#{first_value}#{parameter_one&.to_unicodemath(options: options)}#{second_value}"
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
def evaluate(evaluator)
|
|
43
|
+
evaluator.evaluate_node(parameter_one).ceil
|
|
44
|
+
end
|
|
45
|
+
|
|
42
46
|
def line_breaking(obj)
|
|
43
47
|
parameter_one.line_breaking(obj)
|
|
44
48
|
if obj.value_exist?
|
|
@@ -8,6 +8,10 @@ module Plurimath
|
|
|
8
8
|
false
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def evaluate(evaluator)
|
|
12
|
+
::Math.exp(evaluator.evaluate_node(parameter_one))
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
def to_omml_without_math_tag(display_style, options:)
|
|
12
16
|
array = []
|
|
13
17
|
array << r_element("exp", rpr_tag: false) unless hide_function_name
|
|
@@ -116,6 +116,10 @@ module Plurimath
|
|
|
116
116
|
"#{unicode_open_paren(options: options)}#{fenced_value}#{unicode_close_paren(options: options)}"
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
+
def evaluate(evaluator)
|
|
120
|
+
evaluator.evaluate_nodes(parameter_two)
|
|
121
|
+
end
|
|
122
|
+
|
|
119
123
|
def to_asciimath_math_zone(spacing, last = false, indent = true,
|
|
120
124
|
options:)
|
|
121
125
|
filtered_values(parameter_two,
|
|
@@ -36,6 +36,10 @@ module Plurimath
|
|
|
36
36
|
"#{first_value}#{parameter_one&.to_unicodemath(options: options)}#{second_value}"
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
def evaluate(evaluator)
|
|
40
|
+
evaluator.evaluate_node(parameter_one).floor
|
|
41
|
+
end
|
|
42
|
+
|
|
39
43
|
def line_breaking(obj)
|
|
40
44
|
parameter_one.line_breaking(obj)
|
|
41
45
|
if obj.value_exist?
|
|
@@ -89,6 +89,13 @@ module Plurimath
|
|
|
89
89
|
"#{first_value}∕#{second_value}" if self.options&.key?(:ldiv)
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
+
def evaluate(evaluator)
|
|
93
|
+
evaluator.divide(
|
|
94
|
+
evaluator.evaluate_node(parameter_one),
|
|
95
|
+
evaluator.evaluate_node(parameter_two),
|
|
96
|
+
)
|
|
97
|
+
end
|
|
98
|
+
|
|
92
99
|
def line_breaking(obj)
|
|
93
100
|
parameter_one&.line_breaking(obj)
|
|
94
101
|
if obj.value_exist?
|
|
@@ -8,6 +8,15 @@ module Plurimath
|
|
|
8
8
|
false
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def evaluate(evaluator)
|
|
12
|
+
values = evaluator.function_arguments(parameter_one)
|
|
13
|
+
unless values.all?(Integer)
|
|
14
|
+
raise Errors::Evaluation::MathDomainError, "gcd requires integer arguments"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
values.reduce(:gcd)
|
|
18
|
+
end
|
|
19
|
+
|
|
11
20
|
def to_omml_without_math_tag(display_style, options:)
|
|
12
21
|
array = []
|
|
13
22
|
array << r_element("gcd", rpr_tag: false) unless hide_function_name
|
|
@@ -8,6 +8,15 @@ module Plurimath
|
|
|
8
8
|
false
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def evaluate(evaluator)
|
|
12
|
+
values = evaluator.function_arguments(parameter_one)
|
|
13
|
+
unless values.all?(Integer)
|
|
14
|
+
raise Errors::Evaluation::MathDomainError, "lcm requires integer arguments"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
values.reduce(:lcm)
|
|
18
|
+
end
|
|
19
|
+
|
|
11
20
|
def to_asciimath(options:)
|
|
12
21
|
first_value = " #{asciimath_value(options: options)}" if parameter_one
|
|
13
22
|
"lcm#{first_value}"
|
|
@@ -8,6 +8,10 @@ module Plurimath
|
|
|
8
8
|
false
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def evaluate(evaluator)
|
|
12
|
+
::Math.log10(evaluator.evaluate_node(parameter_one))
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
def to_omml_without_math_tag(display_style, options:)
|
|
12
16
|
array = []
|
|
13
17
|
array << r_element("lg", rpr_tag: false) unless hide_function_name
|
|
@@ -8,6 +8,10 @@ module Plurimath
|
|
|
8
8
|
false
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def evaluate(evaluator)
|
|
12
|
+
::Math.log(evaluator.evaluate_node(parameter_one))
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
def to_omml_without_math_tag(display_style, options:)
|
|
12
16
|
array = []
|
|
13
17
|
array = r_element("ln", rpr_tag: false) unless hide_function_name
|
|
@@ -10,6 +10,25 @@ module Plurimath
|
|
|
10
10
|
second_value: "supscript",
|
|
11
11
|
}.freeze
|
|
12
12
|
|
|
13
|
+
# `log` carries its base/exponent but not its argument; the parser
|
|
14
|
+
# binds the following fenced group via #evaluate_with_argument, so a
|
|
15
|
+
# bare `log` is unsupported.
|
|
16
|
+
def evaluate(evaluator)
|
|
17
|
+
evaluator.unsupported(self)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def evaluate_with_argument(evaluator, argument)
|
|
21
|
+
base = parameter_one ? evaluator.evaluate_node(parameter_one) : 10
|
|
22
|
+
unless base.positive? && base != 1
|
|
23
|
+
raise Errors::Evaluation::MathDomainError,
|
|
24
|
+
"log base must be a positive number other than 1"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
result = ::Math.log(evaluator.evaluate_node(argument), base)
|
|
28
|
+
result = evaluator.power(result, evaluator.evaluate_node(parameter_two)) if parameter_two
|
|
29
|
+
result
|
|
30
|
+
end
|
|
31
|
+
|
|
13
32
|
def to_asciimath(options:)
|
|
14
33
|
if parameter_one
|
|
15
34
|
first_value = "_#{wrapped(parameter_one,
|
|
@@ -8,6 +8,10 @@ module Plurimath
|
|
|
8
8
|
false
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def evaluate(evaluator)
|
|
12
|
+
evaluator.function_arguments(parameter_one).max
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
def to_omml_without_math_tag(display_style, options:)
|
|
12
16
|
array = []
|
|
13
17
|
array << r_element("max", rpr_tag: false) unless hide_function_name
|
|
@@ -8,6 +8,10 @@ module Plurimath
|
|
|
8
8
|
false
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def evaluate(evaluator)
|
|
12
|
+
evaluator.function_arguments(parameter_one).min
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
def to_omml_without_math_tag(display_style, options:)
|
|
12
16
|
array = []
|
|
13
17
|
array << r_element("min", rpr_tag: false) unless hide_function_name
|
|
@@ -10,6 +10,21 @@ module Plurimath
|
|
|
10
10
|
second_value: "argument",
|
|
11
11
|
}.freeze
|
|
12
12
|
|
|
13
|
+
def evaluate(evaluator)
|
|
14
|
+
evaluator.modulo(
|
|
15
|
+
evaluator.evaluate_node(parameter_one),
|
|
16
|
+
evaluator.evaluate_node(parameter_two),
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# `-a mod b` negates the dividend, matching `(-a) mod b`.
|
|
21
|
+
def evaluate_negated(evaluator)
|
|
22
|
+
evaluator.modulo(
|
|
23
|
+
-evaluator.evaluate_node(parameter_one),
|
|
24
|
+
evaluator.evaluate_node(parameter_two),
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
13
28
|
def to_asciimath(options:)
|
|
14
29
|
first_value = parameter_one&.to_asciimath(options: options)
|
|
15
30
|
second_value = parameter_two&.to_asciimath(options: options)
|
|
@@ -14,7 +14,7 @@ module Plurimath
|
|
|
14
14
|
def to_mathml_without_math_tag(intent, options:)
|
|
15
15
|
mover = ox_element("mover")
|
|
16
16
|
first_value = parameter_one&.to_mathml_without_math_tag(intent,
|
|
17
|
-
|
|
17
|
+
options: options)
|
|
18
18
|
if attributes && attributes[:accent]
|
|
19
19
|
mover[:accent] =
|
|
20
20
|
attributes[:accent]
|
|
@@ -36,7 +36,7 @@ module Plurimath
|
|
|
36
36
|
else
|
|
37
37
|
symbol = Symbols::Symbol.new("\u20e1")
|
|
38
38
|
Overset.new(parameter_one, symbol).to_omml_without_math_tag(true,
|
|
39
|
-
|
|
39
|
+
options: options)
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|
|
@@ -80,6 +80,16 @@ module Plurimath
|
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
# Nested Power trees evaluate literally: `Power(Power(2, 3), 2)` is
|
|
84
|
+
# `(2^3)^2`, whether it came from explicit MathML nesting or a
|
|
85
|
+
# left-nested source chain.
|
|
86
|
+
def evaluate(evaluator)
|
|
87
|
+
evaluator.power(
|
|
88
|
+
evaluator.evaluate_node(parameter_one),
|
|
89
|
+
evaluator.evaluate_node(parameter_two),
|
|
90
|
+
)
|
|
91
|
+
end
|
|
92
|
+
|
|
83
93
|
def line_breaking(obj)
|
|
84
94
|
parameter_one&.line_breaking(obj)
|
|
85
95
|
if obj.value_exist?
|
|
@@ -12,6 +12,16 @@ module Plurimath
|
|
|
12
12
|
second_value: "supscript",
|
|
13
13
|
}.freeze
|
|
14
14
|
|
|
15
|
+
def evaluate(evaluator)
|
|
16
|
+
if parameter_one.nil? || parameter_two.nil? || parameter_three.nil?
|
|
17
|
+
evaluator.unsupported(self)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Evaluation::Iteration
|
|
21
|
+
.new(evaluator, parameter_one, parameter_two, parameter_three)
|
|
22
|
+
.accumulate(1, :*)
|
|
23
|
+
end
|
|
24
|
+
|
|
15
25
|
def initialize(parameter_one = nil,
|
|
16
26
|
parameter_two = nil,
|
|
17
27
|
parameter_three = nil,
|
|
@@ -51,6 +51,13 @@ module Plurimath
|
|
|
51
51
|
second_value = parameter_two.to_unicodemath(options: options) if parameter_two
|
|
52
52
|
"√(#{first_value}&#{second_value})"
|
|
53
53
|
end
|
|
54
|
+
|
|
55
|
+
def evaluate(evaluator)
|
|
56
|
+
evaluator.power(
|
|
57
|
+
evaluator.evaluate_node(parameter_two),
|
|
58
|
+
evaluator.divide(1.0, evaluator.evaluate_node(parameter_one)),
|
|
59
|
+
)
|
|
60
|
+
end
|
|
54
61
|
end
|
|
55
62
|
end
|
|
56
63
|
end
|
|
@@ -13,6 +13,16 @@ module Plurimath
|
|
|
13
13
|
third_value: "term",
|
|
14
14
|
}.freeze
|
|
15
15
|
|
|
16
|
+
def evaluate(evaluator)
|
|
17
|
+
if parameter_one.nil? || parameter_two.nil? || parameter_three.nil?
|
|
18
|
+
evaluator.unsupported(self)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Evaluation::Iteration
|
|
22
|
+
.new(evaluator, parameter_one, parameter_two, parameter_three)
|
|
23
|
+
.accumulate(0, :+)
|
|
24
|
+
end
|
|
25
|
+
|
|
16
26
|
def initialize(parameter_one = nil,
|
|
17
27
|
parameter_two = nil,
|
|
18
28
|
parameter_three = nil,
|
|
@@ -66,6 +66,23 @@ module Plurimath
|
|
|
66
66
|
false
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
+
# OMML emits variable text runs as Text nodes. Only a plain, non-blank
|
|
70
|
+
# string names a variable; rich content (arrays/formulas) or a missing
|
|
71
|
+
# value does not.
|
|
72
|
+
def variable_name
|
|
73
|
+
return unless parameter_one.is_a?(String)
|
|
74
|
+
|
|
75
|
+
stripped = parameter_one.strip
|
|
76
|
+
stripped unless stripped.empty?
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def evaluate(evaluator)
|
|
80
|
+
name = variable_name
|
|
81
|
+
evaluator.unsupported(self) unless name
|
|
82
|
+
|
|
83
|
+
evaluator.value_for(name)
|
|
84
|
+
end
|
|
85
|
+
|
|
69
86
|
def to_asciimath_math_zone(spacing, _, _, options:)
|
|
70
87
|
"#{spacing}#{to_asciimath(options: options)} text\n"
|
|
71
88
|
end
|