plurimath 0.8.15 → 0.8.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/gen_docs.yml +10 -8
  3. data/README.adoc +4 -0
  4. data/Rakefile +55 -8
  5. data/intent_supported_classes.adoc +82 -0
  6. data/lib/plurimath/formatter/number_formatter.rb +6 -6
  7. data/lib/plurimath/formatter/numeric_formatter.rb +6 -8
  8. data/lib/plurimath/formatter/standard.rb +5 -1
  9. data/lib/plurimath/formatter.rb +14 -0
  10. data/lib/plurimath/latex/parse.rb +2 -1
  11. data/lib/plurimath/math/core.rb +2 -2
  12. data/lib/plurimath/math/formula.rb +26 -6
  13. data/lib/plurimath/math/function/abs.rb +5 -1
  14. data/lib/plurimath/math/function/fenced.rb +19 -7
  15. data/lib/plurimath/math/function/frac.rb +8 -1
  16. data/lib/plurimath/math/function/inf.rb +5 -1
  17. data/lib/plurimath/math/function/int.rb +5 -1
  18. data/lib/plurimath/math/function/intent.rb +6 -2
  19. data/lib/plurimath/math/function/lim.rb +5 -1
  20. data/lib/plurimath/math/function/nary.rb +13 -1
  21. data/lib/plurimath/math/function/oint.rb +5 -1
  22. data/lib/plurimath/math/function/prod.rb +5 -1
  23. data/lib/plurimath/math/function/sum.rb +5 -1
  24. data/lib/plurimath/math/function/table/array.rb +1 -1
  25. data/lib/plurimath/math/function/table/bmatrix.rb +1 -1
  26. data/lib/plurimath/math/function/table/cases.rb +2 -2
  27. data/lib/plurimath/math/function/table/eqarray.rb +2 -2
  28. data/lib/plurimath/math/function/table/pmatrix.rb +1 -1
  29. data/lib/plurimath/math/function/table/vmatrix.rb +1 -1
  30. data/lib/plurimath/math/function/table.rb +12 -0
  31. data/lib/plurimath/math/function/unary_function.rb +5 -1
  32. data/lib/plurimath/math/symbols/bigwedge.rb +4 -0
  33. data/lib/plurimath/math/symbols/cap.rb +0 -4
  34. data/lib/plurimath/math/symbols/clockoint.rb +1 -1
  35. data/lib/plurimath/math/symbols/cntclockoint.rb +1 -1
  36. data/lib/plurimath/math/symbols/coprod.rb +1 -1
  37. data/lib/plurimath/math/symbols/dd.rb +4 -0
  38. data/lib/plurimath/math/symbols/dint.rb +4 -0
  39. data/lib/plurimath/math/symbols/duni.rb +4 -0
  40. data/lib/plurimath/math/symbols/ii.rb +4 -0
  41. data/lib/plurimath/math/symbols/iiiint.rb +1 -1
  42. data/lib/plurimath/math/symbols/iiint.rb +4 -0
  43. data/lib/plurimath/math/symbols/iint.rb +1 -1
  44. data/lib/plurimath/math/symbols/intclockwise.rb +1 -1
  45. data/lib/plurimath/math/symbols/intercal.rb +4 -0
  46. data/lib/plurimath/math/symbols/jj.rb +4 -0
  47. data/lib/plurimath/math/symbols/oiiint.rb +1 -1
  48. data/lib/plurimath/math/symbols/oiint.rb +1 -1
  49. data/lib/plurimath/math/symbols/oint.rb +1 -1
  50. data/lib/plurimath/math/symbols/upcase_dd.rb +4 -0
  51. data/lib/plurimath/math.rb +1 -0
  52. data/lib/plurimath/mathml/transform.rb +2 -0
  53. data/lib/plurimath/number_formatter.rb +5 -5
  54. data/lib/plurimath/unitsml.rb +3 -1
  55. data/lib/plurimath/utility/intent_encoding.rb +21 -21
  56. data/lib/plurimath/version.rb +1 -1
  57. metadata +4 -2
@@ -124,6 +124,17 @@ module Plurimath
124
124
  end
125
125
  end
126
126
 
127
+ def intent_names
128
+ @@names ||= Symbols::Symbol.descendants.map.with_object({}) do |symbol, hash|
129
+ sym_instance = symbol.new
130
+ next unless sym_instance.is_nary_symbol?
131
+
132
+ intent_name = sym_instance.nary_intent_name
133
+ next pp symbol.const_source_location(:INPUT) if intent_name.nil?
134
+ hash[intent_name.gsub(/\s|-/, '_').to_sym] = intent_name
135
+ end
136
+ end
137
+
127
138
  protected
128
139
 
129
140
  def chr_value(narypr, options:)
@@ -197,8 +208,9 @@ module Plurimath
197
208
  end
198
209
  end
199
210
 
211
+ # Function calling intent name for a specific symbol
200
212
  def intent_name
201
- return "n-ary" unless parameter_one&.is_nary_symbol?
213
+ return ":n-ary" unless parameter_one&.is_nary_symbol?
202
214
 
203
215
  parameter_one.nary_intent_name
204
216
  end
@@ -119,6 +119,10 @@ module Plurimath
119
119
  true
120
120
  end
121
121
 
122
+ def intent_names
123
+ { name: ":contour integral"}
124
+ end
125
+
122
126
  private
123
127
 
124
128
  def ternary_intentify(tag, intent)
@@ -126,7 +130,7 @@ module Plurimath
126
130
  tag,
127
131
  intent,
128
132
  func_name: :naryand,
129
- intent_name: "contour integral",
133
+ intent_name: intent_names[:name],
130
134
  )
131
135
  end
132
136
  end
@@ -116,6 +116,10 @@ module Plurimath
116
116
  true
117
117
  end
118
118
 
119
+ def intent_names
120
+ { name: ":product" }
121
+ end
122
+
119
123
  private
120
124
 
121
125
  def sup_value(options:)
@@ -152,7 +156,7 @@ module Plurimath
152
156
  tag,
153
157
  intent,
154
158
  func_name: :naryand,
155
- intent_name: :product,
159
+ intent_name: intent_names[:name],
156
160
  )
157
161
  end
158
162
  end
@@ -122,6 +122,10 @@ module Plurimath
122
122
  true
123
123
  end
124
124
 
125
+ def intent_names
126
+ { name: ":sum"}
127
+ end
128
+
125
129
  private
126
130
 
127
131
  def sum_tag
@@ -138,7 +142,7 @@ module Plurimath
138
142
  tag,
139
143
  intent,
140
144
  func_name: :naryand,
141
- intent_name: :sum,
145
+ intent_name: intent_names[:name],
142
146
  )
143
147
  end
144
148
  end
@@ -42,7 +42,7 @@ module Plurimath
42
42
  def attributes(intent)
43
43
  return table_attribute unless intent
44
44
 
45
- table_attribute.merge(intent: ":equations")
45
+ table_attribute.merge(intent: intent_names[:equations])
46
46
  end
47
47
  end
48
48
  end
@@ -54,7 +54,7 @@ module Plurimath
54
54
  return {} unless intent
55
55
 
56
56
  {
57
- intent: capital_bmatrix? ? ":curly-braced-matrix" : ":bracketed-matrix"
57
+ intent: intent_names.dig(capital_bmatrix? ? :curly_braced_matrix : :bracketed_matrix)
58
58
  }
59
59
  end
60
60
  end
@@ -22,7 +22,7 @@ module Plurimath
22
22
  def to_mathml_without_math_tag(intent, **)
23
23
  table_tag = super
24
24
  set_table_intent(table_tag) if intent
25
- table_tag.attributes["intent"] = ":equations" if intent
25
+ table_tag.attributes["intent"] = intent_names[:equations] if intent
26
26
  table_tag
27
27
  end
28
28
 
@@ -30,7 +30,7 @@ module Plurimath
30
30
 
31
31
  def set_table_intent(tag)
32
32
  table = tag.nodes.find { |tag| tag.name == "mtable" }
33
- table["intent"] = ":cases"
33
+ table["intent"] = intent_names[:cases]
34
34
  end
35
35
  end
36
36
  end
@@ -22,7 +22,7 @@ module Plurimath
22
22
  def to_mathml_without_math_tag(intent, **)
23
23
  matrix = super
24
24
  set_table_intent(matrix) if intent
25
- matrix["intent"] = ":equations" if intent
25
+ matrix["intent"] = intent_names[:equations] if intent
26
26
  matrix
27
27
  end
28
28
 
@@ -32,7 +32,7 @@ module Plurimath
32
32
  matrix = tag.nodes.find { |tag| tag.name == "mtable" }
33
33
  return unless matrix
34
34
 
35
- matrix["intent"] = ":cases"
35
+ matrix["intent"] = intent_names[:cases]
36
36
  end
37
37
  end
38
38
  end
@@ -25,7 +25,7 @@ module Plurimath
25
25
 
26
26
  def to_mathml_without_math_tag(intent, **)
27
27
  matrix = super
28
- matrix["intent"] = ":parenthesized-matrix" if intent
28
+ matrix["intent"] = intent_names[:parenthesized_matrix] if intent
29
29
  matrix
30
30
  end
31
31
  end
@@ -40,7 +40,7 @@ module Plurimath
40
40
  end
41
41
 
42
42
  def intent_attr_value(intent)
43
- capital_vmatrix? ? ":normed-matrix" : ":determinant"
43
+ intent_names.dig(capital_vmatrix? ? :normed_matrix : :determinant)
44
44
  end
45
45
  end
46
46
  end
@@ -125,6 +125,18 @@ module Plurimath
125
125
  ]
126
126
  end
127
127
 
128
+ def intent_names
129
+ {
130
+ curly_braced_matrix: ":curly-braced-matrix",
131
+ parenthesized_matrix: ":parenthesized-matrix",
132
+ bracketed_matrix: ":bracketed-matrix",
133
+ normed_matrix: ":normed-matrix",
134
+ determinant: ":determinant",
135
+ equations: ":equations",
136
+ cases: ":cases",
137
+ }
138
+ end
139
+
128
140
  protected
129
141
 
130
142
  def mathml_parenthesis(field, intent, options:)
@@ -35,7 +35,7 @@ module Plurimath
35
35
  new_arr += mathml_value(intent, options: options)
36
36
  mrow = ox_element("mrow")
37
37
  Utility.update_nodes(mrow, new_arr)
38
- intentify(mrow, intent, func_name: :function, intent_name: :function)
38
+ intentify(mrow, intent, func_name: :function, intent_name: intent_names[:name])
39
39
  else
40
40
  new_arr.first
41
41
  end
@@ -153,6 +153,10 @@ module Plurimath
153
153
  !parameter_one
154
154
  end
155
155
 
156
+ def intent_names
157
+ { name: ":function" }
158
+ end
159
+
156
160
  protected
157
161
 
158
162
  def asciimath_value(options:)
@@ -36,6 +36,10 @@ module Plurimath
36
36
  "⋀"
37
37
  end
38
38
 
39
+ def nary_intent_name
40
+ ":n-ary"
41
+ end
42
+
39
43
  def is_nary_symbol?
40
44
  true
41
45
  end
@@ -35,10 +35,6 @@ module Plurimath
35
35
  def to_html(**)
36
36
  "∩"
37
37
  end
38
-
39
- def is_nary_symbol?
40
- true
41
- end
42
38
  end
43
39
  end
44
40
  end
@@ -41,7 +41,7 @@ module Plurimath
41
41
  end
42
42
 
43
43
  def nary_intent_name
44
- "n-ary"
44
+ ":n-ary"
45
45
  end
46
46
 
47
47
  def tag_name
@@ -41,7 +41,7 @@ module Plurimath
41
41
  end
42
42
 
43
43
  def nary_intent_name
44
- "anticlockwise contour integral"
44
+ ":anticlockwise contour integral"
45
45
  end
46
46
 
47
47
  def tag_name
@@ -41,7 +41,7 @@ module Plurimath
41
41
  end
42
42
 
43
43
  def nary_intent_name
44
- "coproduct"
44
+ ":coproduct"
45
45
  end
46
46
  end
47
47
  end
@@ -37,6 +37,10 @@ module Plurimath
37
37
  "ⅆ"
38
38
  end
39
39
 
40
+ def intent_names
41
+ { name: encoded }
42
+ end
43
+
40
44
  private
41
45
 
42
46
  def encoded
@@ -36,6 +36,10 @@ module Plurimath
36
36
  "⋂"
37
37
  end
38
38
 
39
+ def nary_intent_name
40
+ ":n-ary"
41
+ end
42
+
39
43
  def is_nary_symbol?
40
44
  true
41
45
  end
@@ -36,6 +36,10 @@ module Plurimath
36
36
  "⋃"
37
37
  end
38
38
 
39
+ def nary_intent_name
40
+ ":n-ary"
41
+ end
42
+
39
43
  def is_nary_symbol?
40
44
  true
41
45
  end
@@ -37,6 +37,10 @@ module Plurimath
37
37
  "ⅈ"
38
38
  end
39
39
 
40
+ def intent_names
41
+ { name: encoded }
42
+ end
43
+
40
44
  private
41
45
 
42
46
  def encoded
@@ -41,7 +41,7 @@ module Plurimath
41
41
  end
42
42
 
43
43
  def nary_intent_name
44
- "quadruple integral"
44
+ ":quadruple integral"
45
45
  end
46
46
  end
47
47
  end
@@ -36,6 +36,10 @@ module Plurimath
36
36
  "∭"
37
37
  end
38
38
 
39
+ def nary_intent_name
40
+ ":triple integral"
41
+ end
42
+
39
43
  def is_nary_symbol?
40
44
  true
41
45
  end
@@ -41,7 +41,7 @@ module Plurimath
41
41
  end
42
42
 
43
43
  def nary_intent_name
44
- "double integral"
44
+ ":double integral"
45
45
  end
46
46
  end
47
47
  end
@@ -41,7 +41,7 @@ module Plurimath
41
41
  end
42
42
 
43
43
  def nary_intent_name
44
- "clockwise contour integral"
44
+ ":clockwise contour integral"
45
45
  end
46
46
 
47
47
  def tag_name
@@ -36,6 +36,10 @@ module Plurimath
36
36
  def to_html(**)
37
37
  "⊺"
38
38
  end
39
+
40
+ def intent_names
41
+ { name: "transpose" }
42
+ end
39
43
  end
40
44
  end
41
45
  end
@@ -37,6 +37,10 @@ module Plurimath
37
37
  "ⅉ"
38
38
  end
39
39
 
40
+ def intent_names
41
+ { name: encoded }
42
+ end
43
+
40
44
  private
41
45
 
42
46
  def encoded
@@ -41,7 +41,7 @@ module Plurimath
41
41
  end
42
42
 
43
43
  def nary_intent_name
44
- "volume integral"
44
+ ":volume integral"
45
45
  end
46
46
 
47
47
  def tag_name
@@ -41,7 +41,7 @@ module Plurimath
41
41
  end
42
42
 
43
43
  def nary_intent_name
44
- "surface integral"
44
+ ":surface integral"
45
45
  end
46
46
 
47
47
  def tag_name
@@ -41,7 +41,7 @@ module Plurimath
41
41
  end
42
42
 
43
43
  def nary_intent_name
44
- "contour integral"
44
+ ":contour integral"
45
45
  end
46
46
 
47
47
  def tag_name
@@ -37,6 +37,10 @@ module Plurimath
37
37
  "ⅅ"
38
38
  end
39
39
 
40
+ def intent_names
41
+ { name: encoded }
42
+ end
43
+
40
44
  private
41
45
 
42
46
  def encoded
@@ -8,6 +8,7 @@ require_relative "html"
8
8
  require_relative "latex"
9
9
  require_relative "unitsml"
10
10
  require_relative "number_formatter"
11
+ require_relative "formatter/standard"
11
12
  require_relative "math/core"
12
13
  require_relative "math/number"
13
14
  require_relative "math/symbols"
@@ -245,6 +245,8 @@ module Plurimath
245
245
  elsif Constants::CLASSES.any?(mover&.last&.class_name)
246
246
  mover.last.parameter_one = mover.shift if mover.length > 1
247
247
  mover.last
248
+ elsif mover&.last&.class_name == "period" && mover.length == 2
249
+ Math::Function::Dot.new(mover[0])
248
250
  else
249
251
  Math::Function::Overset.new(mover[1], mover[0])
250
252
  end
@@ -1,17 +1,17 @@
1
- require_relative "formatter/numeric_formatter"
2
- require_relative "formatter/supported_locales"
1
+ require_relative "formatter"
3
2
 
4
3
  module Plurimath
5
4
  class NumberFormatter
6
- attr_accessor :locale, :localize_number, :localizer_symbols
5
+ attr_accessor :locale, :localize_number, :localizer_symbols, :precision
7
6
 
8
- def initialize(locale = "en", localize_number: nil, localizer_symbols: {})
7
+ def initialize(locale = "en", localize_number: nil, localizer_symbols: {}, precision: nil)
9
8
  @locale = supported_locale(locale)
10
9
  @localize_number = localize_number
11
10
  @localizer_symbols = localizer_symbols
11
+ @precision = precision
12
12
  end
13
13
 
14
- def localized_number(number_string, locale: @locale, precision: nil, format: {})
14
+ def localized_number(number_string, locale: @locale, precision: @precision, format: {})
15
15
  prev_symbols = symbols(locale).dup
16
16
  Formatter::NumericFormatter.new(
17
17
  supported_locale(locale),
@@ -11,9 +11,11 @@ module Plurimath
11
11
  end
12
12
 
13
13
  def to_formula
14
- formula = ::Unitsml.parse(text).to_plurimath
14
+ unitsml = ::Unitsml.parse(text)
15
+ formula = unitsml.to_plurimath
15
16
  formula.unitsml = true
16
17
  formula.input_string = text
18
+ formula.unitsml_xml = unitsml.to_xml
17
19
  formula
18
20
  end
19
21
 
@@ -19,21 +19,21 @@ module Plurimath
19
19
  # Intent common code end
20
20
 
21
21
  # Naryand intent begin
22
- def naryand_intent(field, intent_name)
23
- return nary_intent(field, intent_name) if field.name == "mrow"
22
+ def naryand_intent(field, intent_name, options)
23
+ return nary_intent(field, intent_name, options) if field.name == "mrow"
24
24
 
25
25
  base, power = power_base_intent(field)
26
26
  base, power = power_or_base_intent(field) unless base && power
27
- field["intent"] = ":#{intent_name}(#{base},#{power})"
27
+ field["intent"] = "#{intent_name}(#{base},#{power})"
28
28
  field
29
29
  end
30
30
 
31
- def nary_intent(field, intent_name)
31
+ def nary_intent(field, intent_name, _)
32
32
  sub_sup = field.nodes[0]
33
33
  base, power = power_base_intent(sub_sup)
34
34
  base, power = power_or_base_intent(sub_sup) unless base || power
35
35
  naryand = node_value(field.nodes[1], "naryand")
36
- field["intent"] = ":#{intent_name}(#{base},#{power},#{naryand})"
36
+ field["intent"] = "#{intent_name}(#{base},#{power},#{naryand})"
37
37
  field
38
38
  end
39
39
  # Naryand intent end
@@ -57,14 +57,14 @@ module Plurimath
57
57
  # SubSup intent end
58
58
 
59
59
  # Function intent begin
60
- def function_intent(tag, intent_name = "function")
61
- tag.attributes["intent"] = ":#{intent_name}"
60
+ def function_intent(tag, intent_name = ":function", _)
61
+ tag.attributes["intent"] = intent_name
62
62
  tag
63
63
  end
64
64
  # Function intent end
65
65
 
66
66
  # Binomial fraction intent begin
67
- def binomial_fraction_intent(tag, intent_name)
67
+ def binomial_fraction_intent(tag, intent_name, _)
68
68
  numerator = node_value(tag.nodes[1].nodes[0], "t")
69
69
  denominator = node_value(tag.nodes[1].nodes[1], "b")
70
70
  tag["intent"] = "#{intent_name}(#{numerator},#{denominator})"
@@ -73,30 +73,31 @@ module Plurimath
73
73
  # Binomial fraction intent end
74
74
 
75
75
  # Interval fence intent begin
76
- def interval_fence_intent(tag, intent_name)
77
- return function_intent(tag, intent_name) if intent_name == "fenced"
78
- return binomial_fraction_intent(tag, intent_name) if intent_name == "binomial-coefficient"
76
+ def interval_fence_intent(tag, intent_name, options)
77
+ intent = options[intent_name]
78
+ return function_intent(tag, intent, options) if intent_name == :fenced
79
+ return binomial_fraction_intent(tag, intent, options) if intent_name == :binomial_coefficient
79
80
 
80
81
  first_value = fence_node_value(tag.nodes[1], "a")
81
82
  second_value = fence_node_value(tag.nodes[3], "b")
82
- tag["intent"] = "#{intent_name}(#{first_value},#{second_value})"
83
+ tag["intent"] = "#{intent}(#{first_value},#{second_value})"
83
84
  tag
84
85
  end
85
86
  # Interval fence intent end
86
87
 
87
88
  # Frac derivative intent begin
88
- def frac_intent(tag, intent_name)
89
+ def frac_intent(tag, _, options)
89
90
  num = tag.nodes[0]
90
91
  den = tag.nodes[1]
91
- return partial_derivative(tag) if partial_derivative?(num, den)
92
- return derivative(tag) if derivative?(num, den)
92
+ return partial_derivative(tag, options[:partial_derivative]) if partial_derivative?(num, den)
93
+ return derivative(tag, options[:derivative]) if derivative?(num, den)
93
94
 
94
95
  tag
95
96
  end
96
97
  # Frac derivative intent end
97
98
 
98
99
  # Abs intent begin
99
- def abs_intent(tag, intent_name)
100
+ def abs_intent(tag, intent_name, _options)
100
101
  tag["intent"] = "#{intent_name}(#{node_value(tag.nodes[1], 'a')})"
101
102
  tag
102
103
  end
@@ -156,9 +157,9 @@ module Plurimath
156
157
  found_node&.nodes[1]
157
158
  end
158
159
 
159
- def partial_derivative(node)
160
+ def partial_derivative(node, intent_name)
160
161
  intent = "(#{partial_arg(node)},#{f_arg(node&.nodes[0])},#{den_arg(node&.nodes[1])})"
161
- node["intent"] = ":partial-derivative#{intent}"
162
+ node["intent"] = intent_name + intent
162
163
  node
163
164
  end
164
165
 
@@ -255,11 +256,10 @@ module Plurimath
255
256
  node.nodes.length >= 2
256
257
  end
257
258
 
258
- def derivative(node)
259
+ def derivative(node, intent_name)
259
260
  num = node.nodes[0]
260
261
  den = node.nodes[1]
261
- intent_name = ":derivative(1,#{num_arg(num)},#{derivative_den_arg(den)})"
262
- node["intent"] = intent_name
262
+ node["intent"] = "#{intent_name}(1,#{num_arg(num)},#{derivative_den_arg(den)})"
263
263
  node
264
264
  end
265
265
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plurimath
4
- VERSION = "0.8.15"
4
+ VERSION = "0.8.17"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plurimath
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.15
4
+ version: 0.8.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-11 00:00:00.000000000 Z
11
+ date: 2024-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -95,6 +95,7 @@ files:
95
95
  - bin/console
96
96
  - bin/setup
97
97
  - exe/plurimath
98
+ - intent_supported_classes.adoc
98
99
  - lib/plurimath.rb
99
100
  - lib/plurimath/asciimath.rb
100
101
  - lib/plurimath/asciimath/constants.rb
@@ -102,6 +103,7 @@ files:
102
103
  - lib/plurimath/asciimath/parser.rb
103
104
  - lib/plurimath/asciimath/transform.rb
104
105
  - lib/plurimath/cli.rb
106
+ - lib/plurimath/formatter.rb
105
107
  - lib/plurimath/formatter/number_formatter.rb
106
108
  - lib/plurimath/formatter/numbers/base.rb
107
109
  - lib/plurimath/formatter/numbers/fraction.rb