# `Feel.Analysis.MonthScaling`
[🔗](https://github.com/FeeJai/BDM/blob/feel-v0.1.0/apps/feel/lib/feel/analysis/month_scaling.ex#L1)

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}}

# `cut`

```elixir
@spec cut(Feel.Type.NumberSet.t()) :: {Feel.Type.NumberSet.t(), boolean()}
```

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`

```elixir
@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.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
