Support value equality checks on RDF.Decimals
This commit is contained in:
parent
d06dcacb04
commit
2313e001fd
3 changed files with 28 additions and 6 deletions
|
@ -2,10 +2,10 @@ defmodule RDF.Decimal do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
`RDF.Datatype` for XSD decimal.
|
`RDF.Datatype` for XSD decimal.
|
||||||
"""
|
"""
|
||||||
alias Elixir.Decimal, as: D
|
|
||||||
|
|
||||||
use RDF.Datatype, id: RDF.Datatype.NS.XSD.decimal
|
use RDF.Datatype, id: RDF.Datatype.NS.XSD.decimal
|
||||||
|
|
||||||
|
alias Elixir.Decimal, as: D
|
||||||
|
|
||||||
|
|
||||||
def build_literal_by_value(value, opts) when is_integer(value),
|
def build_literal_by_value(value, opts) when is_integer(value),
|
||||||
do: value |> D.new() |> build_literal(to_string(value), opts)
|
do: value |> D.new() |> build_literal(to_string(value), opts)
|
||||||
|
@ -67,4 +67,7 @@ defmodule RDF.Decimal do
|
||||||
defp canonical_decimal(%D{coef: coef, exp: exp} = decimal),
|
defp canonical_decimal(%D{coef: coef, exp: exp} = decimal),
|
||||||
do: canonical_decimal(%{decimal | coef: Kernel.div(coef, 10), exp: exp + 1})
|
do: canonical_decimal(%{decimal | coef: Kernel.div(coef, 10), exp: exp + 1})
|
||||||
|
|
||||||
|
|
||||||
|
def equal_value?(left, right), do: RDF.Numeric.equal_value?(left, right)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,8 @@ defmodule RDF.Numeric do
|
||||||
alias RDF.Literal
|
alias RDF.Literal
|
||||||
alias RDF.Datatype.NS.XSD
|
alias RDF.Datatype.NS.XSD
|
||||||
|
|
||||||
|
alias Elixir.Decimal, as: D
|
||||||
|
|
||||||
@types MapSet.new [
|
@types MapSet.new [
|
||||||
XSD.integer,
|
XSD.integer,
|
||||||
XSD.decimal,
|
XSD.decimal,
|
||||||
|
@ -35,6 +37,7 @@ defmodule RDF.Numeric do
|
||||||
"""
|
"""
|
||||||
def type?(type), do: MapSet.member?(@types, type)
|
def type?(type), do: MapSet.member?(@types, type)
|
||||||
|
|
||||||
|
@xsd_decimal XSD.decimal
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Tests for numeric value equality of two numeric literals.
|
Tests for numeric value equality of two numeric literals.
|
||||||
|
@ -48,18 +51,29 @@ defmodule RDF.Numeric do
|
||||||
"""
|
"""
|
||||||
def equal_value?(left, right)
|
def equal_value?(left, right)
|
||||||
|
|
||||||
def equal_value?(%Literal{datatype: left_datatype} = left,
|
def equal_value?(%Literal{datatype: left_datatype, value: left},
|
||||||
%Literal{datatype: right_datatype} = right) do
|
%Literal{datatype: right_datatype, value: right})
|
||||||
|
when left_datatype == @xsd_decimal or right_datatype == @xsd_decimal,
|
||||||
|
do: equal_decimal_value?(left, right)
|
||||||
|
|
||||||
|
def equal_value?(%Literal{datatype: left_datatype, value: left},
|
||||||
|
%Literal{datatype: right_datatype, value: right})
|
||||||
|
do
|
||||||
if type?(left_datatype) and type?(right_datatype) do
|
if type?(left_datatype) and type?(right_datatype) do
|
||||||
# We rely here on Elixirs numeric equality comparison.
|
# We rely here on Elixirs numeric equality comparison.
|
||||||
# TODO: There are probably problematic edge-case, which might require an
|
# TODO: There are probably problematic edge-case, which might require an
|
||||||
# TODO: implementation of XPath type promotion and subtype substitution
|
# TODO: implementation of XPath type promotion and subtype substitution
|
||||||
# - https://www.w3.org/TR/xpath-functions/#op.numeric
|
# - https://www.w3.org/TR/xpath-functions/#op.numeric
|
||||||
# - https://www.w3.org/TR/xpath20/#id-type-promotion-and-operator-mapping
|
# - https://www.w3.org/TR/xpath20/#id-type-promotion-and-operator-mapping
|
||||||
Literal.canonical(left).value == Literal.canonical(right).value
|
left == right
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def equal_value?(_, _), do: nil
|
def equal_value?(_, _), do: nil
|
||||||
|
|
||||||
|
defp equal_decimal_value?(%D{} = left, %D{} = right), do: D.equal?(left, right)
|
||||||
|
defp equal_decimal_value?(%D{} = left, right), do: equal_decimal_value?(left, D.new(right))
|
||||||
|
defp equal_decimal_value?(left, %D{} = right), do: equal_decimal_value?(D.new(left), right)
|
||||||
|
defp equal_decimal_value?(_, _), do: nil
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -126,12 +126,17 @@ defmodule RDF.EqualityTest do
|
||||||
]
|
]
|
||||||
@value_equal_numerics [
|
@value_equal_numerics [
|
||||||
{RDF.integer("42"), RDF.integer("042")},
|
{RDF.integer("42"), RDF.integer("042")},
|
||||||
{RDF.double("+0"), RDF.double("-0")},
|
|
||||||
{RDF.integer("42"), RDF.double("42")},
|
{RDF.integer("42"), RDF.double("42")},
|
||||||
{RDF.integer(42), RDF.double(42.0)},
|
{RDF.integer(42), RDF.double(42.0)},
|
||||||
|
{RDF.integer("42"), RDF.decimal("42")},
|
||||||
|
{RDF.integer(42), RDF.decimal(42.0)},
|
||||||
|
{RDF.double(3.14), RDF.decimal(3.14)},
|
||||||
|
{RDF.double("+0"), RDF.double("-0")},
|
||||||
|
{RDF.decimal("+0"), RDF.decimal("-0")},
|
||||||
]
|
]
|
||||||
@value_unequal_numerics [
|
@value_unequal_numerics [
|
||||||
{RDF.integer("1"), RDF.double("1.1")},
|
{RDF.integer("1"), RDF.double("1.1")},
|
||||||
|
{RDF.integer("1"), RDF.decimal("1.1")},
|
||||||
]
|
]
|
||||||
@incomparable_numerics [
|
@incomparable_numerics [
|
||||||
{RDF.string("42"), RDF.integer(42)},
|
{RDF.string("42"), RDF.integer(42)},
|
||||||
|
|
Loading…
Reference in a new issue