plurimath 0.8.15 → 0.8.17

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.
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