Skip to content

Commit 81f39cd

Browse files
committed
Add native support for Rational to xsd:double. Update Literal::Numeric#** to use the type of the native result, rather than always double.
1 parent 304b92d commit 81f39cd

3 files changed

Lines changed: 30 additions & 12 deletions

File tree

lib/rdf/model/literal.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ def self.new(value, language: nil, datatype: nil, lexical: nil, validate: false,
118118
when ::Integer then RDF::Literal::Integer
119119
when ::Float then RDF::Literal::Double
120120
when ::BigDecimal then RDF::Literal::Decimal
121+
when ::Rational then RDF::Literal::Double
121122
when ::DateTime then RDF::Literal::DateTime
122123
when ::Time then RDF::Literal::DateTime
123124
when ::Date then RDF::Literal::Date

lib/rdf/model/literal/numeric.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,16 @@ def *(other)
126126
##
127127
# Exponent − Performs exponential (power) calculation on operators.
128128
#
129-
# If other is an instance of xs:integer, the result is self raised to the power of other as defined in the [IEEE 754-2008] specification of the pown function applied to a 64-bit binary floating point value and an integer.
130-
#
131-
# Otherwise $y is converted to an xs:double by numeric promotion, and the result is the value of $x raised to the power of $y as defined in the [IEEE 754-2008] specification of the pow function applied to two 64-bit binary floating point values.
129+
# Promotes values, as necessary, with the result type depending on the input values.
132130
#
133131
# @param [Literal::Numeric, #to_i, #to_f, #to_d] other
134-
# @return [RDF::Literal::Double]
132+
# @return [RDF::Literal::Numeric]
135133
# @since 0.2.3
136134
# @see https://www.w3.org/TR/xpath-functions/#func-math-pow
137135
def **(other)
138-
RDF::Literal::Double.new(to_f ** other.to_f)
136+
RDF::Literal(object ** (other.is_a?(RDF::Literal::Numeric) ? other.object : other))
137+
rescue ZeroDivisionError
138+
RDF::Literal::Double.new('INF')
139139
end
140140

141141
##

spec/model_literal_spec.rb

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def self.literal(selector)
2222
when :int then [123]
2323
when :long then [9223372036854775807]
2424
when :double then [3.1415]
25+
when :decimal then [BigDecimal("1.2")]
2526
when :date then [Date.new(2010)]
2627
when :datetime then [DateTime.new(2011)]
2728
when :time then ['01:02:03Z', {datatype: RDF::XSD.time}]
@@ -35,7 +36,7 @@ def self.literals(*selector)
3536
ary += case sel
3637
when :all_simple then [:empty, :plain, :string].map {|s| literal(s)}
3738
when :all_plain_lang then [:empty_lang, :plain_lang].map {|s| literal(s)}
38-
when :all_native then [:false, :true, :int, :long, :double, :time, :date, :datetime].map {|s| literal(s)}
39+
when :all_native then [:false, :true, :int, :long, :decimal, :double, :time, :date, :datetime].map {|s| literal(s)}
3940
when :all_invalid_lang then [:wrong_lang, :unset_lang].map {|s| literal(s)}
4041
when :all_plain then literals(:all_simple, :all_plain_lang)
4142
else literals(:all_plain, :all_native)
@@ -142,8 +143,10 @@ def self.literals(*selector)
142143
false => "boolean",
143144
9223372036854775807 => "integer",
144145
3.1415 => "double",
146+
BigDecimal("1.2") => "decimal",
145147
Date.new(2010) => "date",
146148
DateTime.new(2011) => "dateTime",
149+
Rational("1/3") => "double",
147150
Time.parse("01:02:03Z") => "dateTime"
148151
}.each_pair do |value, type|
149152
it "returns xsd.#{type} for #{value.inspect} #{value.class}" do
@@ -470,13 +473,13 @@ def self.literals(*selector)
470473

471474
describe "#**" do
472475
{
473-
"2^3": [2, 3, 8.0e0],
474-
"-2^3": [-2, 3, -8.0e0],
476+
"2^3": [2, 3, 8],
477+
"-2^3": [-2, 3, -8],
475478
"2^-3": [2, -3, 0.125e0],
476479
"-2^-3": [-2, -3, -0.125e0],
477-
"2^0": [2, 0, 1.0e0],
478-
"0^0": [0, 0, 1.0e0],
479-
"0^4": [0, 4, 0.0e0],
480+
"2^0": [2, 0, 1],
481+
"0^0": [0, 0, 1],
482+
"0^4": [0, 4, 0],
480483
"0^-4": [0, -4, RDF::Literal::Double.new('INF')],
481484
"16^0.5e0": [16, 0.5e0, 4.0e0],
482485
"16^0.25e0": [16, 0.25e0, 2.0e0],
@@ -488,6 +491,7 @@ def self.literals(*selector)
488491
}.each do |name, (n, e, result)|
489492
it name do
490493
expect(RDF::Literal(n) ** RDF::Literal(e)).to eq RDF::Literal(result)
494+
expect((RDF::Literal(n) ** RDF::Literal(e)).datatype).to eq RDF::Literal(result).datatype
491495
end
492496
end
493497
end
@@ -567,13 +571,25 @@ def self.literals(*selector)
567571

568572
describe "#%" do
569573
{
570-
"4.5 % 1.2": [RDF::Literal::Decimal.new("4.5"), RDF::Literal::Decimal.new("1.2"), RDF::Literal::Decimal.new("0.9")],
574+
"4.5 % 1.2": [BigDecimal("4.5"), BigDecimal("1.2"), BigDecimal("0.9")],
571575
}.each do |name, (n, e, result)|
572576
it name do
573577
expect(RDF::Literal(n) % RDF::Literal(e)).to eq RDF::Literal(result)
574578
end
575579
end
576580
end
581+
582+
describe "#**" do
583+
{
584+
"2.7^10": [BigDecimal("2.7"), 10, BigDecimal("20589.1132094649")],
585+
"2.7^10.3": [BigDecimal("2.7"), BigDecimal("10.3"), BigDecimal("27736.1879020809118")],
586+
}.each do |name, (n, e, result)|
587+
it name do
588+
expect(RDF::Literal(n) ** RDF::Literal(e)).to eq RDF::Literal(result)
589+
expect((RDF::Literal(n) ** RDF::Literal(e)).datatype).to eq RDF::Literal(result).datatype
590+
end
591+
end
592+
end
577593
end
578594

579595
describe RDF::Literal::Double do
@@ -751,6 +767,7 @@ def self.literals(*selector)
751767
}.each do |name, (n, e, result)|
752768
it name do
753769
expect(RDF::Literal(n) ** RDF::Literal(e)).to eq RDF::Literal(result)
770+
expect((RDF::Literal(n) ** RDF::Literal(e)).datatype).to eq RDF::Literal(result).datatype
754771
end
755772
end
756773
end

0 commit comments

Comments
 (0)