Skip to content

Commit 304b92d

Browse files
committed
Add RDF::Literal::Numberic#** and RDF::Literal::Numeric#% based on XPath definitions.
1 parent fc30eec commit 304b92d

2 files changed

Lines changed: 109 additions & 0 deletions

File tree

lib/rdf/model/literal/numeric.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,40 @@ def *(other)
123123
end
124124
end
125125

126+
##
127+
# Exponent − Performs exponential (power) calculation on operators.
128+
#
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.
132+
#
133+
# @param [Literal::Numeric, #to_i, #to_f, #to_d] other
134+
# @return [RDF::Literal::Double]
135+
# @since 0.2.3
136+
# @see https://www.w3.org/TR/xpath-functions/#func-math-pow
137+
def **(other)
138+
RDF::Literal::Double.new(to_f ** other.to_f)
139+
end
140+
141+
##
142+
# Exponent − Performs remainder of `self` divided by `other`.
143+
#
144+
# @param [Literal::Numeric, #to_i, #to_f, #to_d] other
145+
# @return [RDF::Literal]
146+
# @since 0.2.3
147+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-mod
148+
def %(other)
149+
if self.class == Double || [Double, ::Float].include?(other.class)
150+
self.class.new(to_f % other.to_f)
151+
elsif ((self.class == RDF::Literal::Float || other.class == RDF::Literal::Float) rescue false)
152+
self.class.new(to_f % other.to_f)
153+
elsif self.class == Decimal || other.class == Decimal
154+
self.class.new(to_d % (other.respond_to?(:to_d) ? other.to_d : BigDecimal(other.to_s)))
155+
else
156+
self.class.new(to_i % other.to_i)
157+
end
158+
end
159+
126160
##
127161
# Returns the quotient of `self` divided by `other`.
128162
#

spec/model_literal_spec.rb

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,41 @@ def self.literals(*selector)
467467
end
468468
end
469469
end
470+
471+
describe "#**" do
472+
{
473+
"2^3": [2, 3, 8.0e0],
474+
"-2^3": [-2, 3, -8.0e0],
475+
"2^-3": [2, -3, 0.125e0],
476+
"-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+
"0^-4": [0, -4, RDF::Literal::Double.new('INF')],
481+
"16^0.5e0": [16, 0.5e0, 4.0e0],
482+
"16^0.25e0": [16, 0.25e0, 2.0e0],
483+
"-1^INF": [-1, RDF::Literal::Double.new('INF'), 1.0e0],
484+
"-1^-INF": [-1, RDF::Literal::Double.new('-INF'), 1.0e0],
485+
"1^INF": [1, RDF::Literal::Double.new('INF'), 1.0e0],
486+
"1^-INF": [1, RDF::Literal::Double.new('-INF'), 1.0e0],
487+
"1^-NaN": [1, RDF::Literal::Double.new('NaN'), 1.0e0],
488+
}.each do |name, (n, e, result)|
489+
it name do
490+
expect(RDF::Literal(n) ** RDF::Literal(e)).to eq RDF::Literal(result)
491+
end
492+
end
493+
end
494+
495+
describe "#%" do
496+
{
497+
"10 % 3": [10, 3, 1],
498+
"6 % -2": [6, -2, 0],
499+
}.each do |name, (n, e, result)|
500+
it name do
501+
expect(RDF::Literal(n) % RDF::Literal(e)).to eq RDF::Literal(result)
502+
end
503+
end
504+
end
470505
end
471506

472507
describe RDF::Literal::Decimal do
@@ -529,6 +564,16 @@ def self.literals(*selector)
529564
end
530565
end
531566
end
567+
568+
describe "#%" do
569+
{
570+
"4.5 % 1.2": [RDF::Literal::Decimal.new("4.5"), RDF::Literal::Decimal.new("1.2"), RDF::Literal::Decimal.new("0.9")],
571+
}.each do |name, (n, e, result)|
572+
it name do
573+
expect(RDF::Literal(n) % RDF::Literal(e)).to eq RDF::Literal(result)
574+
end
575+
end
576+
end
532577
end
533578

534579
describe RDF::Literal::Double do
@@ -689,6 +734,36 @@ def self.literals(*selector)
689734
expect(inf + nan).to be_nan
690735
expect(nan + nan).to be_nan
691736
end
737+
738+
describe "#**" do
739+
{
740+
"INF^0": [RDF::Literal::Double.new('INF'), 0, 1.0e0],
741+
"NaN^0": [RDF::Literal::Double.new('NaN'), 0, 1.0e0],
742+
"0e0^3": [0e0, 3, 0.0e0],
743+
"0e0^4": [0e0, 4, 0.0e0],
744+
"-0e0^3": [-0e0, 3, -0.0e0],
745+
"0e0^-3": [0e0, -3, RDF::Literal::Double.new('INF')],
746+
"0e0^-4": [0e0, -4, RDF::Literal::Double.new('INF')],
747+
"-0e0^-3": [-0e0, -3, RDF::Literal::Double.new('-INF')],
748+
"-0e0^-3.0e0": [-0e0, -3.0e0, RDF::Literal::Double.new('-INF')],
749+
"0e0^-3.1e0": [0e0, -3.1e0, RDF::Literal::Double.new('INF')],
750+
"-0e0^-3.1e0": [-0e0, -3.1e0, RDF::Literal::Double.new('INF')],
751+
}.each do |name, (n, e, result)|
752+
it name do
753+
expect(RDF::Literal(n) ** RDF::Literal(e)).to eq RDF::Literal(result)
754+
end
755+
end
756+
end
757+
758+
describe "#%" do
759+
{
760+
"0e0 % 3": [1.23e2, 0.6e1, 3.0e0],
761+
}.each do |name, (n, e, result)|
762+
it name do
763+
expect(RDF::Literal(n) % RDF::Literal(e)).to eq RDF::Literal(result)
764+
end
765+
end
766+
end
692767
end
693768

694769
describe RDF::Literal::DateTime do

0 commit comments

Comments
 (0)