From cfead4c3d003387e2d5e1d9755c45529a030d83f Mon Sep 17 00:00:00 2001 From: Nick Nicholas Date: Thu, 19 Sep 2024 23:40:36 +1000 Subject: [PATCH] large_notation option in number formatting: https://github.com/metanorma/isodoc/issues/602 --- lib/isodoc/presentation_function/math.rb | 30 +++- spec/isodoc/presentation_xml_maths_spec.rb | 164 ++++++++++++++++++++- 2 files changed, 187 insertions(+), 7 deletions(-) diff --git a/lib/isodoc/presentation_function/math.rb b/lib/isodoc/presentation_function/math.rb index 8e142b60..6a398c13 100644 --- a/lib/isodoc/presentation_function/math.rb +++ b/lib/isodoc/presentation_function/math.rb @@ -24,7 +24,7 @@ def localize_maths(node, locale) fmt = x["data-metanorma-numberformat"] x.delete("data-metanorma-numberformat") x.children = - if fmt.nil? && !fmt.empty? + if !fmt.nil? && !fmt.empty? explicit_number_formatter(x, locale, fmt) else implicit_number_formatter(x, locale) end @@ -80,11 +80,35 @@ def explicit_number_formatter(num, locale, options) def explicit_number_formatter_cfg(num, fmt) symbols = twitter_cldr_localiser_symbols.dup.merge(fmt) - precision = symbols[:precision] || num_precision(num.text) + symbols = large_notation_fmt(symbols, num.text) + [symbols[:precision] || num_precision(num.text), symbols, + explicit_number_formatter_signif(num, symbols)] + end + + def explicit_number_formatter_signif(num, symbols) signif = symbols[:significant] (symbols.keys & %i(precision digit_count)).empty? and signif ||= num_totaldigits(num.text) - [precision, symbols, signif] + signif + end + + def large_notation_fmt(symbols, num) + n = symbols[:large_notation] + min = BigDecimal(symbols[:large_notation_min] || "1e-6") + max = BigDecimal(symbols[:large_notation_max] || "1e6") + n1 = large_notation_fmt1(num, n, min, max) and symbols[:notation] = n1 + symbols.delete(:large_notation) + symbols.delete(:large_notation_min) + symbols.delete(:large_notation_max) + symbols + end + + def large_notation_fmt1(num, notation, min, max) + notation.nil? || notation == "nil" and return + val = BigDecimal(num).abs + val < min and return notation + val > max and return notation + nil end def num_precision(num) diff --git a/spec/isodoc/presentation_xml_maths_spec.rb b/spec/isodoc/presentation_xml_maths_spec.rb index 84906559..655d2430 100644 --- a/spec/isodoc/presentation_xml_maths_spec.rb +++ b/spec/isodoc/presentation_xml_maths_spec.rb @@ -181,7 +181,8 @@ end it "Supports twitter_cldr_localiser_symbols fraction options" do - expect(Xml::C14n.format(strip_guid(IsoDoc::PresentationXMLConvert.new(presxml_options) + expect(Xml::C14n.format(strip_guid(IsoDoc::PresentationXMLConvert + .new(presxml_options) .convert("test", input, true)) .sub(%r{.*}m, ""))) .to(be_equivalent_to(Xml::C14n.format(output))) @@ -217,7 +218,8 @@ OUTPUT - expect(Xml::C14n.format(strip_guid(IsoDoc::PresentationXMLConvert.new(presxml_options) + expect(Xml::C14n.format(strip_guid(IsoDoc::PresentationXMLConvert + .new(presxml_options) .convert("test", input, true)) .sub(%r{.*}m, ""))) .to be_equivalent_to Xml::C14n.format(output) @@ -252,7 +254,8 @@ OUTPUT - expect(Xml::C14n.format(strip_guid(IsoDoc::PresentationXMLConvert.new(presxml_options) + expect(Xml::C14n.format(strip_guid(IsoDoc::PresentationXMLConvert + .new(presxml_options) .convert("test", input, true)) .sub(%r{.*}m, ""))) .to be_equivalent_to Xml::C14n.format(output) @@ -447,7 +450,7 @@ 0.6421214967726451564515e18 - 0.6421214967726451564515e18 + 0.6421214967726451564515e18 0.6421214967726451564515e18 @@ -619,6 +622,159 @@ .to be_equivalent_to Xml::C14n.format(output1) end + it "with large-notation attribute and implicit minimum and maximum" do + allow_any_instance_of(IsoDoc::PresentationXMLConvert) + .to(receive(:twitter_cldr_localiser_symbols) + .and_return({ + fraction_group_digits: 2, + fraction_group: "'", + large_notation: "scientific", + })) + + output1 = <<~OUTPUT + + + test + + + Table of contents +

+ 31 + 327,428.74'32'87'84'32'99'2 + 327,428.74'32'87'84'32'99'2 + 327,428 + 327,428.74'3 + 327,000 + 327,428.74'3 + 327,428.74'3 + 327,428 + 327 428,74'3 + 327,000 + 327 428,74'3 + 327 428,74'3 + 1 + 1,1 + 1,10'0 + 1 × 1021 + 1,0 × 1019 + 1,0 × 10-19 + 3.27e5 + 3,27'42'87'43e5 + 3.27e5 + 3,27'42'87'43e5 + 3,27'4e5 + 1e0 + 1,1e0 + 1,10'0e0 + 1 × 1021 + 1,0 × 1019 + 1,0 × 10-19 + ... + 6,4212y1490y0 × 1017 + 6,4212y1490y0 × 1017 + 6,4212y1490y0 × 10+17 + 642,1214y967 × 1015 + 6,42'12'14'96'8 × 1017 + 6,4212y1490y0 × 10-20 + 6,4212y1490y0 × 10-20 + 6,4212y1490y0 × 10-20 + 6,42'12'14'96'8 × 10-20 + 6,42'12'14'96'8 × 10-20sqrt(0.6421214967726451564515e-19) + 30 000 + + + OUTPUT + TwitterCldr.reset_locale_fallbacks + + expect(Xml::C14n.format(strip_guid(IsoDoc::PresentationXMLConvert + .new({ localizenumber: "#=#0;##$#" } + .merge(presxml_options)) + .convert("test", input, true)) + .sub(%r{.*}m, ""))) + .to be_equivalent_to Xml::C14n.format(output1) + end + + it "with large-notation attribute and explicit minimum and maximum" do + allow_any_instance_of(IsoDoc::PresentationXMLConvert) + .to(receive(:twitter_cldr_localiser_symbols) + .and_return({ + fraction_group_digits: 2, + fraction_group: "'", + large_notation: "scientific", + large_notation_min: "1e-3", + large_notation_max: "1e3", + })) + + output1 = <<~OUTPUT + + + test + + + Table of contents +

+ 31 3.27'42'87'43'28'78'43'29'92 × 105 + 3.27'42'87'43'28'78'43'29'92 × 105 + 3.27 × 105 + 3.27'42'87'43 × 105 + 3.27 × 105 + 3.27'42'87'43 × 105 + 3.27'4 × 105 + 3.27 × 105 + 3,27'42'87'43 × 105 + 3.27 × 105 + 3,27'42'87'43 × 105 + 3,27'4 × 105 + 1 1,1 1,10'0 1 × 1021 + 1,0 × 1019 + 1,0 × 10-19 + 3.27 × 105 + 3,27'42'87'43 × 105 + 3.27 × 105 + 3,27'42'87'43 × 105 + 3,27'4 × 105 + 1e0 + 1,1e0 + 1,10'0e0 + 1 × 1021 + 1,0 × 1019 + 1,0 × 10-19 + ... 6,4212y1490y0 × 1017 + 6,4212y1490y0 × 1017 + 6,4212y1490y0 × 10+17 + 642,1214y967 × 1015 + 6,42'12'14'96'8 × 1017 + 6,4212y1490y0 × 10-20 + 6,4212y1490y0 × 10-20 + 6,4212y1490y0 × 10-20 + 6,42'12'14'96'8 × 10-20 + + + + + 6,42'12'14'96'8 × 10 + -20 + + + + sqrt(0.6421214967726451564515e-19) + + 3,00'00 × 10 + 4 +

+ + + OUTPUT + TwitterCldr.reset_locale_fallbacks + + expect(Xml::C14n.format(strip_guid(IsoDoc::PresentationXMLConvert + .new({ localizenumber: "#=#0;##$#" } + .merge(presxml_options)) + .convert("test", input, true)) + .sub(%r{.*}m, ""))) + .to be_equivalent_to Xml::C14n.format(output1) + end + it "with numbers within formulas" do allow_any_instance_of(IsoDoc::PresentationXMLConvert) .to(receive(:twitter_cldr_localiser_symbols)