Skip to content

Commit

Permalink
Merge branch 'v4'
Browse files Browse the repository at this point in the history
  • Loading branch information
Qqwy committed Aug 8, 2023
2 parents 62c8d90 + 85f0af9 commit 4a533a2
Show file tree
Hide file tree
Showing 9 changed files with 388 additions and 202 deletions.
89 changes: 89 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# create this in .github/workflows/ci.yml
name: ci
on: push

jobs:
test:
runs-on: ubuntu-latest
name: OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}}
strategy:
matrix:
include:
- elixir: 1.14.x
otp: 25.x
- elixir: 1.14.x
otp: 24.x
- elixir: 1.14.x
otp: 23.x
- elixir: 1.13.x
otp: 24.x
- elixir: 1.13.x
otp: 23.x
- elixir: 1.13.x
otp: 22.x
- elixir: 1.12.x
otp: 24.x
- elixir: 1.12.x
otp: 23.x
- elixir: 1.12.x
otp: 22.x
- elixir: 1.11.x
otp: 23.x
- elixir: 1.11.x
otp: 22.x
- elixir: 1.11.x
otp: 21.x
- elixir: 1.10.x
otp: 22.x
- elixir: 1.10.x
otp: 21.x
- elixir: 1.9.x
otp: 22.x
- elixir: 1.9.x
otp: 21.x
- elixir: 1.9.x
otp: 20.x
- elixir: 1.8.x
otp: 22.x
- elixir: 1.8.x
otp: 21.x
- elixir: 1.8.x
otp: 20.x
# - elixir: 1.7.x
# otp: 22.x
# - elixir: 1.7.x
# otp: 21.x
# - elixir: 1.7.x
# otp: 20.x
# - elixir: 1.7.x
# otp: 19.x
# - elixir: 1.6.x
# otp: 20.x
# - elixir: 1.6.x
# otp: 19.x
env:
MIX_ENV: test
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# NODE_COVERALLS_DEBUG: 1
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
otp-version: ${{matrix.otp}}
elixir-version: ${{matrix.elixir}}
- uses: actions/cache@v2
id: mix-cache
with:
path: |
deps
_build
key: ${{ runner.os }}-${{ matrix.otp}}-${{ matrix.elixir }}-mix-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.otp}}-${{ matrix.elixir }}-mix-
- if: steps.mix-cache.outputs.cache-hit != 'true'
run: |
mix deps.get
mix deps.compile
- run: mix compile
- run: mix test # Testing is already done as part of the next task:
# - run: mix coveralls.github --trace
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
elixir 1.12.3-otp-24
erlang 24.1.2
elixir 1.15.0
erlang 25.0
67 changes: 52 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,43 @@ Ratio follows the Numeric behaviour from [Numbers](https://github.com/Qqwy/elixi

`Ratio` defines arithmetic and comparison operations to work with rational numbers.

Usually, you probably want to add the line `import Ratio, only: [<|>: 2]` to your code.
Rational numbers can be created by using `Ratio.new/2`,
or by calling mathematical operators where one of the two operands is already a rational number.

### Shorthand operator

Rational numbers can be written using the operator `<|>` (as in: `1 <|> 2`), which is also how Ratio structs are pretty-printed when inspecting.
`a <|> b` is a shorthand for `Ratio.new(a, b)`.
### Shorthand infix construction operator

Since version 4.0, `Ratio` no longer defines an infix operator to create rational numbers.
Instead, rational numbers are made using `Ratio.new`,
and as the output from using an existing `Ratio` struct with a mathematical operation.

If you do want to use an infix operator such as
`<~>` (supported in all Elixir versions)
or `<|>` (deprecated in Elixir v1.14, the default of older versions of the `Ratio` library)

you can add the following one-liner to the module(s) in which you want to use it:

```elixir
defdelegate numerator <~> denominator, to: Ratio, as: :new
```

### Basic functionality

Rational numbers can be manipulated using the functions in the [`Ratio`](https://hexdocs.pm/ratio/Ratio.html) module.

```elixir
iex> Ratio.mult( 1 <|> 3, 1 <|> 2)
1 <|> 6
iex> Ratio.div(2 <|> 3, 8 <|> 5)
5 <|> 12
iex> Ratio.mult(Ratio.new(1, 3), Ratio.new(1, 2))
Ratio.new(1, 6)
iex> Ratio.div(Ratio.new(2, 3), Ratio.new(8, 5))
Ratio.new(5, 12)
iex> Ratio.pow(Ratio.new(2), 4)
16 <|> 1
Ratio.new(16, 1)
```

The ratio module also contains:
The Ratio module also contains:
- a guard-safe `is_rational/1` check.
- a `compare/2` function for use with e.g. `Enum.sort`.
- `to_float` to (lossly) convert a rational into a float.
- `to_float/1` to (lossly) convert a rational into a float.

### Inline Math Operators and Casting

Expand All @@ -46,7 +59,26 @@ you can add `use Numbers, overload_operators: true` to your module.
This also allows you to pass in a rational number as one argument
and an integer, float or Decimal (if you have installed the `Decimal` library),
which are then cast to rational numbers whenever necessary.
which are then cast to rational numbers whenever necessary:
``` elixir
defmodule IDoAlotOfMathHere do
defdelegate numerator <~> denominator, to: Ratio, as: :new
use Numbers, overload_operators: true
def calculate(input) do
num = input <~> 2
result = num * 2 + (3 <~> 4) * 5.0
result / 2
end
end
```
``` elixir
iex> IDoAlotOfMathHere.calculate(42)
Ratio.new(183, 8)
```
## Installation
Expand All @@ -55,13 +87,18 @@ which are then cast to rational numbers whenever necessary.
def deps do
[
{:ratio, "~> 3.0"}
{:ratio, "~> 4.0"}
]
end
## Changelog
- 4.0.0 -
- Remove infix operator `<|>` as its usage is deprecated in Elixir v1.14. This is a backwards-incompatible change. If you want to use the old syntax with the new version, add `defdelegate num <|> denom, to: Ratio, as: :new` to your module. Alternatively, you might want to use the not-deprecated `<~>` operator for this instead.
- Switch the `Inspect` implementation to use the form `Ratio.new(10, 20)` instead of `10 <|> 20`, related to above. This is also a backwards-incompatible change.
- Remove implementation of `String.Chars`, as the earlier implementation was not a (non-programmer) human-readable format.
- Ensure that the right-hand-side operand of calls to `Ratio.{add, sub, mult, div}/2` is allowed to be an integer for ease of use and backwards compatibility. Thank you for noticing this problem, @kipcole9 ! (c.f. #111)
- 3.0.2 -
- Fixes: A bug with `<|>` when the numerator was a rational and the denuminator an integer. (c.f. #104) Thank you, @varsill!
- 3.0.1 -
Expand Down Expand Up @@ -107,8 +144,8 @@ which are then cast to rational numbers whenever necessary.
## Difference with the 'rational' library
Observant readers might notice that there also is a '[rational](https://hex.pm/packages/rational)' library in Hex.pm. The design idea between that library vs. this one is a bit different: `Ratio` hides the internal data representation as much as possible, and numbers are therefore created using `Rational.<|>/2` or `Ratio.new/2`. This has as mayor advantage that the internal representation is always correct and simplified.
Observant readers might notice that there also is a '[rational](https://hex.pm/packages/rational)' library in Hex.pm. The design idea between that library vs. this one is a bit different: `Ratio` hides the internal data representation as much as possible, and numbers are therefore only created using `Ratio.new/2`. This has as mayor advantage that the internal representation is always correct and simplified.
The Ratio library also (optionally) overrides the built-in math operations `+, -, *, /, div, abs` so they work with combinations of integers, floats and rationals.
The Ratio library also (optionally) overrides (by virtue of the `Numbers` library) the built-in math operations `+, -, *, /, div, abs` so they work with combinations of integers, floats and rationals.
Finally, Ratio follows the Numeric behaviour, which means that it can be used with any data types that follow [Numbers](https://github.com/Qqwy/elixir_number).
31 changes: 1 addition & 30 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -1,30 +1 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config

# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
# if you want to provide default values for your application for
# 3rd-party users, it should be done in your "mix.exs" file.

# You can configure for your application as:
#
# config :rational, key: :value
#
# And access this configuration in your application as:
#
# Application.get_env(:rational, :key)
#
# Or configure a 3rd-party app:
#
# config :logger, level: :info
#

# It is also possible to import configuration files, relative to this
# directory. For example, you can emulate configuration per environment
# by uncommenting the line below and defining dev.exs, test.exs and such.
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env}.exs"
# Ratio does not have any config
Loading

0 comments on commit 4a533a2

Please sign in to comment.