zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

decimal.ex (51114B)


      1 defmodule Decimal do
      2   @moduledoc """
      3   Decimal arithmetic on arbitrary precision floating-point numbers.
      4 
      5   A number is represented by a signed coefficient and exponent such that: `sign
      6   * coefficient * 10 ^ exponent`. All numbers are represented and calculated
      7   exactly, but the result of an operation may be rounded depending on the
      8   context the operation is performed with, see: `Decimal.Context`. Trailing
      9   zeros in the coefficient are never truncated to preserve the number of
     10   significant digits unless explicitly done so.
     11 
     12   There are also special values such as NaN (not a number) and ±Infinity.
     13   -0 and +0 are two distinct values.
     14   Some operation results are not defined and will return NaN.
     15   This kind of NaN is quiet, any operation returning a number will return
     16   NaN when given a quiet NaN (the NaN value will flow through all operations).
     17 
     18   Exceptional conditions are grouped into signals, each signal has a flag and a
     19   trap enabler in the context. Whenever a signal is triggered it's flag is set
     20   in the context and will be set until explicitly cleared. If the signal is trap
     21   enabled `Decimal.Error` will be raised.
     22 
     23   ## Specifications
     24 
     25     * [IBM's General Decimal Arithmetic Specification](http://speleotrove.com/decimal/decarith.html)
     26     * [IEEE standard 854-1987](http://web.archive.org/web/20150908012941/http://754r.ucbtest.org/standards/854.pdf)
     27 
     28   This library follows the above specifications for reference of arithmetic
     29   operation implementations, but the public APIs may differ to provide a
     30   more idiomatic Elixir interface.
     31 
     32   The specification models the sign of the number as 1, for a negative number,
     33   and 0 for a positive number. Internally this implementation models the sign as
     34   1 or -1 such that the complete number will be `sign * coefficient *
     35   10 ^ exponent` and will refer to the sign in documentation as either *positive*
     36   or *negative*.
     37 
     38   There is currently no maximum or minimum values for the exponent. Because of
     39   that all numbers are "normal". This means that when an operation should,
     40   according to the specification, return a number that "underflows" 0 is returned
     41   instead of Etiny. This may happen when dividing a number with infinity.
     42   Additionally, overflow, underflow and clamped may never be signalled.
     43   """
     44 
     45   import Bitwise
     46   import Kernel, except: [abs: 1, div: 2, max: 2, min: 2, rem: 2, round: 1]
     47   import Decimal.Macros
     48   alias Decimal.Context
     49   alias Decimal.Error
     50 
     51   @power_of_2_to_52 4_503_599_627_370_496
     52 
     53   @typedoc """
     54   The coefficient of the power of `10`. Non-negative because the sign is stored separately in `sign`.
     55 
     56     * `non_neg_integer` - when the `t` represents a number, instead of one of the special values below.
     57     * `:NaN` - Not a Number.
     58     * `:inf` - Infinity.
     59 
     60   """
     61   @type coefficient :: non_neg_integer | :NaN | :inf
     62 
     63   @typedoc """
     64   The exponent to which `10` is raised.
     65   """
     66   @type exponent :: integer
     67 
     68   @typedoc """
     69 
     70     * `1` for positive
     71     * `-1` for negative
     72 
     73   """
     74   @type sign :: 1 | -1
     75 
     76   @type signal ::
     77           :invalid_operation
     78           | :division_by_zero
     79           | :rounded
     80           | :inexact
     81 
     82   @typedoc """
     83   Rounding algorithm.
     84 
     85   See `Decimal.Context` for more information.
     86   """
     87   @type rounding ::
     88           :down
     89           | :half_up
     90           | :half_even
     91           | :ceiling
     92           | :floor
     93           | :half_down
     94           | :up
     95 
     96   @typedoc """
     97   This implementation models the `sign` as `1` or `-1` such that the complete number will be: `sign * coef * 10 ^ exp`.
     98 
     99     * `coef` - the coefficient of the power of `10`.
    100     * `exp` - the exponent of the power of `10`.
    101     * `sign` - `1` for positive, `-1` for negative.
    102 
    103   """
    104   @type t :: %__MODULE__{
    105           sign: sign,
    106           coef: coefficient,
    107           exp: exponent
    108         }
    109 
    110   @type decimal :: t | integer | String.t()
    111 
    112   defstruct sign: 1, coef: 0, exp: 0
    113 
    114   defmacrop error(flags, reason, result, context \\ nil) do
    115     quote bind_quoted: binding() do
    116       case handle_error(flags, reason, result, context) do
    117         {:ok, result} -> result
    118         {:error, error} -> raise Error, error
    119       end
    120     end
    121   end
    122 
    123   @doc """
    124   Returns `true` if number is NaN, otherwise `false`.
    125   """
    126   @spec nan?(t) :: boolean
    127   def nan?(%Decimal{coef: :NaN}), do: true
    128   def nan?(%Decimal{}), do: false
    129 
    130   @doc """
    131   Returns `true` if number is ±Infinity, otherwise `false`.
    132   """
    133   @spec inf?(t) :: boolean
    134   def inf?(%Decimal{coef: :inf}), do: true
    135   def inf?(%Decimal{}), do: false
    136 
    137   @doc """
    138   Returns `true` if argument is a decimal number, otherwise `false`.
    139 
    140   ## Examples
    141 
    142       iex> Decimal.is_decimal(Decimal.new(42))
    143       true
    144 
    145       iex> Decimal.is_decimal(42)
    146       false
    147 
    148   Allowed in guard tests on OTP 21+.
    149   """
    150   doc_since("1.9.0")
    151   defmacro is_decimal(term)
    152 
    153   if function_exported?(:erlang, :is_map_key, 2) do
    154     defmacro is_decimal(term) do
    155       case __CALLER__.context do
    156         nil ->
    157           quote do
    158             case unquote(term) do
    159               %Decimal{} -> true
    160               _ -> false
    161             end
    162           end
    163 
    164         :match ->
    165           raise ArgumentError,
    166                 "invalid expression in match, is_decimal is not allowed in patterns " <>
    167                   "such as function clauses, case clauses or on the left side of the = operator"
    168 
    169         :guard ->
    170           quote do
    171             is_map(unquote(term)) and :erlang.is_map_key(:__struct__, unquote(term)) and
    172               :erlang.map_get(:__struct__, unquote(term)) == Decimal
    173           end
    174       end
    175     end
    176   else
    177     # TODO: remove when we require Elixir v1.10
    178     defmacro is_decimal(term) do
    179       quote do
    180         case unquote(term) do
    181           %Decimal{} -> true
    182           _ -> false
    183         end
    184       end
    185     end
    186   end
    187 
    188   @doc """
    189   The absolute value of given number. Sets the number's sign to positive.
    190   """
    191   @spec abs(t) :: t
    192   def abs(%Decimal{coef: :NaN} = num), do: %{num | sign: 1}
    193   def abs(%Decimal{} = num), do: context(%{num | sign: 1})
    194 
    195   @doc """
    196   Adds two numbers together.
    197 
    198   ## Exceptional conditions
    199 
    200     * If one number is -Infinity and the other +Infinity, `:invalid_operation` will
    201       be signalled.
    202 
    203   ## Examples
    204 
    205       iex> Decimal.add(1, "1.1")
    206       #Decimal<2.1>
    207 
    208       iex> Decimal.add(1, "Inf")
    209       #Decimal<Infinity>
    210 
    211   """
    212   @spec add(decimal, decimal) :: t
    213   def add(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1
    214 
    215   def add(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2
    216 
    217   def add(%Decimal{coef: :inf, sign: sign} = num1, %Decimal{coef: :inf, sign: sign} = num2) do
    218     if num1.exp > num2.exp do
    219       num1
    220     else
    221       num2
    222     end
    223   end
    224 
    225   def add(%Decimal{coef: :inf}, %Decimal{coef: :inf}),
    226     do: error(:invalid_operation, "adding +Infinity and -Infinity", %Decimal{coef: :NaN})
    227 
    228   def add(%Decimal{coef: :inf} = num1, %Decimal{}), do: num1
    229 
    230   def add(%Decimal{}, %Decimal{coef: :inf} = num2), do: num2
    231 
    232   def add(%Decimal{} = num1, %Decimal{} = num2) do
    233     %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1
    234     %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2
    235 
    236     {coef1, coef2} = add_align(coef1, exp1, coef2, exp2)
    237     coef = sign1 * coef1 + sign2 * coef2
    238     exp = Kernel.min(exp1, exp2)
    239     sign = add_sign(sign1, sign2, coef)
    240     context(%Decimal{sign: sign, coef: Kernel.abs(coef), exp: exp})
    241   end
    242 
    243   def add(num1, num2), do: add(decimal(num1), decimal(num2))
    244 
    245   @doc """
    246   Subtracts second number from the first. Equivalent to `Decimal.add/2` when the
    247   second number's sign is negated.
    248 
    249   ## Exceptional conditions
    250 
    251     * If one number is -Infinity and the other +Infinity `:invalid_operation` will
    252       be signalled.
    253 
    254   ## Examples
    255 
    256       iex> Decimal.sub(1, "0.1")
    257       #Decimal<0.9>
    258 
    259       iex> Decimal.sub(1, "Inf")
    260       #Decimal<-Infinity>
    261 
    262   """
    263   @spec sub(decimal, decimal) :: t
    264   def sub(%Decimal{} = num1, %Decimal{sign: sign} = num2) do
    265     add(num1, %{num2 | sign: -sign})
    266   end
    267 
    268   def sub(num1, num2) do
    269     sub(decimal(num1), decimal(num2))
    270   end
    271 
    272   @doc """
    273   Compares two numbers numerically. If the first number is greater than the second
    274   `:gt` is returned, if less than `:lt` is returned, if both numbers are equal
    275   `:eq` is returned.
    276 
    277   Neither number can be a NaN.
    278 
    279   ## Examples
    280 
    281       iex> Decimal.compare("1.0", 1)
    282       :eq
    283 
    284       iex> Decimal.compare("Inf", -1)
    285       :gt
    286 
    287   """
    288   @spec compare(decimal, decimal) :: :lt | :gt | :eq
    289   def compare(%Decimal{coef: :inf, sign: sign}, %Decimal{coef: :inf, sign: sign}),
    290     do: :eq
    291 
    292   def compare(%Decimal{coef: :inf, sign: sign1}, %Decimal{coef: :inf, sign: sign2})
    293       when sign1 < sign2,
    294       do: :lt
    295 
    296   def compare(%Decimal{coef: :inf, sign: sign1}, %Decimal{coef: :inf, sign: sign2})
    297       when sign1 > sign2,
    298       do: :gt
    299 
    300   def compare(%Decimal{coef: :inf, sign: 1}, _num2), do: :gt
    301   def compare(%Decimal{coef: :inf, sign: -1}, _num2), do: :lt
    302 
    303   def compare(_num1, %Decimal{coef: :inf, sign: 1}), do: :lt
    304   def compare(_num1, %Decimal{coef: :inf, sign: -1}), do: :gt
    305 
    306   def compare(%Decimal{coef: :NaN} = num1, _num2),
    307     do: error(:invalid_operation, "operation on NaN", num1)
    308 
    309   def compare(_num1, %Decimal{coef: :NaN} = num2),
    310     do: error(:invalid_operation, "operation on NaN", num2)
    311 
    312   def compare(%Decimal{} = num1, %Decimal{} = num2) do
    313     case sub(num1, num2) do
    314       %Decimal{coef: 0} -> :eq
    315       %Decimal{sign: 1} -> :gt
    316       %Decimal{sign: -1} -> :lt
    317     end
    318   end
    319 
    320   def compare(num1, num2) do
    321     compare(decimal(num1), decimal(num2))
    322   end
    323 
    324   @deprecated "Use compare/2 instead"
    325   @spec cmp(decimal, decimal) :: :lt | :eq | :gt
    326   def cmp(num1, num2) do
    327     compare(num1, num2)
    328   end
    329 
    330   @doc """
    331   Compares two numbers numerically and returns `true` if they are equal,
    332   otherwise `false`. If one of the operands is a quiet NaN this operation
    333   will always return `false`.
    334 
    335   ## Examples
    336 
    337       iex> Decimal.equal?("1.0", 1)
    338       true
    339 
    340       iex> Decimal.equal?(1, -1)
    341       false
    342 
    343   """
    344   @spec equal?(decimal, decimal) :: boolean
    345   def equal?(num1, num2) do
    346     eq?(num1, num2)
    347   end
    348 
    349   @doc """
    350   Compares two numbers numerically and returns `true` if they are equal,
    351   otherwise `false`. If one of the operands is a quiet NaN this operation
    352   will always return `false`.
    353 
    354   ## Examples
    355 
    356       iex> Decimal.eq?("1.0", 1)
    357       true
    358 
    359       iex> Decimal.eq?(1, -1)
    360       false
    361 
    362   """
    363   doc_since("1.8.0")
    364   @spec eq?(decimal, decimal) :: boolean
    365   def eq?(%Decimal{coef: :NaN}, _num2), do: false
    366   def eq?(_num1, %Decimal{coef: :NaN}), do: false
    367   def eq?(num1, num2), do: compare(num1, num2) == :eq
    368 
    369   @doc """
    370   Compares two numbers numerically and returns `true` if the the first argument
    371   is greater than the second, otherwise `false`. If one the operands is a
    372   quiet NaN this operation will always return `false`.
    373 
    374   ## Examples
    375 
    376       iex> Decimal.gt?("1.3", "1.2")
    377       true
    378 
    379       iex> Decimal.gt?("1.2", "1.3")
    380       false
    381 
    382   """
    383   doc_since("1.8.0")
    384   @spec gt?(decimal, decimal) :: boolean
    385   def gt?(%Decimal{coef: :NaN}, _num2), do: false
    386   def gt?(_num1, %Decimal{coef: :NaN}), do: false
    387   def gt?(num1, num2), do: compare(num1, num2) == :gt
    388 
    389   @doc """
    390   Compares two numbers numerically and returns `true` if the the first number is
    391   less than the second number, otherwise `false`. If one of the operands is a
    392   quiet NaN this operation will always return `false`.
    393 
    394   ## Examples
    395 
    396       iex> Decimal.lt?("1.1", "1.2")
    397       true
    398 
    399       iex> Decimal.lt?("1.4", "1.2")
    400       false
    401 
    402   """
    403   doc_since("1.8.0")
    404   @spec lt?(decimal, decimal) :: boolean
    405   def lt?(%Decimal{coef: :NaN}, _num2), do: false
    406   def lt?(_num1, %Decimal{coef: :NaN}), do: false
    407   def lt?(num1, num2), do: compare(num1, num2) == :lt
    408 
    409   @doc """
    410   Divides two numbers.
    411 
    412   ## Exceptional conditions
    413 
    414     * If both numbers are ±Infinity `:invalid_operation` is signalled.
    415     * If both numbers are ±0 `:invalid_operation` is signalled.
    416     * If second number (denominator) is ±0 `:division_by_zero` is signalled.
    417 
    418   ## Examples
    419 
    420       iex> Decimal.div(3, 4)
    421       #Decimal<0.75>
    422 
    423       iex> Decimal.div("Inf", -1)
    424       #Decimal<-Infinity>
    425 
    426   """
    427   @spec div(decimal, decimal) :: t
    428   def div(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1
    429 
    430   def div(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2
    431 
    432   def div(%Decimal{coef: :inf}, %Decimal{coef: :inf}),
    433     do: error(:invalid_operation, "±Infinity / ±Infinity", %Decimal{coef: :NaN})
    434 
    435   def div(%Decimal{sign: sign1, coef: :inf} = num1, %Decimal{sign: sign2}) do
    436     sign = if sign1 == sign2, do: 1, else: -1
    437     %{num1 | sign: sign}
    438   end
    439 
    440   def div(%Decimal{sign: sign1, exp: exp1}, %Decimal{sign: sign2, coef: :inf, exp: exp2}) do
    441     sign = if sign1 == sign2, do: 1, else: -1
    442     # TODO: Subnormal
    443     # exponent?
    444     %Decimal{sign: sign, coef: 0, exp: exp1 - exp2}
    445   end
    446 
    447   def div(%Decimal{coef: 0}, %Decimal{coef: 0}),
    448     do: error(:invalid_operation, "0 / 0", %Decimal{coef: :NaN})
    449 
    450   def div(%Decimal{sign: sign1}, %Decimal{sign: sign2, coef: 0}) do
    451     sign = if sign1 == sign2, do: 1, else: -1
    452     error(:division_by_zero, nil, %Decimal{sign: sign, coef: :inf})
    453   end
    454 
    455   def div(%Decimal{} = num1, %Decimal{} = num2) do
    456     %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1
    457     %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2
    458     sign = if sign1 == sign2, do: 1, else: -1
    459 
    460     if coef1 == 0 do
    461       context(%Decimal{sign: sign, coef: 0, exp: exp1 - exp2}, [])
    462     else
    463       prec10 = pow10(Context.get().precision)
    464       {coef1, coef2, adjust} = div_adjust(coef1, coef2, 0)
    465       {coef, adjust, _rem, signals} = div_calc(coef1, coef2, 0, adjust, prec10)
    466 
    467       context(%Decimal{sign: sign, coef: coef, exp: exp1 - exp2 - adjust}, signals)
    468     end
    469   end
    470 
    471   def div(num1, num2) do
    472     div(decimal(num1), decimal(num2))
    473   end
    474 
    475   @doc """
    476   Divides two numbers and returns the integer part.
    477 
    478   ## Exceptional conditions
    479 
    480     * If both numbers are ±Infinity `:invalid_operation` is signalled.
    481     * If both numbers are ±0 `:invalid_operation` is signalled.
    482     * If second number (denominator) is ±0 `:division_by_zero` is signalled.
    483 
    484   ## Examples
    485 
    486       iex> Decimal.div_int(5, 2)
    487       #Decimal<2>
    488 
    489       iex> Decimal.div_int("Inf", -1)
    490       #Decimal<-Infinity>
    491 
    492   """
    493   @spec div_int(decimal, decimal) :: t
    494   def div_int(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1
    495 
    496   def div_int(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2
    497 
    498   def div_int(%Decimal{coef: :inf}, %Decimal{coef: :inf}),
    499     do: error(:invalid_operation, "±Infinity / ±Infinity", %Decimal{coef: :NaN})
    500 
    501   def div_int(%Decimal{sign: sign1, coef: :inf} = num1, %Decimal{sign: sign2}) do
    502     sign = if sign1 == sign2, do: 1, else: -1
    503     %{num1 | sign: sign}
    504   end
    505 
    506   def div_int(%Decimal{sign: sign1, exp: exp1}, %Decimal{sign: sign2, coef: :inf, exp: exp2}) do
    507     sign = if sign1 == sign2, do: 1, else: -1
    508     # TODO: Subnormal
    509     # exponent?
    510     %Decimal{sign: sign, coef: 0, exp: exp1 - exp2}
    511   end
    512 
    513   def div_int(%Decimal{coef: 0}, %Decimal{coef: 0}),
    514     do: error(:invalid_operation, "0 / 0", %Decimal{coef: :NaN})
    515 
    516   def div_int(%Decimal{sign: sign1}, %Decimal{sign: sign2, coef: 0}) do
    517     div_sign = if sign1 == sign2, do: 1, else: -1
    518     error(:division_by_zero, nil, %Decimal{sign: div_sign, coef: :inf})
    519   end
    520 
    521   def div_int(%Decimal{} = num1, %Decimal{} = num2) do
    522     %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1
    523     %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2
    524     div_sign = if sign1 == sign2, do: 1, else: -1
    525 
    526     cond do
    527       compare(%{num1 | sign: 1}, %{num2 | sign: 1}) == :lt ->
    528         %Decimal{sign: div_sign, coef: 0, exp: exp1 - exp2}
    529 
    530       coef1 == 0 ->
    531         context(%{num1 | sign: div_sign})
    532 
    533       true ->
    534         case integer_division(div_sign, coef1, exp1, coef2, exp2) do
    535           {:ok, result} ->
    536             result
    537 
    538           {:error, error, reason, num} ->
    539             error(error, reason, num)
    540         end
    541     end
    542   end
    543 
    544   def div_int(num1, num2) do
    545     div_int(decimal(num1), decimal(num2))
    546   end
    547 
    548   @doc """
    549   Remainder of integer division of two numbers. The result will have the sign of
    550   the first number.
    551 
    552   ## Exceptional conditions
    553 
    554     * If both numbers are ±Infinity `:invalid_operation` is signalled.
    555     * If both numbers are ±0 `:invalid_operation` is signalled.
    556     * If second number (denominator) is ±0 `:division_by_zero` is signalled.
    557 
    558   ## Examples
    559 
    560       iex> Decimal.rem(5, 2)
    561       #Decimal<1>
    562 
    563   """
    564   @spec rem(decimal, decimal) :: t
    565   def rem(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1
    566 
    567   def rem(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2
    568 
    569   def rem(%Decimal{coef: :inf}, %Decimal{coef: :inf}),
    570     do: error(:invalid_operation, "±Infinity / ±Infinity", %Decimal{coef: :NaN})
    571 
    572   def rem(%Decimal{sign: sign1, coef: :inf}, %Decimal{}), do: %Decimal{sign: sign1, coef: 0}
    573 
    574   def rem(%Decimal{sign: sign1}, %Decimal{coef: :inf} = num2) do
    575     # TODO: Subnormal
    576     # exponent?
    577     %{num2 | sign: sign1}
    578   end
    579 
    580   def rem(%Decimal{coef: 0}, %Decimal{coef: 0}),
    581     do: error(:invalid_operation, "0 / 0", %Decimal{coef: :NaN})
    582 
    583   def rem(%Decimal{sign: sign1}, %Decimal{coef: 0}),
    584     do: error(:division_by_zero, nil, %Decimal{sign: sign1, coef: 0})
    585 
    586   def rem(%Decimal{} = num1, %Decimal{} = num2) do
    587     %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1
    588     %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2
    589 
    590     cond do
    591       compare(%{num1 | sign: 1}, %{num2 | sign: 1}) == :lt ->
    592         %{num1 | sign: sign1}
    593 
    594       coef1 == 0 ->
    595         context(%{num2 | sign: sign1})
    596 
    597       true ->
    598         div_sign = if sign1 == sign2, do: 1, else: -1
    599 
    600         case integer_division(div_sign, coef1, exp1, coef2, exp2) do
    601           {:ok, result} ->
    602             sub(num1, mult(num2, result))
    603 
    604           {:error, error, reason, num} ->
    605             error(error, reason, num)
    606         end
    607     end
    608   end
    609 
    610   def rem(num1, num2) do
    611     rem(decimal(num1), decimal(num2))
    612   end
    613 
    614   @doc """
    615   Integer division of two numbers and the remainder. Should be used when both
    616   `div_int/2` and `rem/2` is needed. Equivalent to: `{Decimal.div_int(x, y),
    617   Decimal.rem(x, y)}`.
    618 
    619   ## Exceptional conditions
    620 
    621     * If both numbers are ±Infinity `:invalid_operation` is signalled.
    622     * If both numbers are ±0 `:invalid_operation` is signalled.
    623     * If second number (denominator) is ±0 `:division_by_zero` is signalled.
    624 
    625   ## Examples
    626 
    627       iex> Decimal.div_rem(5, 2)
    628       {Decimal.new(2), Decimal.new(1)}
    629 
    630   """
    631   @spec div_rem(decimal, decimal) :: {t, t}
    632   def div_rem(%Decimal{coef: :NaN} = num1, %Decimal{}), do: {num1, num1}
    633 
    634   def div_rem(%Decimal{}, %Decimal{coef: :NaN} = num2), do: {num2, num2}
    635 
    636   def div_rem(%Decimal{coef: :inf}, %Decimal{coef: :inf}) do
    637     numbers = {%Decimal{coef: :NaN}, %Decimal{coef: :NaN}}
    638     error(:invalid_operation, "±Infinity / ±Infinity", numbers)
    639   end
    640 
    641   def div_rem(%Decimal{sign: sign1, coef: :inf} = num1, %Decimal{sign: sign2}) do
    642     sign = if sign1 == sign2, do: 1, else: -1
    643     {%{num1 | sign: sign}, %Decimal{sign: sign1, coef: 0}}
    644   end
    645 
    646   def div_rem(%Decimal{} = num1, %Decimal{coef: :inf} = num2) do
    647     %Decimal{sign: sign1, exp: exp1} = num1
    648     %Decimal{sign: sign2, exp: exp2} = num2
    649 
    650     sign = if sign1 == sign2, do: 1, else: -1
    651     # TODO: Subnormal
    652     # exponent?
    653     {%Decimal{sign: sign, coef: 0, exp: exp1 - exp2}, %{num2 | sign: sign1}}
    654   end
    655 
    656   def div_rem(%Decimal{coef: 0}, %Decimal{coef: 0}) do
    657     error = error(:invalid_operation, "0 / 0", %Decimal{coef: :NaN})
    658     {error, error}
    659   end
    660 
    661   def div_rem(%Decimal{sign: sign1}, %Decimal{sign: sign2, coef: 0}) do
    662     div_sign = if sign1 == sign2, do: 1, else: -1
    663     div_error = error(:division_by_zero, nil, %Decimal{sign: div_sign, coef: :inf})
    664     rem_error = error(:division_by_zero, nil, %Decimal{sign: sign1, coef: 0})
    665     {div_error, rem_error}
    666   end
    667 
    668   def div_rem(%Decimal{} = num1, %Decimal{} = num2) do
    669     %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1
    670     %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2
    671     div_sign = if sign1 == sign2, do: 1, else: -1
    672 
    673     cond do
    674       compare(%{num1 | sign: 1}, %{num2 | sign: 1}) == :lt ->
    675         {%Decimal{sign: div_sign, coef: 0, exp: exp1 - exp2}, %{num1 | sign: sign1}}
    676 
    677       coef1 == 0 ->
    678         {context(%{num1 | sign: div_sign}), context(%{num2 | sign: sign1})}
    679 
    680       true ->
    681         case integer_division(div_sign, coef1, exp1, coef2, exp2) do
    682           {:ok, result} ->
    683             {result, sub(num1, mult(num2, result))}
    684 
    685           {:error, error, reason, num} ->
    686             error(error, reason, {num, num})
    687         end
    688     end
    689   end
    690 
    691   def div_rem(num1, num2) do
    692     div_rem(decimal(num1), decimal(num2))
    693   end
    694 
    695   @doc """
    696   Compares two values numerically and returns the maximum. Unlike most other
    697   functions in `Decimal` if a number is NaN the result will be the other number.
    698   Only if both numbers are NaN will NaN be returned.
    699 
    700   ## Examples
    701 
    702       iex> Decimal.max(1, "2.0")
    703       #Decimal<2.0>
    704 
    705       iex> Decimal.max(1, "NaN")
    706       #Decimal<1>
    707 
    708       iex> Decimal.max("NaN", "NaN")
    709       #Decimal<NaN>
    710 
    711   """
    712   @spec max(decimal, decimal) :: t
    713   def max(%Decimal{coef: :NaN}, %Decimal{} = num2), do: num2
    714 
    715   def max(%Decimal{} = num1, %Decimal{coef: :NaN}), do: num1
    716 
    717   def max(%Decimal{sign: sign1, exp: exp1} = num1, %Decimal{sign: sign2, exp: exp2} = num2) do
    718     case compare(num1, num2) do
    719       :lt ->
    720         num2
    721 
    722       :gt ->
    723         num1
    724 
    725       :eq ->
    726         cond do
    727           sign1 != sign2 ->
    728             if sign1 == 1, do: num1, else: num2
    729 
    730           sign1 == 1 ->
    731             if exp1 > exp2, do: num1, else: num2
    732 
    733           sign1 == -1 ->
    734             if exp1 < exp2, do: num1, else: num2
    735         end
    736     end
    737     |> context()
    738   end
    739 
    740   def max(num1, num2) do
    741     max(decimal(num1), decimal(num2))
    742   end
    743 
    744   @doc """
    745   Compares two values numerically and returns the minimum. Unlike most other
    746   functions in `Decimal` if a number is NaN the result will be the other number.
    747   Only if both numbers are NaN will NaN be returned.
    748 
    749   ## Examples
    750 
    751       iex> Decimal.min(1, "2.0")
    752       #Decimal<1>
    753 
    754       iex> Decimal.min(1, "NaN")
    755       #Decimal<1>
    756 
    757       iex> Decimal.min("NaN", "NaN")
    758       #Decimal<NaN>
    759 
    760   """
    761   @spec min(decimal, decimal) :: t
    762   def min(%Decimal{coef: :NaN}, %Decimal{} = num2), do: num2
    763 
    764   def min(%Decimal{} = num1, %Decimal{coef: :NaN}), do: num1
    765 
    766   def min(%Decimal{sign: sign1, exp: exp1} = num1, %Decimal{sign: sign2, exp: exp2} = num2) do
    767     case compare(num1, num2) do
    768       :lt ->
    769         num1
    770 
    771       :gt ->
    772         num2
    773 
    774       :eq ->
    775         cond do
    776           sign1 != sign2 ->
    777             if sign1 == -1, do: num1, else: num2
    778 
    779           sign1 == 1 ->
    780             if exp1 < exp2, do: num1, else: num2
    781 
    782           sign1 == -1 ->
    783             if exp1 > exp2, do: num1, else: num2
    784         end
    785     end
    786     |> context()
    787   end
    788 
    789   def min(num1, num2) do
    790     min(decimal(num1), decimal(num2))
    791   end
    792 
    793   @doc """
    794   Negates the given number.
    795 
    796   ## Examples
    797 
    798       iex> Decimal.negate(1)
    799       #Decimal<-1>
    800 
    801       iex> Decimal.negate("-Inf")
    802       #Decimal<Infinity>
    803 
    804   """
    805   doc_since("1.9.0")
    806   @spec negate(decimal) :: t
    807   def negate(%Decimal{coef: :NaN} = num), do: num
    808   def negate(%Decimal{sign: sign} = num), do: context(%{num | sign: -sign})
    809   def negate(num), do: negate(decimal(num))
    810 
    811   @doc """
    812   Applies the context to the given number rounding it to specified precision.
    813   """
    814   doc_since("1.9.0")
    815   @spec apply_context(t) :: t
    816   def apply_context(%Decimal{} = num), do: context(num)
    817 
    818   @doc """
    819   Check if given number is positive
    820   """
    821   doc_since("1.5.0")
    822   @spec positive?(t) :: boolean
    823   def positive?(%Decimal{coef: :NaN}), do: false
    824   def positive?(%Decimal{coef: 0}), do: false
    825   def positive?(%Decimal{sign: -1}), do: false
    826   def positive?(%Decimal{sign: 1}), do: true
    827 
    828   @doc """
    829   Check if given number is negative
    830   """
    831   doc_since("1.5.0")
    832   @spec negative?(t) :: boolean
    833   def negative?(%Decimal{coef: :NaN}), do: false
    834   def negative?(%Decimal{coef: 0}), do: false
    835   def negative?(%Decimal{sign: 1}), do: false
    836   def negative?(%Decimal{sign: -1}), do: true
    837 
    838   @doc """
    839   Multiplies two numbers.
    840 
    841   ## Exceptional conditions
    842 
    843     * If one number is ±0 and the other is ±Infinity `:invalid_operation` is
    844       signalled.
    845 
    846   ## Examples
    847 
    848       iex> Decimal.mult("0.5", 3)
    849       #Decimal<1.5>
    850 
    851       iex> Decimal.mult("Inf", -1)
    852       #Decimal<-Infinity>
    853 
    854   """
    855   @spec mult(decimal, decimal) :: t
    856   def mult(%Decimal{coef: :NaN} = num1, %Decimal{}), do: num1
    857 
    858   def mult(%Decimal{}, %Decimal{coef: :NaN} = num2), do: num2
    859 
    860   def mult(%Decimal{coef: 0}, %Decimal{coef: :inf}),
    861     do: error(:invalid_operation, "0 * ±Infinity", %Decimal{coef: :NaN})
    862 
    863   def mult(%Decimal{coef: :inf}, %Decimal{coef: 0}),
    864     do: error(:invalid_operation, "0 * ±Infinity", %Decimal{coef: :NaN})
    865 
    866   def mult(%Decimal{sign: sign1, coef: :inf, exp: exp1}, %Decimal{sign: sign2, exp: exp2}) do
    867     sign = if sign1 == sign2, do: 1, else: -1
    868     # exponent?
    869     %Decimal{sign: sign, coef: :inf, exp: exp1 + exp2}
    870   end
    871 
    872   def mult(%Decimal{sign: sign1, exp: exp1}, %Decimal{sign: sign2, coef: :inf, exp: exp2}) do
    873     sign = if sign1 == sign2, do: 1, else: -1
    874     # exponent?
    875     %Decimal{sign: sign, coef: :inf, exp: exp1 + exp2}
    876   end
    877 
    878   def mult(%Decimal{} = num1, %Decimal{} = num2) do
    879     %Decimal{sign: sign1, coef: coef1, exp: exp1} = num1
    880     %Decimal{sign: sign2, coef: coef2, exp: exp2} = num2
    881     sign = if sign1 == sign2, do: 1, else: -1
    882     %Decimal{sign: sign, coef: coef1 * coef2, exp: exp1 + exp2} |> context()
    883   end
    884 
    885   def mult(num1, num2) do
    886     mult(decimal(num1), decimal(num2))
    887   end
    888 
    889   @doc """
    890   Normalizes the given decimal: removes trailing zeros from coefficient while
    891   keeping the number numerically equivalent by increasing the exponent.
    892 
    893   ## Examples
    894 
    895       iex> Decimal.normalize(Decimal.new("1.00"))
    896       #Decimal<1>
    897 
    898       iex> Decimal.normalize(Decimal.new("1.01"))
    899       #Decimal<1.01>
    900 
    901   """
    902   doc_since("1.9.0")
    903   @spec normalize(t) :: t
    904   def normalize(%Decimal{coef: :NaN} = num), do: num
    905 
    906   def normalize(%Decimal{coef: :inf} = num) do
    907     # exponent?
    908     %{num | exp: 0}
    909   end
    910 
    911   def normalize(%Decimal{sign: sign, coef: coef, exp: exp}) do
    912     if coef == 0 do
    913       %Decimal{sign: sign, coef: 0, exp: 0}
    914     else
    915       %{do_normalize(coef, exp) | sign: sign} |> context
    916     end
    917   end
    918 
    919   @doc """
    920   Rounds the given number to specified decimal places with the given strategy
    921   (default is to round to nearest one). If places is negative, at least that
    922   many digits to the left of the decimal point will be zero.
    923 
    924   See `Decimal.Context` for more information about rounding algorithms.
    925 
    926   ## Examples
    927 
    928       iex> Decimal.round("1.234")
    929       #Decimal<1>
    930 
    931       iex> Decimal.round("1.234", 1)
    932       #Decimal<1.2>
    933 
    934   """
    935   @spec round(decimal, integer, rounding) :: t
    936   def round(num, places \\ 0, mode \\ :half_up)
    937 
    938   def round(%Decimal{coef: :NaN} = num, _, _), do: num
    939 
    940   def round(%Decimal{coef: :inf} = num, _, _), do: num
    941 
    942   def round(%Decimal{} = num, n, mode) do
    943     %Decimal{sign: sign, coef: coef, exp: exp} = normalize(num)
    944     digits = :erlang.integer_to_list(coef)
    945     target_exp = -n
    946     value = do_round(sign, digits, exp, target_exp, mode)
    947     context(value, [])
    948   end
    949 
    950   def round(num, n, mode) do
    951     round(decimal(num), n, mode)
    952   end
    953 
    954   @doc """
    955   Finds the square root.
    956 
    957   ## Examples
    958 
    959       iex> Decimal.sqrt("100")
    960       #Decimal<10>
    961 
    962   """
    963   doc_since("1.7.0")
    964   @spec sqrt(decimal) :: t
    965   def sqrt(%Decimal{coef: :NaN} = num),
    966     do: error(:invalid_operation, "operation on NaN", num)
    967 
    968   def sqrt(%Decimal{coef: 0, exp: exp} = num),
    969     do: %{num | exp: exp >>> 1}
    970 
    971   def sqrt(%Decimal{sign: -1} = num),
    972     do: error(:invalid_operation, "less than zero", num)
    973 
    974   def sqrt(%Decimal{sign: 1, coef: :inf} = num),
    975     do: num
    976 
    977   def sqrt(%Decimal{sign: 1, coef: coef, exp: exp}) do
    978     precision = Context.get().precision + 1
    979     digits = :erlang.integer_to_list(coef)
    980     num_digits = length(digits)
    981 
    982     # Since the root is calculated from integer operations only, it must be
    983     # large enough to contain the desired precision. Calculate the amount of
    984     # `shift` required (powers of 10).
    985     case exp &&& 1 do
    986       0 ->
    987         # To get the desired `shift`, subtract the precision of `coef`'s square
    988         # root from the desired precision.
    989         #
    990         # If `coef` is 10_000, the root is 100 (3 digits of precision).
    991         # If `coef` is 100, the root is 10 (2 digits of precision).
    992         shift = precision - ((num_digits + 1) >>> 1)
    993         sqrt(coef, shift, exp)
    994 
    995       _ ->
    996         # If `exp` is odd, multiply `coef` by 10 and reduce shift by 1/2. `exp`
    997         # must be even so the root's exponent is an integer.
    998         shift = precision - ((num_digits >>> 1) + 1)
    999         sqrt(coef * 10, shift, exp)
   1000     end
   1001   end
   1002 
   1003   def sqrt(num) do
   1004     sqrt(decimal(num))
   1005   end
   1006 
   1007   defp sqrt(coef, shift, exp) do
   1008     if shift >= 0 do
   1009       # shift `coef` up by `shift * 2` digits
   1010       sqrt(coef * pow10(shift <<< 1), shift, exp, true)
   1011     else
   1012       # shift `coef` down by `shift * 2` digits
   1013       operand = pow10(-shift <<< 1)
   1014       sqrt(Kernel.div(coef, operand), shift, exp, Kernel.rem(coef, operand) === 0)
   1015     end
   1016   end
   1017 
   1018   defp sqrt(shifted_coef, shift, exp, exact) do
   1019     # the preferred exponent is `exp / 2` as per IEEE 754
   1020     exp = exp >>> 1
   1021     # guess a root 10x higher than desired precision
   1022     guess = pow10(Context.get().precision + 1)
   1023     root = sqrt_loop(shifted_coef, guess)
   1024 
   1025     if exact and root * root === shifted_coef do
   1026       # if the root is exact, use preferred `exp` and shift `coef` to match
   1027       coef =
   1028         if shift >= 0,
   1029           do: Kernel.div(root, pow10(shift)),
   1030           else: root * pow10(-shift)
   1031 
   1032       context(%Decimal{sign: 1, coef: coef, exp: exp})
   1033     else
   1034       # otherwise the calculated root is inexact (but still meets precision),
   1035       # so use the root as `coef` and get the final exponent by shifting `exp`
   1036       context(%Decimal{sign: 1, coef: root, exp: exp - shift})
   1037     end
   1038   end
   1039 
   1040   # Babylonion method
   1041   defp sqrt_loop(coef, guess) do
   1042     quotient = Kernel.div(coef, guess)
   1043 
   1044     if guess <= quotient do
   1045       guess
   1046     else
   1047       sqrt_loop(coef, (guess + quotient) >>> 1)
   1048     end
   1049   end
   1050 
   1051   @doc """
   1052   Creates a new decimal number from an integer or a string representation.
   1053 
   1054   A decimal number will always be created exactly as specified with all digits
   1055   kept - it will not be rounded with the context.
   1056 
   1057   ## Backus–Naur form
   1058 
   1059       sign           ::=  "+" | "-"
   1060       digit          ::=  "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
   1061       indicator      ::=  "e" | "E"
   1062       digits         ::=  digit [digit]...
   1063       decimal-part   ::=  digits "." [digits] | ["."] digits
   1064       exponent-part  ::=  indicator [sign] digits
   1065       infinity       ::=  "Infinity" | "Inf"
   1066       nan            ::=  "NaN" [digits]
   1067       numeric-value  ::=  decimal-part [exponent-part] | infinity
   1068       numeric-string ::=  [sign] numeric-value | [sign] nan
   1069 
   1070   ## Floats
   1071 
   1072   See also `from_float/1`.
   1073 
   1074   ## Examples
   1075 
   1076       iex> Decimal.new(1)
   1077       #Decimal<1>
   1078 
   1079       iex> Decimal.new("3.14")
   1080       #Decimal<3.14>
   1081   """
   1082   @spec new(decimal) :: t
   1083   def new(%Decimal{sign: sign, coef: coef, exp: exp} = num)
   1084       when sign in [1, -1] and ((is_integer(coef) and coef >= 0) or coef in [:NaN, :inf]) and
   1085              is_integer(exp),
   1086       do: num
   1087 
   1088   def new(int) when is_integer(int),
   1089     do: %Decimal{sign: if(int < 0, do: -1, else: 1), coef: Kernel.abs(int)}
   1090 
   1091   def new(binary) when is_binary(binary) do
   1092     case parse(binary) do
   1093       {decimal, ""} -> decimal
   1094       _ -> raise Error, reason: "number parsing syntax: #{inspect(binary)}"
   1095     end
   1096   end
   1097 
   1098   @doc """
   1099   Creates a new decimal number from the sign, coefficient and exponent such that
   1100   the number will be: `sign * coefficient * 10 ^ exponent`.
   1101 
   1102   A decimal number will always be created exactly as specified with all digits
   1103   kept - it will not be rounded with the context.
   1104   """
   1105   @spec new(1 | -1, non_neg_integer | :NaN | :inf, integer) :: t
   1106   def new(sign, coef, exp)
   1107       when sign in [1, -1] and ((is_integer(coef) and coef >= 0) or coef in [:NaN, :inf]) and
   1108              is_integer(exp),
   1109       do: %Decimal{sign: sign, coef: coef, exp: exp}
   1110 
   1111   @doc """
   1112   Creates a new decimal number from a floating point number.
   1113 
   1114   Floating point numbers use a fixed number of binary digits to represent
   1115   a decimal number which has inherent inaccuracy as some decimal numbers cannot
   1116   be represented exactly in limited precision binary.
   1117 
   1118   Floating point numbers will be converted to decimal numbers with
   1119   `:io_lib_format.fwrite_g/1`. Since this conversion is not exact and
   1120   because of inherent inaccuracy mentioned above, we may run into counter-intuitive results:
   1121 
   1122       iex> Enum.reduce([0.1, 0.1, 0.1], &+/2)
   1123       0.30000000000000004
   1124 
   1125       iex> Enum.reduce([Decimal.new("0.1"), Decimal.new("0.1"), Decimal.new("0.1")], &Decimal.add/2)
   1126       #Decimal<0.3>
   1127 
   1128   For this reason, it's recommended to build decimals with `new/1`, which is always precise, instead.
   1129 
   1130   ## Examples
   1131 
   1132       iex> Decimal.from_float(3.14)
   1133       #Decimal<3.14>
   1134 
   1135   """
   1136   doc_since("1.5.0")
   1137   @spec from_float(float) :: t
   1138   def from_float(float) when is_float(float) do
   1139     float
   1140     |> :io_lib_format.fwrite_g()
   1141     |> fix_float_exp()
   1142     |> IO.iodata_to_binary()
   1143     |> new()
   1144   end
   1145 
   1146   @doc """
   1147   Creates a new decimal number from an integer, string, float, or existing decimal number.
   1148 
   1149   Because conversion from a floating point number is not exact, it's recommended
   1150   to instead use `new/1` or `from_float/1` when the argument's type is certain.
   1151   See `from_float/1`.
   1152 
   1153   ## Examples
   1154 
   1155       iex> {:ok, decimal} = Decimal.cast(3)
   1156       iex> decimal
   1157       #Decimal<3>
   1158 
   1159       iex> Decimal.cast("bad")
   1160       :error
   1161 
   1162   """
   1163   @spec cast(term) :: {:ok, t} | :error
   1164   def cast(integer) when is_integer(integer), do: {:ok, Decimal.new(integer)}
   1165   def cast(%Decimal{} = decimal), do: {:ok, decimal}
   1166   def cast(float) when is_float(float), do: {:ok, from_float(float)}
   1167 
   1168   def cast(binary) when is_binary(binary) do
   1169     case parse(binary) do
   1170       {decimal, ""} -> {:ok, decimal}
   1171       _ -> :error
   1172     end
   1173   end
   1174 
   1175   def cast(_), do: :error
   1176 
   1177   @doc """
   1178   Parses a binary into a decimal.
   1179 
   1180   If successful, returns a tuple in the form of `{decimal, remainder_of_binary}`,
   1181   otherwise `:error`.
   1182 
   1183   ## Examples
   1184 
   1185       iex> Decimal.parse("3.14")
   1186       {%Decimal{coef: 314, exp: -2, sign: 1}, ""}
   1187 
   1188       iex> Decimal.parse("3.14.15")
   1189       {%Decimal{coef: 314, exp: -2, sign: 1}, ".15"}
   1190 
   1191       iex> Decimal.parse("-1.1e3")
   1192       {%Decimal{coef: 11, exp: 2, sign: -1}, ""}
   1193 
   1194       iex> Decimal.parse("bad")
   1195       :error
   1196 
   1197   """
   1198   @spec parse(binary()) :: {t(), binary()} | :error
   1199   def parse("+" <> rest) do
   1200     parse_unsign(rest)
   1201   end
   1202 
   1203   def parse("-" <> rest) do
   1204     case parse_unsign(rest) do
   1205       {%Decimal{} = num, rest} -> {%{num | sign: -1}, rest}
   1206       :error -> :error
   1207     end
   1208   end
   1209 
   1210   def parse(binary) when is_binary(binary) do
   1211     parse_unsign(binary)
   1212   end
   1213 
   1214   @doc """
   1215   Converts given number to its string representation.
   1216 
   1217   ## Options
   1218 
   1219     * `:scientific` - number converted to scientific notation.
   1220     * `:normal` - number converted without a exponent.
   1221     * `:xsd` - number converted to the [canonical XSD representation](https://www.w3.org/TR/xmlschema-2/#decimal).
   1222     * `:raw` - number converted to its raw, internal format.
   1223 
   1224   """
   1225   @spec to_string(t, :scientific | :normal | :xsd | :raw) :: String.t()
   1226   def to_string(num, type \\ :scientific)
   1227 
   1228   def to_string(%Decimal{sign: sign, coef: :NaN}, _type) do
   1229     if sign == 1, do: "NaN", else: "-NaN"
   1230   end
   1231 
   1232   def to_string(%Decimal{sign: sign, coef: :inf}, _type) do
   1233     if sign == 1, do: "Infinity", else: "-Infinity"
   1234   end
   1235 
   1236   def to_string(%Decimal{sign: sign, coef: coef, exp: exp}, :normal) do
   1237     list = integer_to_charlist(coef)
   1238 
   1239     list =
   1240       if exp >= 0 do
   1241         list ++ :lists.duplicate(exp, ?0)
   1242       else
   1243         diff = length(list) + exp
   1244 
   1245         if diff > 0 do
   1246           List.insert_at(list, diff, ?.)
   1247         else
   1248           '0.' ++ :lists.duplicate(-diff, ?0) ++ list
   1249         end
   1250       end
   1251 
   1252     list = if sign == -1, do: [?- | list], else: list
   1253     IO.iodata_to_binary(list)
   1254   end
   1255 
   1256   def to_string(%Decimal{sign: sign, coef: coef, exp: exp}, :scientific) do
   1257     list = integer_to_charlist(coef)
   1258     length = length(list)
   1259     adjusted = exp + length - 1
   1260 
   1261     list =
   1262       cond do
   1263         exp == 0 ->
   1264           list
   1265 
   1266         exp < 0 and adjusted >= -6 ->
   1267           abs_exp = Kernel.abs(exp)
   1268           diff = -length + abs_exp + 1
   1269 
   1270           if diff > 0 do
   1271             list = :lists.duplicate(diff, ?0) ++ list
   1272             List.insert_at(list, 1, ?.)
   1273           else
   1274             List.insert_at(list, exp - 1, ?.)
   1275           end
   1276 
   1277         true ->
   1278           list = if length > 1, do: List.insert_at(list, 1, ?.), else: list
   1279           list = list ++ 'E'
   1280           list = if exp >= 0, do: list ++ '+', else: list
   1281           list ++ integer_to_charlist(adjusted)
   1282       end
   1283 
   1284     list = if sign == -1, do: [?- | list], else: list
   1285     IO.iodata_to_binary(list)
   1286   end
   1287 
   1288   def to_string(%Decimal{sign: sign, coef: coef, exp: exp}, :raw) do
   1289     str = Integer.to_string(coef)
   1290     str = if sign == -1, do: [?- | str], else: str
   1291     str = if exp != 0, do: [str, "E", Integer.to_string(exp)], else: str
   1292 
   1293     IO.iodata_to_binary(str)
   1294   end
   1295 
   1296   def to_string(%Decimal{} = decimal, :xsd) do
   1297     decimal |> canonical_xsd() |> to_string(:normal)
   1298   end
   1299 
   1300   defp canonical_xsd(%Decimal{coef: 0} = decimal), do: %{decimal | exp: -1}
   1301 
   1302   defp canonical_xsd(%Decimal{coef: coef, exp: 0} = decimal),
   1303     do: %{decimal | coef: coef * 10, exp: -1}
   1304 
   1305   defp canonical_xsd(%Decimal{coef: coef, exp: exp} = decimal)
   1306        when exp > 0,
   1307        do: canonical_xsd(%{decimal | coef: coef * 10, exp: exp - 1})
   1308 
   1309   defp canonical_xsd(%Decimal{coef: coef} = decimal)
   1310        when Kernel.rem(coef, 10) != 0,
   1311        do: decimal
   1312 
   1313   defp canonical_xsd(%Decimal{coef: coef, exp: exp} = decimal),
   1314     do: canonical_xsd(%{decimal | coef: Kernel.div(coef, 10), exp: exp + 1})
   1315 
   1316   @doc """
   1317   Returns the decimal represented as an integer.
   1318 
   1319   Fails when loss of precision will occur.
   1320   """
   1321   @spec to_integer(t) :: integer
   1322   def to_integer(%Decimal{sign: sign, coef: coef, exp: 0})
   1323       when is_integer(coef),
   1324       do: sign * coef
   1325 
   1326   def to_integer(%Decimal{sign: sign, coef: coef, exp: exp})
   1327       when is_integer(coef) and exp > 0,
   1328       do: to_integer(%Decimal{sign: sign, coef: coef * 10, exp: exp - 1})
   1329 
   1330   def to_integer(%Decimal{sign: sign, coef: coef, exp: exp})
   1331       when is_integer(coef) and exp < 0 and Kernel.rem(coef, 10) == 0,
   1332       do: to_integer(%Decimal{sign: sign, coef: Kernel.div(coef, 10), exp: exp + 1})
   1333 
   1334   @doc """
   1335   Returns the decimal converted to a float.
   1336 
   1337   The returned float may have lower precision than the decimal. Fails if
   1338   the decimal cannot be converted to a float.
   1339   """
   1340   @spec to_float(t) :: float
   1341   def to_float(%Decimal{sign: sign, coef: coef, exp: exp}) when is_integer(coef) do
   1342     # Convert back to float without loss
   1343     # http://www.exploringbinary.com/correct-decimal-to-floating-point-using-big-integers/
   1344     {num, den} = ratio(coef, exp)
   1345 
   1346     boundary = den <<< 52
   1347 
   1348     cond do
   1349       num == 0 ->
   1350         0.0
   1351 
   1352       num >= boundary ->
   1353         {den, exp} = scale_down(num, boundary, 52)
   1354         decimal_to_float(sign, num, den, exp)
   1355 
   1356       true ->
   1357         {num, exp} = scale_up(num, boundary, 52)
   1358         decimal_to_float(sign, num, den, exp)
   1359     end
   1360   end
   1361 
   1362   defp scale_up(num, den, exp) when num >= den, do: {num, exp}
   1363   defp scale_up(num, den, exp), do: scale_up(num <<< 1, den, exp - 1)
   1364 
   1365   defp scale_down(num, den, exp) do
   1366     new_den = den <<< 1
   1367 
   1368     if num < new_den do
   1369       {den >>> 52, exp}
   1370     else
   1371       scale_down(num, new_den, exp + 1)
   1372     end
   1373   end
   1374 
   1375   defp decimal_to_float(sign, num, den, exp) do
   1376     quo = Kernel.div(num, den)
   1377     rem = num - quo * den
   1378 
   1379     tmp =
   1380       case den >>> 1 do
   1381         den when rem > den -> quo + 1
   1382         den when rem < den -> quo
   1383         _ when (quo &&& 1) === 1 -> quo + 1
   1384         _ -> quo
   1385       end
   1386 
   1387     sign = if sign == -1, do: 1, else: 0
   1388     tmp = tmp - @power_of_2_to_52
   1389     exp = if tmp < @power_of_2_to_52, do: exp, else: exp + 1
   1390     <<tmp::float>> = <<sign::size(1), exp + 1023::size(11), tmp::size(52)>>
   1391     tmp
   1392   end
   1393 
   1394   @doc """
   1395   Returns `true` when the given `decimal` has no significant digits after the decimal point.
   1396 
   1397   ## Examples
   1398 
   1399       iex> Decimal.integer?("1.00")
   1400       true
   1401 
   1402       iex> Decimal.integer?("1.10")
   1403       false
   1404   """
   1405   doc_since("2.0.0")
   1406   @spec integer?(t) :: boolean
   1407   def integer?(%Decimal{coef: :NaN}), do: false
   1408   def integer?(%Decimal{coef: :inf}), do: false
   1409   def integer?(%Decimal{coef: coef, exp: exp}), do: exp >= 0 or zero_after_dot?(coef, exp)
   1410   def integer?(num), do: integer?(decimal(num))
   1411 
   1412   defp zero_after_dot?(coef, exp) when coef >= 10 and exp < 0,
   1413     do: Kernel.rem(coef, 10) == 0 and zero_after_dot?(Kernel.div(coef, 10), exp + 1)
   1414 
   1415   defp zero_after_dot?(_coef, exp),
   1416     do: exp == 0
   1417 
   1418   ## ARITHMETIC ##
   1419 
   1420   defp add_align(coef1, exp1, coef2, exp2) when exp1 == exp2, do: {coef1, coef2}
   1421 
   1422   defp add_align(coef1, exp1, coef2, exp2) when exp1 > exp2,
   1423     do: {coef1 * pow10(exp1 - exp2), coef2}
   1424 
   1425   defp add_align(coef1, exp1, coef2, exp2) when exp1 < exp2,
   1426     do: {coef1, coef2 * pow10(exp2 - exp1)}
   1427 
   1428   defp add_sign(sign1, sign2, coef) do
   1429     cond do
   1430       coef > 0 -> 1
   1431       coef < 0 -> -1
   1432       sign1 == -1 and sign2 == -1 -> -1
   1433       sign1 != sign2 and Context.get().rounding == :floor -> -1
   1434       true -> 1
   1435     end
   1436   end
   1437 
   1438   defp div_adjust(coef1, coef2, adjust) when coef1 < coef2,
   1439     do: div_adjust(coef1 * 10, coef2, adjust + 1)
   1440 
   1441   defp div_adjust(coef1, coef2, adjust) when coef1 >= coef2 * 10,
   1442     do: div_adjust(coef1, coef2 * 10, adjust - 1)
   1443 
   1444   defp div_adjust(coef1, coef2, adjust), do: {coef1, coef2, adjust}
   1445 
   1446   defp div_calc(coef1, coef2, coef, adjust, prec10) do
   1447     cond do
   1448       coef1 >= coef2 ->
   1449         div_calc(coef1 - coef2, coef2, coef + 1, adjust, prec10)
   1450 
   1451       coef1 == 0 and adjust >= 0 ->
   1452         {coef, adjust, coef1, []}
   1453 
   1454       coef >= prec10 ->
   1455         signals = [:rounded]
   1456         signals = if base10?(coef1), do: signals, else: [:inexact | signals]
   1457         {coef, adjust, coef1, signals}
   1458 
   1459       true ->
   1460         div_calc(coef1 * 10, coef2, coef * 10, adjust + 1, prec10)
   1461     end
   1462   end
   1463 
   1464   defp div_int_calc(coef1, coef2, coef, adjust, precision) do
   1465     cond do
   1466       coef1 >= coef2 ->
   1467         div_int_calc(coef1 - coef2, coef2, coef + 1, adjust, precision)
   1468 
   1469       adjust != precision ->
   1470         div_int_calc(coef1 * 10, coef2, coef * 10, adjust + 1, precision)
   1471 
   1472       true ->
   1473         {coef, coef1}
   1474     end
   1475   end
   1476 
   1477   defp integer_division(div_sign, coef1, exp1, coef2, exp2) do
   1478     precision = exp1 - exp2
   1479     {coef1, coef2, adjust} = div_adjust(coef1, coef2, 0)
   1480 
   1481     {coef, _rem} = div_int_calc(coef1, coef2, 0, adjust, precision)
   1482 
   1483     prec10 = pow10(Context.get().precision)
   1484 
   1485     if coef > prec10 do
   1486       {
   1487         :error,
   1488         :invalid_operation,
   1489         "integer division impossible, quotient too large",
   1490         %Decimal{coef: :NaN}
   1491       }
   1492     else
   1493       {:ok, %Decimal{sign: div_sign, coef: coef, exp: 0}}
   1494     end
   1495   end
   1496 
   1497   defp do_normalize(coef, exp) do
   1498     if Kernel.rem(coef, 10) == 0 do
   1499       do_normalize(Kernel.div(coef, 10), exp + 1)
   1500     else
   1501       %Decimal{coef: coef, exp: exp}
   1502     end
   1503   end
   1504 
   1505   defp ratio(coef, exp) when exp >= 0, do: {coef * pow10(exp), 1}
   1506   defp ratio(coef, exp) when exp < 0, do: {coef, pow10(-exp)}
   1507 
   1508   pow10_max =
   1509     Enum.reduce(0..104, 1, fn int, acc ->
   1510       defp pow10(unquote(int)), do: unquote(acc)
   1511       defp base10?(unquote(acc)), do: true
   1512       acc * 10
   1513     end)
   1514 
   1515   defp pow10(num) when num > 104, do: pow10(104) * pow10(num - 104)
   1516 
   1517   defp base10?(num) when num >= unquote(pow10_max) do
   1518     if Kernel.rem(num, unquote(pow10_max)) == 0 do
   1519       base10?(Kernel.div(num, unquote(pow10_max)))
   1520     else
   1521       false
   1522     end
   1523   end
   1524 
   1525   defp base10?(_num), do: false
   1526 
   1527   ## ROUNDING ##
   1528 
   1529   defp do_round(sign, digits, exp, target_exp, rounding) do
   1530     num_digits = length(digits)
   1531     precision = num_digits - (target_exp - exp)
   1532 
   1533     cond do
   1534       exp == target_exp ->
   1535         %Decimal{sign: sign, coef: digits_to_integer(digits), exp: exp}
   1536 
   1537       exp < target_exp and precision < 0 ->
   1538         zeros = :lists.duplicate(target_exp - exp, ?0)
   1539         digits = zeros ++ digits
   1540         {signif, remain} = :lists.split(1, digits)
   1541 
   1542         signif =
   1543           if increment?(rounding, sign, signif, remain),
   1544             do: digits_increment(signif),
   1545             else: signif
   1546 
   1547         coef = digits_to_integer(signif)
   1548         %Decimal{sign: sign, coef: coef, exp: target_exp}
   1549 
   1550       exp < target_exp and precision >= 0 ->
   1551         {signif, remain} = :lists.split(precision, digits)
   1552 
   1553         signif =
   1554           if increment?(rounding, sign, signif, remain),
   1555             do: digits_increment(signif),
   1556             else: signif
   1557 
   1558         coef = digits_to_integer(signif)
   1559         %Decimal{sign: sign, coef: coef, exp: target_exp}
   1560 
   1561       exp > target_exp ->
   1562         digits = digits ++ Enum.map(1..(exp - target_exp), fn _ -> ?0 end)
   1563         coef = digits_to_integer(digits)
   1564         %Decimal{sign: sign, coef: coef, exp: target_exp}
   1565     end
   1566   end
   1567 
   1568   defp digits_to_integer([]), do: 0
   1569   defp digits_to_integer(digits), do: :erlang.list_to_integer(digits)
   1570 
   1571   defp precision(%Decimal{coef: :NaN} = num, _precision, _rounding) do
   1572     {num, []}
   1573   end
   1574 
   1575   defp precision(%Decimal{coef: :inf} = num, _precision, _rounding) do
   1576     {num, []}
   1577   end
   1578 
   1579   defp precision(%Decimal{sign: sign, coef: coef, exp: exp} = num, precision, rounding) do
   1580     digits = :erlang.integer_to_list(coef)
   1581     num_digits = length(digits)
   1582 
   1583     if num_digits > precision do
   1584       do_precision(sign, digits, num_digits, exp, precision, rounding)
   1585     else
   1586       {num, []}
   1587     end
   1588   end
   1589 
   1590   defp do_precision(sign, digits, num_digits, exp, precision, rounding) do
   1591     precision = Kernel.min(num_digits, precision)
   1592     {signif, remain} = :lists.split(precision, digits)
   1593 
   1594     signif =
   1595       if increment?(rounding, sign, signif, remain), do: digits_increment(signif), else: signif
   1596 
   1597     signals = if any_nonzero(remain), do: [:inexact, :rounded], else: [:rounded]
   1598 
   1599     exp = exp + length(remain)
   1600     coef = digits_to_integer(signif)
   1601     dec = %Decimal{sign: sign, coef: coef, exp: exp}
   1602     {dec, signals}
   1603   end
   1604 
   1605   defp increment?(_, _, _, []), do: false
   1606 
   1607   defp increment?(:down, _, _, _), do: false
   1608 
   1609   defp increment?(:up, _, _, _), do: true
   1610 
   1611   defp increment?(:ceiling, sign, _, remain), do: sign == 1 and any_nonzero(remain)
   1612 
   1613   defp increment?(:floor, sign, _, remain), do: sign == -1 and any_nonzero(remain)
   1614 
   1615   defp increment?(:half_up, _, _, [digit | _]), do: digit >= ?5
   1616 
   1617   defp increment?(:half_even, _, [], [?5 | rest]), do: any_nonzero(rest)
   1618 
   1619   defp increment?(:half_even, _, signif, [?5 | rest]),
   1620     do: any_nonzero(rest) or Kernel.rem(:lists.last(signif), 2) == 1
   1621 
   1622   defp increment?(:half_even, _, _, [digit | _]), do: digit > ?5
   1623 
   1624   defp increment?(:half_down, _, _, [digit | rest]),
   1625     do: digit > ?5 or (digit == ?5 and any_nonzero(rest))
   1626 
   1627   defp any_nonzero(digits), do: :lists.any(fn digit -> digit != ?0 end, digits)
   1628 
   1629   defp digits_increment(digits), do: digits_increment(:lists.reverse(digits), [])
   1630 
   1631   defp digits_increment([?9 | rest], acc), do: digits_increment(rest, [?0 | acc])
   1632 
   1633   defp digits_increment([head | rest], acc), do: :lists.reverse(rest, [head + 1 | acc])
   1634 
   1635   defp digits_increment([], acc), do: [?1 | acc]
   1636 
   1637   ## CONTEXT ##
   1638 
   1639   defp context(num, signals \\ []) do
   1640     context = Context.get()
   1641     {result, prec_signals} = precision(num, context.precision, context.rounding)
   1642     error(put_uniq(signals, prec_signals), nil, result, context)
   1643   end
   1644 
   1645   defp put_uniq(list, elems) when is_list(elems) do
   1646     Enum.reduce(elems, list, &put_uniq(&2, &1))
   1647   end
   1648 
   1649   defp put_uniq(list, elem) do
   1650     if elem in list, do: list, else: [elem | list]
   1651   end
   1652 
   1653   ## PARSING ##
   1654 
   1655   defp parse_unsign(<<first, remainder::size(7)-binary, rest::binary>>) when first in [?i, ?I] do
   1656     if String.downcase(remainder) == "nfinity" do
   1657       {%Decimal{coef: :inf}, rest}
   1658     else
   1659       :error
   1660     end
   1661   end
   1662 
   1663   defp parse_unsign(<<first, remainder::size(2)-binary, rest::binary>>) when first in [?i, ?I] do
   1664     if String.downcase(remainder) == "nf" do
   1665       {%Decimal{coef: :inf}, rest}
   1666     else
   1667       :error
   1668     end
   1669   end
   1670 
   1671   defp parse_unsign(<<first, remainder::size(2)-binary, rest::binary>>) when first in [?n, ?N] do
   1672     if String.downcase(remainder) == "an" do
   1673       {%Decimal{coef: :NaN}, rest}
   1674     else
   1675       :error
   1676     end
   1677   end
   1678 
   1679   defp parse_unsign(bin) do
   1680     {int, rest} = parse_digits(bin)
   1681     {float, rest} = parse_float(rest)
   1682     {exp, rest} = parse_exp(rest)
   1683 
   1684     if int == [] and float == [] do
   1685       :error
   1686     else
   1687       int = if int == [], do: '0', else: int
   1688       exp = if exp == [], do: '0', else: exp
   1689 
   1690       number = %Decimal{
   1691         coef: List.to_integer(int ++ float),
   1692         exp: List.to_integer(exp) - length(float)
   1693       }
   1694 
   1695       {number, rest}
   1696     end
   1697   end
   1698 
   1699   defp parse_float("." <> rest), do: parse_digits(rest)
   1700   defp parse_float(bin), do: {[], bin}
   1701 
   1702   defp parse_exp(<<e, rest::binary>>) when e in [?e, ?E] do
   1703     case rest do
   1704       <<sign, rest::binary>> when sign in [?+, ?-] ->
   1705         {digits, rest} = parse_digits(rest)
   1706         {[sign | digits], rest}
   1707 
   1708       _ ->
   1709         parse_digits(rest)
   1710     end
   1711   end
   1712 
   1713   defp parse_exp(bin) do
   1714     {[], bin}
   1715   end
   1716 
   1717   defp parse_digits(bin), do: parse_digits(bin, [])
   1718 
   1719   defp parse_digits(<<digit, rest::binary>>, acc) when digit in ?0..?9 do
   1720     parse_digits(rest, [digit | acc])
   1721   end
   1722 
   1723   defp parse_digits(rest, acc) do
   1724     {:lists.reverse(acc), rest}
   1725   end
   1726 
   1727   # Util
   1728 
   1729   defp decimal(%Decimal{} = num), do: num
   1730   defp decimal(num) when is_integer(num), do: new(num)
   1731   defp decimal(num) when is_binary(num), do: new(num)
   1732 
   1733   defp decimal(other) when is_float(other) do
   1734     raise ArgumentError,
   1735           "implicit conversion of #{inspect(other)} to Decimal is not allowed. Use Decimal.from_float/1"
   1736   end
   1737 
   1738   defp handle_error(signals, reason, result, context) do
   1739     context = context || Context.get()
   1740     signals = List.wrap(signals)
   1741 
   1742     flags = Enum.reduce(signals, context.flags, &put_uniq(&2, &1))
   1743     Context.set(%{context | flags: flags})
   1744     error_signal = Enum.find(signals, &(&1 in context.traps))
   1745 
   1746     if error_signal do
   1747       error = [signal: error_signal, reason: reason]
   1748       {:error, error}
   1749     else
   1750       {:ok, result}
   1751     end
   1752   end
   1753 
   1754   defp fix_float_exp(digits) do
   1755     fix_float_exp(digits, [])
   1756   end
   1757 
   1758   defp fix_float_exp([?e | rest], [?0 | [?. | result]]) do
   1759     fix_float_exp(rest, [?e | result])
   1760   end
   1761 
   1762   defp fix_float_exp([digit | rest], result) do
   1763     fix_float_exp(rest, [digit | result])
   1764   end
   1765 
   1766   defp fix_float_exp([], result), do: :lists.reverse(result)
   1767 
   1768   if Version.compare(System.version(), "1.3.0") == :lt do
   1769     defp integer_to_charlist(string), do: Integer.to_char_list(string)
   1770   else
   1771     defp integer_to_charlist(string), do: Integer.to_charlist(string)
   1772   end
   1773 end
   1774 
   1775 defimpl Inspect, for: Decimal do
   1776   def inspect(dec, _opts) do
   1777     "#Decimal<" <> Decimal.to_string(dec) <> ">"
   1778   end
   1779 end
   1780 
   1781 defimpl String.Chars, for: Decimal do
   1782   def to_string(dec) do
   1783     Decimal.to_string(dec)
   1784   end
   1785 end