Feel.Analysis.Images.Number.Preimage (feel v0.1.0)

Copy Markdown View Source

The numbers an argument of a number built-in can be when the result is in a set (D-161, step C).

Feel.Analysis.Images.Number goes from the argument to the result. This goes back, for abs(x) < 100: the comparison says the result is in [-max..100) (Feel.Analysis.TestSets), so x is in (-100..100). Given the set that the result is in, operand/3 gives the set that the argument has to be in for the call to give a number in it: every number the run gives such a result for is in it, and so is a few more where the rounding of the run is in the way. Feel.Analysis.Narrowing reads a comparison of a call with it, as it reads the comparison of an operation with Feel.Analysis.Preimage.

FunctionThe argumentExact?
absthe results and their negatives (for the two kinds of duration too)yes
floor, ceiling, round *, decimal at a scalethe numbers between the steps next to the results that are multiples of the stepyes
modulo by a numberthe numbers of the argument's own set that are a remainder of the results away from a multiple of the divisor (modulo_within/3)yes
sqrt, exp, logthe numbers that give a result in the set, found from the inverse of the function and the runthe ends of a result that the comparison has, and not the ends that it has not (below)

The rounding functions are step functions of x * 10^scale, increasing by one at a time, so a set of results is a set of steps (m * 10^-scale for the whole numbers m of it), and the numbers that give them are the numbers from the start of the first step to the end of the last: floor(x) = 3 is [3..4), round half up(x) = 3 is [2.5..3.5), and round up(x) = 3 is (2..3]. A result that is not a multiple of the step is given by no number, and the set is empty.

The roots, the logarithm and the exponential are increasing, and the run rounds their value to 34 digits, to the nearest. The end of a result that is not in the set (sqrt(x) > 3, sqrt(x) < 10) is exact: the rounding keeps the order, and a bound of 34 digits is not changed by it, so a number that gives a result above 3 has a root above 3, which is x > 9. The end that is in (>=, <=, =) is one that the value can be half a unit of its last digit short of, and still be rounded to, so it is looked for from there in: the inverse of the function (ln for the exponential, exp for the logarithm, from the run, with a unit of the last digit either way to hold the true value) gives a number a unit of the last digit out, and the run itself brings it in to the first number that gives a result in the set, in at most 24 numbers; where it does not come to one, the number from the inverse stays, which is a larger set. So sqrt(x) >= 10 is [100..max], sqrt(x) >= 3 is [8.999999999999999999999999999999998..max] (the first number whose root the run rounds to 3), and sqrt(x) <= 10 is [0..100.0000000000000000000000000000001], since that is a number whose root rounds to 10.

An end of the argument is where the run has no result any more: exp(x) is a number up to Real.exp_range/0's high, so exp(x) > 1 is (0..14149.38539644841072829055748903541].

Summary

Functions

The numbers of a set that give a remainder in the results when divided by a number, for a divisor that is one number: the numbers of the set that are a remainder of the results away from a multiple of the divisor, modulo(x, 7) = 3 being the 3, 10, 17 ... of it. The set of the argument is needed since the numbers are many, as many as the multiples of the divisor there are; a set with more than a few of them is returned as it is.

The functions that have a preimage.

The number of 34 digits next to a number, above or below it.

The numbers an argument can be for the call name(argument) (name(argument, scale) for a rounding function, with the scale that scale/1 gives) to give a result in the set, or :error for a function and a scale it has no preimage for.

The scale of a call of a rounding function, as the run takes it (a whole number in -6111..6176, the fraction cut off), for the number the scale is, or :error if the scale is out of range (the call is null).

Functions

modulo_within(own, modulus, results)

The numbers of a set that give a remainder in the results when divided by a number, for a divisor that is one number: the numbers of the set that are a remainder of the results away from a multiple of the divisor, modulo(x, 7) = 3 being the 3, 10, 17 ... of it. The set of the argument is needed since the numbers are many, as many as the multiples of the divisor there are; a set with more than a few of them is returned as it is.

iex> alias Feel.Type.NumberSet
iex> alias Feel.Analysis.Images.Number.Preimage
iex> to_20 = NumberSet.interval(Decimal.new(0), Decimal.new(20))
iex> Preimage.modulo_within(to_20, Decimal.new(7), NumberSet.point(Decimal.new(3))) |> NumberSet.format()
"3, 10, 17"
iex> Preimage.modulo_within(to_20, Decimal.new(-7), NumberSet.point(Decimal.new(-3))) |> NumberSet.format()
"4, 11, 18"
iex> results = NumberSet.interval(Decimal.new(0), {Decimal.new(2), :open})
iex> Preimage.modulo_within(to_20, Decimal.new(7), results) |> NumberSet.format()
"[0..2), [7..9), [14..16)"

names()

@spec names() :: [String.t()]

The functions that have a preimage.

neighbor(number, direction)

@spec neighbor(Decimal.t(), :up | :down) :: Decimal.t()

The number of 34 digits next to a number, above or below it.

iex> alias Feel.Analysis.Images.Number.Preimage
iex> Preimage.neighbor(Decimal.new(100), :up) |> Decimal.to_string(:normal)
"100.0000000000000000000000000000001"
iex> Preimage.neighbor(Decimal.new(100), :down) |> Decimal.to_string(:normal)
"99.99999999999999999999999999999999"

operand(name, scale, results)

@spec operand(String.t(), integer() | nil, Feel.Type.NumberSet.t()) ::
  {:ok, Feel.Type.NumberSet.t()} | :error

The numbers an argument can be for the call name(argument) (name(argument, scale) for a rounding function, with the scale that scale/1 gives) to give a result in the set, or :error for a function and a scale it has no preimage for.

iex> alias Feel.Type.NumberSet
iex> alias Feel.Analysis.Images.Number.Preimage
iex> lt_100 = NumberSet.interval(Decimal.negate(NumberSet.max_value()), {Decimal.new(100), :open})
iex> {:ok, set} = Preimage.operand("abs", nil, lt_100)
iex> NumberSet.format(set)
"(-100..100)"
iex> {:ok, set} = Preimage.operand("floor", 0, NumberSet.point(Decimal.new(3)))
iex> NumberSet.format(set)
"[3..4)"
iex> {:ok, set} = Preimage.operand("sqrt", nil, lt_100)
iex> NumberSet.format(set)
"[0..10000)"

scale(number)

@spec scale(Decimal.t()) :: {:ok, integer()} | :error

The scale of a call of a rounding function, as the run takes it (a whole number in -6111..6176, the fraction cut off), for the number the scale is, or :error if the scale is out of range (the call is null).

iex> Feel.Analysis.Images.Number.Preimage.scale(Decimal.new("2.9"))
{:ok, 2}
iex> Feel.Analysis.Images.Number.Preimage.scale(Decimal.new(6177))
:error