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

The values an operand of an arithmetic operation can be, when the result is in a set (D-122).

A comparison of an operation (`d + p > @"2020-06-01"`, `p * 2 <= @"PT1H"`) says that the result is in a set of the
kind that it is compared with (`Feel.Analysis.TestSets`). The kind of the result depends on the kinds of the two
operands, so for an operand of a kind and the other operand's alternatives of each kind, this gives the set of the
operand of that kind that gives such a result with some value of the other. The sets are of the numbers that stand
for the values (`Feel.Type.Image`): a number is its own, a date is its days, a years and months duration its
months and a days and time duration its seconds.

| The operation | The result | Inverted by |
| ------------- | ---------- | ----------- |
| number, number | number | `Feel.Analysis.Preimage`, the run's arithmetic |
| days and time duration `+ -` days and time duration | days and time duration | the same, on seconds |
| days and time duration `*` number, number `*` days and time duration, days and time duration `/` number | days and time duration | the same, on seconds |
| days and time duration `/` days and time duration | number | the same |
| years and months duration `+ -` years and months duration | years and months duration | the same, with no rounding and whole months |
| years and months duration `/` years and months duration | number | the same, with whole months |
| years and months duration `*` number, number `*` years and months duration, years and months duration `/` number | years and months duration | the same, for a result that is rounded half up to a month |
| date `-` date | days and time duration | the same, on whole days (86,400 seconds each), with no rounding |
| date `+ -` duration, duration `+` date | date | `Feel.Analysis.DatePreimage` |

A pair of kinds that gives only `null` (a date and a number, a string and a duration) gives no value of the
operand; any other pair (a time, a name of a type that is not known, a function) is not known, and the operand is
not narrowed.

# `kind`

```elixir
@type kind() :: :number | :date | :years_and_months_duration | :days_and_time_duration
```

A kind of the values that an operation here takes and gives.

# `kinds`

```elixir
@spec kinds() :: [kind(), ...]
```

The kinds of values that these operations take.

# `sets`

```elixir
@spec sets(atom(), :left | :right, [kind()], Feel.Type.Union.t(), %{
  optional(kind()) =&gt; Feel.Type.NumberSet.t()
}) :: %{optional(kind()) =&gt; Feel.Type.NumberSet.t()}
```

The set of the operand of each of the kinds that give a result in the sets, for the other operand's type.

`results` has the set of images that the result can be, for each kind of result (a kind that is not in it can be
any). A kind is left out if it is not known what it can be: the other operand has an alternative that may give a
value of it and is not read.

    iex> alias Feel.Type.NumberSet
    iex> five = NumberSet.interval({Decimal.new(5), :open}, NumberSet.max_value())
    iex> one = [{:number, NumberSet.point(Decimal.new(1))}]
    iex> %{number: set} = Feel.Analysis.Operands.sets(:add, :left, [:number], one, %{number: five})
    iex> NumberSet.format(set)
    "(4..max]"

---

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