A set of numbers, as intervals (D-39).
A set of numbers is a list of intervals that do not touch, in order, each from a lower bound
to an upper bound. A bound is a number and says whether it is in the interval, :closed, or
not, :open: [0..150] is {{0, :closed}, {150, :closed}}, and (0..5] is
{{0, :open}, {5, :closed}}. The numbers are the Decimals of FEEL, and the sets lie within
the range of decimal128, from -max_value/0 to max_value/0, since there are no others.
all/0 is that range, and an empty set is [].
Feel.Type.Union holds one of these on a number alternative, as {:number, set}, to say which
numbers a value can be, and on a date or a duration alternative to say which values it can be, by
the numbers that stand for them (D-109, Feel.Type.Image). The functions here are the algebra of the sets: union, intersection,
complement, and the tests contains?/2 and subset?/2. The rules for what an operation
does to a set are in Feel.Analysis.Intervals.
A set is built with new/1, which puts the intervals in order, merges those that overlap or
touch ([0..5) and [5..9] are [0..9], but [0..5) and (5..9] are not, since 5 is in
neither), and drops the empty ones. The default :outer approximation replaces more than 16
intervals by their hull, suitable for possible-value upper bounds. :inner keeps at most 16
intervals without filling gaps, suitable for certainly-accepted lower bounds. :exact keeps
every interval. Complement and inclusion are exact; they must not complement a widened gap set.
Summary
Types
A bound of an interval: a number, and whether the interval includes it.
Intervals in order that do not touch, each with a number in it.
Functions
Every number there is.
Returns true for the set of every number.
The numbers that are in the range of decimal128 and not in the set, without approximation. The complement of 16 separated interior intervals needs 17 intervals and retains all of them.
Returns true when the number is in the set.
Returns true for a set with no number in it.
Writes a set: [0..150] for an interval, with ( and ) for a bound that is left out,
3 for one number, and -max and max for the ends of the range of decimal128. Several
intervals are separated by commas.
The numbers that are in both sets, with the approximation policy of new/2.
The interval from lower to upper: each is a number, or {number, :open} for a number
that is not in it.
The set with the intervals that meet at whole numbers made one, for the numbers that are whole: [1..3] and [4..6] hold the
same whole numbers as [1..6], and the days of two dates that follow one another are such (a date is the number of its
day, Feel.Type.Image). It is not for a set of numbers that may have a fraction, which the two do not hold the same of.
The lowest bound of the set, or nil for an empty set.
The largest number of decimal128: 9.999999999999999999999999999999999E+6144.
Builds a set from intervals, in any order and form: they are cut to the range of decimal128,
the empty ones dropped, and those that overlap or touch merged. The optional approximation
is :outer (the default, at most 16 intervals enlarged to their hull), :inner (at most 16
intervals retained as a subset), or :exact (no interval cap).
A set of one number. A number outside the range of decimal128 is not a number of FEEL, and gives every number, since nothing is known about it.
Returns the number of a set of one number, or :error.
Returns true when every number of the first set is in the second.
The numbers that are in either set, with the approximation policy of new/2.
The highest bound of the set, or nil for an empty set.
Types
Functions
@spec all() :: t()
Every number there is.
iex> Feel.Type.NumberSet.all?(Feel.Type.NumberSet.all())
true
Returns true for the set of every number.
The numbers that are in the range of decimal128 and not in the set, without approximation. The complement of 16 separated interior intervals needs 17 intervals and retains all of them.
iex> Feel.Type.NumberSet.point(Decimal.new(0)) |> Feel.Type.NumberSet.complement() |> Feel.Type.NumberSet.format()
"[-max..0), (0..max]"
Returns true when the number is in the set.
iex> set = Feel.Type.NumberSet.interval({Decimal.new(0), :open}, Decimal.new(5))
iex> {Feel.Type.NumberSet.contains?(set, Decimal.new(5)), Feel.Type.NumberSet.contains?(set, Decimal.new(0))}
{true, false}
Returns true for a set with no number in it.
Writes a set: [0..150] for an interval, with ( and ) for a bound that is left out,
3 for one number, and -max and max for the ends of the range of decimal128. Several
intervals are separated by commas.
A set can stand for something other than numbers (the days of a date, the seconds of a
duration; see Feel.Type.Image). text then writes each bound, and gets every number
but the ends of the range of decimal128, which are -max and max as above.
iex> Feel.Type.NumberSet.format(Feel.Type.NumberSet.all())
"[-max..max]"
iex> set = Feel.Type.NumberSet.interval(Decimal.new(1), Decimal.new(3))
iex> Feel.Type.NumberSet.format(set, &("<" <> Decimal.to_string(&1) <> ">"))
"[<1>..<3>]"The default writes a number in full, with its scale, unless its first digit is more than 34 places
from the point: 1E-6176 is not a 0, a point and 6,175 more zeros.
iex> Feel.Type.NumberSet.format(Feel.Type.NumberSet.point(Decimal.new(1, 1, -6176)))
"1E-6176"
iex> set = Feel.Type.NumberSet.interval(Decimal.new(1), Decimal.new(1, 5, 6143))
iex> Feel.Type.NumberSet.format(set)
"[1..5E+6143]"
iex> Feel.Type.NumberSet.format(Feel.Type.NumberSet.point(Decimal.new(1, 1, -34)))
"0.0000000000000000000000000000000001"
The numbers that are in both sets, with the approximation policy of new/2.
iex> a = Feel.Type.NumberSet.interval(Decimal.new(0), Decimal.new(10))
iex> b = Feel.Type.NumberSet.interval({Decimal.new(5), :open}, Decimal.new(20))
iex> a |> Feel.Type.NumberSet.intersect(b) |> Feel.Type.NumberSet.format()
"(5..10]"
The interval from lower to upper: each is a number, or {number, :open} for a number
that is not in it.
iex> Feel.Type.NumberSet.interval(Decimal.new(0), Decimal.new(150)) |> Feel.Type.NumberSet.format()
"[0..150]"
iex> Feel.Type.NumberSet.interval({Decimal.new(0), :open}, Decimal.new(5)) |> Feel.Type.NumberSet.format()
"(0..5]"
The set with the intervals that meet at whole numbers made one, for the numbers that are whole: [1..3] and [4..6] hold the
same whole numbers as [1..6], and the days of two dates that follow one another are such (a date is the number of its
day, Feel.Type.Image). It is not for a set of numbers that may have a fraction, which the two do not hold the same of.
iex> a = Feel.Type.NumberSet.interval(Decimal.new(1), Decimal.new(3))
iex> b = Feel.Type.NumberSet.interval(Decimal.new(4), Decimal.new(6))
iex> a |> Feel.Type.NumberSet.union(b) |> Feel.Type.NumberSet.join_whole_neighbours() |> Feel.Type.NumberSet.format()
"[1..6]"
iex> c = Feel.Type.NumberSet.interval(Decimal.new(8), Decimal.new(9))
iex> a |> Feel.Type.NumberSet.union(c) |> Feel.Type.NumberSet.join_whole_neighbours() |> Feel.Type.NumberSet.format()
"[1..3], [8..9]"
The lowest bound of the set, or nil for an empty set.
@spec max_value() :: Decimal.t()
The largest number of decimal128: 9.999999999999999999999999999999999E+6144.
iex> Decimal.to_string(Feel.Type.NumberSet.max_value(), :scientific)
"9.999999999999999999999999999999999E+6144"
Builds a set from intervals, in any order and form: they are cut to the range of decimal128,
the empty ones dropped, and those that overlap or touch merged. The optional approximation
is :outer (the default, at most 16 intervals enlarged to their hull), :inner (at most 16
intervals retained as a subset), or :exact (no interval cap).
iex> intervals = [
...> {{Decimal.new(5), :closed}, {Decimal.new(9), :closed}},
...> {{Decimal.new(0), :closed}, {Decimal.new(5), :open}}
...> ]
iex> intervals |> Feel.Type.NumberSet.new() |> Feel.Type.NumberSet.format()
"[0..9]"
A set of one number. A number outside the range of decimal128 is not a number of FEEL, and gives every number, since nothing is known about it.
iex> Feel.Type.NumberSet.point(Decimal.new(3)) |> Feel.Type.NumberSet.format()
"3"
Returns the number of a set of one number, or :error.
iex> Feel.Type.NumberSet.single(Feel.Type.NumberSet.point(Decimal.new(3)))
{:ok, Decimal.new(3)}
iex> Feel.Type.NumberSet.single(Feel.Type.NumberSet.all())
:error
Returns true when every number of the first set is in the second.
iex> inner = Feel.Type.NumberSet.interval(Decimal.new(1), Decimal.new(2))
iex> outer = Feel.Type.NumberSet.interval(Decimal.new(0), Decimal.new(5))
iex> {Feel.Type.NumberSet.subset?(inner, outer), Feel.Type.NumberSet.subset?(outer, inner)}
{true, false}
The numbers that are in either set, with the approximation policy of new/2.
iex> a = Feel.Type.NumberSet.interval(Decimal.new(0), Decimal.new(5))
iex> b = Feel.Type.NumberSet.interval(Decimal.new(10), Decimal.new(20))
iex> a |> Feel.Type.NumberSet.union(b) |> Feel.Type.NumberSet.format()
"[0..5], [10..20]"
The highest bound of the set, or nil for an empty set.