Feel.Analysis.MonthScaling (feel v0.1.0)

Copy Markdown View Source

The months that a years and months duration times a number, or divided by one, can be (D-109).

A years and months duration is a whole number of months, so the run (Feel.Runtime.Arithmetic) makes the product or the quotient of its months and the number as it does for two numbers, a decimal128 of at most 34 digits and null where it overflows, is too small to write, or divides by zero, and then rounds it to the nearest whole number of months, a half towards positive infinity: P1Y11M * -2.5 is -57.5 months, and -57 is the duration (D-54).

So the months are the numbers that Feel.Analysis.Intervals says the product or the quotient of the two sets can be, rounded. Rounding does not decrease with the number, so an interval of the numbers is the whole numbers from the rounding of its first to the rounding of its last. The ends are taken as closed, as the algebra of the numbers has them: a product of 34 digits is rounded to 34, and can come to an end that the numbers are short of, which then rounds up, so [0..0.5) times 1 is [0..1] and not 0. That holds more and so is sound.

The run makes a number of the months (Decimal.new(months)), which is not one of decimal128 for 34 digits and more: a duration of 10^34 months or more times a number, or divided by one, is null for any number. So the months of the sets are cut to the 34 digits, and the result is null if any were cut, and is null and no month if all were.

The product of two intervals is the interval from the least corner to the greatest, and of the months that is more than the months can be ({1, 100} times [1..2] is not [1..200] but the two intervals [1..2] and [100..200]), so each whole month of an interval is taken by itself, up to 64 of them, and the intervals are joined after the rounding; an interval of more is the one interval from its first month to its last, which holds more and so is sound.

iex> alias Feel.Type.NumberSet
iex> months = NumberSet.interval(Decimal.new(1), Decimal.new(3))
iex> {:ok, {set, false}} = Feel.Analysis.MonthScaling.scale(:multiply, months, NumberSet.point(Decimal.new("0.5")))
iex> NumberSet.format(set)
"[1..2]"
iex> {:ok, {set, false}} = Feel.Analysis.MonthScaling.scale(:divide, months, NumberSet.interval(Decimal.new(1), Decimal.new(2)))
iex> NumberSet.format(set)
"[1..3]"
iex> Feel.Analysis.MonthScaling.scale(:divide, months, NumberSet.point(Decimal.new(0)))
{:ok, {[], true}}

Summary

Functions

The months of a set that the run can make a number of, and whether there are others (which the run gives null for, in a product, a quotient or a quotient of two durations).

The months of months * numbers or months / numbers for the months of a set and the numbers of another, and whether the result can be null. It is :error if the set has no whole month, and the caller says what it did; it is no month and null if all its months are too many for the run to make a number of.

Functions

cut(months)

The months of a set that the run can make a number of, and whether there are others (which the run gives null for, in a product, a quotient or a quotient of two durations).

iex> alias Feel.Type.NumberSet
iex> months = NumberSet.interval(Decimal.new(1), Decimal.new("1E+40"))
iex> {cut, true} = Feel.Analysis.MonthScaling.cut(months)
iex> NumberSet.format(cut)
"[1..9999999999999999999999999999999999]"

scale(operator, months, numbers)

@spec scale(:multiply | :divide, Feel.Type.NumberSet.t(), Feel.Type.NumberSet.t()) ::
  {:ok, {Feel.Type.NumberSet.t(), boolean()}} | :error

The months of months * numbers or months / numbers for the months of a set and the numbers of another, and whether the result can be null. It is :error if the set has no whole month, and the caller says what it did; it is no month and null if all its months are too many for the run to make a number of.