zf

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

context.ex (4899B)


      1 defmodule Decimal.Context do
      2   import Decimal.Macros
      3   alias Decimal.Context
      4 
      5   @moduledoc """
      6   The context is kept in the process dictionary. It can be accessed with
      7   `get/0` and `set/1`.
      8 
      9   The default context has a precision of 28, the rounding algorithm is
     10   `:half_up`. The set trap enablers are `:invalid_operation` and
     11   `:division_by_zero`.
     12 
     13   ## Fields
     14 
     15     * `precision` - maximum number of decimal digits in the coefficient. If an
     16       operation result has more digits it will be rounded to `precision`
     17       digits with the rounding algorithm in `rounding`.
     18     * `rounding` - the rounding algorithm used when the coefficient's number of
     19       exceeds `precision`. Strategies explained below.
     20     * `flags` - a list of signals that for which the flag is sent. When an
     21       exceptional condition is signalled its flag is set. The flags are sticky
     22       and will be set until explicitly cleared.
     23     * `traps` - a list of set trap enablers for signals. When a signal's trap
     24       enabler is set the condition causes `Decimal.Error` to be raised.
     25 
     26   ## Rounding algorithms
     27 
     28     * `:down` - round toward zero (truncate). Discarded digits are ignored,
     29       result is unchanged.
     30     * `:half_up` - if the discarded digits is greater than or equal to half of
     31       the value of a one in the next left position then the coefficient will be
     32       incremented by one (rounded up). Otherwise (the discarded digits are less
     33       than half) the discarded digits will be ignored.
     34     * `:half_even` - also known as "round to nearest" or "banker's rounding". If
     35       the discarded digits is greater than half of the value of a one in the
     36       next left position then the coefficient will be incremented by one
     37       (rounded up). If they represent less than half discarded digits will be
     38       ignored. Otherwise (exactly half), the coefficient is not altered if it's
     39       even, or incremented by one (rounded up) if it's odd (to make an even
     40       number).
     41     * `:ceiling` - round toward +Infinity. If all of the discarded digits are
     42       zero or the sign is negative the result is unchanged. Otherwise, the
     43       coefficient will be incremented by one (rounded up).
     44     * `:floor` - round toward -Infinity. If all of the discarded digits are zero
     45       or the sign is positive the result is unchanged. Otherwise, the sign is
     46       negative and coefficient will be incremented by one.
     47     * `:half_down` - if the discarded digits is greater than half of the value
     48       of a one in the next left position then the coefficient will be
     49       incremented by one (rounded up). Otherwise (the discarded digits are half
     50       or less) the discarded digits are ignored.
     51     * `:up` - round away from zero. If all discarded digits are zero the
     52       coefficient is not changed, otherwise it is incremented by one (rounded
     53       up).
     54 
     55   This table shows the results of rounding operations for all the rounding
     56   algorithms:
     57 
     58   Rounding algorithm | 5.5 | 2.5 | 1.6 | 1.1 | 1.0 | -1.0 | -1.1 | -1.6 | -2.5 | -5.5
     59   :----------------- | :-- | :-- | :-- | :-- | :-- | :--- | :--- | :--- | :--- | :---
     60   `:up`              |   6 |   3 |   2 |   2 |   1 |   -1 |   -2 |   -2 |   -3 |   -6
     61   `:down`            |   5 |   2 |   1 |   1 |   1 |   -1 |   -1 |   -1 |   -2 |   -5
     62   `:ceiling`         |   6 |   3 |   2 |   2 |   1 |   -1 |   -1 |   -1 |   -2 |   -5
     63   `:floor`           |   5 |   2 |   1 |   1 |   1 |   -1 |   -2 |   -2 |   -3 |   -6
     64   `:half_up`         |   6 |   3 |   2 |   1 |   1 |   -1 |   -1 |   -2 |   -3 |   -6
     65   `:half_down`       |   5 |   2 |   2 |   1 |   1 |   -1 |   -1 |   -2 |   -2 |   -5
     66   `:half_even`       |   6 |   2 |   2 |   1 |   1 |   -1 |   -1 |   -2 |   -2 |   -6
     67 
     68   """
     69   @type t :: %__MODULE__{
     70           precision: pos_integer,
     71           rounding: Decimal.rounding(),
     72           flags: [Decimal.signal()],
     73           traps: [Decimal.signal()]
     74         }
     75 
     76   defstruct precision: 28,
     77             rounding: :half_up,
     78             flags: [],
     79             traps: [:invalid_operation, :division_by_zero]
     80 
     81   @context_key :"$decimal_context"
     82 
     83   @doc """
     84   Runs function with given context.
     85   """
     86   doc_since("1.9.0")
     87   @spec with(t(), (() -> x)) :: x when x: var
     88   def with(%Context{} = context, fun) when is_function(fun, 0) do
     89     old = Process.put(@context_key, context)
     90 
     91     try do
     92       fun.()
     93     after
     94       set(old || %Context{})
     95     end
     96   end
     97 
     98   @doc """
     99   Gets the process' context.
    100   """
    101   doc_since("1.9.0")
    102   @spec get() :: t()
    103   def get() do
    104     Process.get(@context_key, %Context{})
    105   end
    106 
    107   @doc """
    108   Set the process' context.
    109   """
    110   doc_since("1.9.0")
    111   @spec set(t()) :: :ok
    112   def set(%Context{} = context) do
    113     Process.put(@context_key, context)
    114     :ok
    115   end
    116 
    117   @doc """
    118   Update the process' context.
    119   """
    120   doc_since("1.9.0")
    121   @spec update((t() -> t())) :: :ok
    122   def update(fun) when is_function(fun, 1) do
    123     get() |> fun.() |> set()
    124   end
    125 end