# Si
The library implements quantities and units which included to basic SI.
The **[International System of Units](https://en.wikipedia.org/wiki/International_System_of_Units)**, internationally known by the abbreviation SI (from French Système International), is the modern form of the [metric system](https://en.wikipedia.org/wiki/Metric_system) and the world's most widely used [system of measurement](https://en.wikipedia.org/wiki/System_of_measurement). Established and maintained by the [General Conference on Weights and Measures](https://en.wikipedia.org/wiki/General_Conference_on_Weights_and_Measures), it is the only system of measurement with an official status in nearly every country in the world, employed in science, technology, industry, and everyday commerce.
## Installation
If [available in Hex](https://hex.pm/packages/si), the package can be installed
by adding `si` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:si, "~> 1.5.1"}
]
end
```
## Basic usage
### Unit creation
```elixir
iex(1)> SI.Unit.Kilogram.create(12.3)
%SI.Unit.Kilogram{value: 12.3}
```
### Unit converting
For example if we wanna convert `kilograms` to `grams` we can use following code:
```elixir
iex(1)> kg = SI.Unit.Kilogram.create(12.3)
%SI.Unit.Kilogram{value: 12.3}
iex(1)> SI.Unit.Gram.create(kg)
%SI.Unit.Gram{value: 12300}
```
### Adding custom conversions
By default library provides converting between units in the same quantity. That means, by default we can convert `nanogram` to `kilogram` or `decagram` to `gram` because they are belongs the same quantity. Converting between different quantities will raise an error.
```elixir
iex(1)> SI.Unit.Gram.create SI.Unit.Ampere.create(123)
** (Protocol.UndefinedError) protocol SI.Unit.Gram.Generator not implemented for %SI.Unit.Ampere{value: 123.0} of type SI.Unit.Ampere (a struct). This protocol is implemented for the
following type(s): Float, Integer, SI.Unit.Attogram, SI.Unit.Centigram, SI.Unit.Decagram, SI.Unit.Decigram, SI.Unit.Exagram, SI.Unit.Femtogram, SI.Unit.Gigagram, SI.Unit.Hectogram,
SI.Unit.Kilogram, SI.Unit.Megagram, SI.Unit.Microgram, SI.Unit.Milligram, SI.Unit.Nanogram, SI.Unit.Petagram, SI.Unit.Picogram, SI.Unit.Teragram
(si 1.0.0) lib/unit/gram.ex:3: SI.Unit.Gram.Generator.impl_for!/1
(si 1.0.0) lib/unit/gram.ex:3: SI.Unit.Gram.Generator.create/1
iex:1: (file)
```
But you can make your own converting protocol if it necessary.
```elixir
defimpl SI.Unit.Gram.Generator, for: SI.Unit.Ampere do
def create(term), do: SI.Unit.Gram.create(term.value * 3)
end
```
and now new converting is allowed
```elixir
iex(1)> SI.Unit.Gram.create SI.Unit.Ampere.create(123)
%SI.Unit.Gram{value: 369.0}
```
## Available modules
Basically `SI` provides 7 quantities and 7 basic units for them.
### Quantities and they inits
| Name | Typical symbol | Module |
|---------------------------|----------------|------------------|
| time | `t` | SI.Unit.Second |
| length | `l` | SI.Unit.Meter |
| mass | `m` | SI.Unit.Kilogram |
| electric current | `I` | SI.Unit.Ampere |
| thermodynamic temperature | `T` | SI.Unit.Kelvin |
| amount of substance | `n` | SI.Unit.Mole |
| luminous intensity | `lv` | SI.Unit.Candela |
### Basic units
| Name | Symbol | Module |
|---------|--------|--------------------|
| ampere | `A` | `SI.Unit.Ampere` |
| candela | `cd` | `SI.Unit.Candela` |
| gram | `g` | `SI.Unit.Gram` |
| kelvin | `K` | `SI.Unit.Kelvin` |
| meter | `m` | `SI.Unit.Meter` |
| mole | `mol` | `SI.Unit.Mole` |
| second | `s` | `SI.Unit.Second` |
### Getting all default available modules
Getting all default quantities
```elixir
iex(1)> SI.quantities
[
mass: SI.Quantity.Mass,
amount_of_substance: SI.Quantity.AmountOfSubstance,
time: SI.Quantity.Time,
thermodynamic_temperature: SI.Quantity.ThermodynamicTemperature,
luminous_intensity: SI.Quantity.LuminousIntensity,
length: SI.Quantity.Length,
electric_current: SI.Quantity.ElectricCurrent
]
```
Getting all default available modules grouped by quantity symbols
```elixir
iex(1)> SI.units
[
time: [
second: SI.Unit.Second,
exasecond: SI.Unit.Exasecond,
petasecond: SI.Unit.Petasecond,
terasecond: SI.Unit.Terasecond,
gigasecond: SI.Unit.Gigasecond,
megasecond: SI.Unit.Megasecond,
kilosecond: SI.Unit.Kilosecond,
hectosecond: SI.Unit.Hectosecond,
decasecond: SI.Unit.Decasecond,
decisecond: SI.Unit.Decisecond,
centisecond: SI.Unit.Centisecond,
millisecond: SI.Unit.Millisecond,
microsecond: SI.Unit.Microsecond,
nanosecond: SI.Unit.Nanosecond,
picosecond: SI.Unit.Picosecond,
femtosecond: SI.Unit.Femtosecond,
attosecond: SI.Unit.Attosecond
],
thermodynamic_temperature: [
kelvin: SI.Unit.Kelvin,
exakelvin: SI.Unit.Exakelvin,
petakelvin: SI.Unit.Petakelvin,
terakelvin: SI.Unit.Terakelvin,
gigakelvin: SI.Unit.Gigakelvin,
megakelvin: SI.Unit.Megakelvin,
kilokelvin: SI.Unit.Kilokelvin,
hectokelvin: SI.Unit.Hectokelvin,
decakelvin: SI.Unit.Decakelvin,
decikelvin: SI.Unit.Decikelvin,
centikelvin: SI.Unit.Centikelvin,
millikelvin: SI.Unit.Millikelvin,
microkelvin: SI.Unit.Microkelvin,
nanokelvin: SI.Unit.Nanokelvin,
picokelvin: SI.Unit.Picokelvin,
femtokelvin: SI.Unit.Femtokelvin,
attokelvin: SI.Unit.Attokelvin
],
luminous_intensity: [
candela: SI.Unit.Candela,
exacandela: SI.Unit.Exacandela,
petacandela: SI.Unit.Petacandela,
teracandela: SI.Unit.Teracandela,
gigacandela: SI.Unit.Gigacandela,
megacandela: SI.Unit.Megacandela,
kilocandela: SI.Unit.Kilocandela,
hectocandela: SI.Unit.Hectocandela,
decacandela: SI.Unit.Decacandela,
decicandela: SI.Unit.Decicandela,
centicandela: SI.Unit.Centicandela,
millicandela: SI.Unit.Millicandela,
microcandela: SI.Unit.Microcandela,
nanocandela: SI.Unit.Nanocandela,
picocandela: SI.Unit.Picocandela,
femtocandela: SI.Unit.Femtocandela,
attocandela: SI.Unit.Attocandela
],
length: [
meter: SI.Unit.Meter,
exameter: SI.Unit.Exameter,
petameter: SI.Unit.Petameter,
terameter: SI.Unit.Terameter,
gigameter: SI.Unit.Gigameter,
megameter: SI.Unit.Megameter,
kilometer: SI.Unit.Kilometer,
hectometer: SI.Unit.Hectometer,
decameter: SI.Unit.Decameter,
decimeter: SI.Unit.Decimeter,
centimeter: SI.Unit.Centimeter,
millimeter: SI.Unit.Millimeter,
micrometer: SI.Unit.Micrometer,
nanometer: SI.Unit.Nanometer,
picometer: SI.Unit.Picometer,
femtometer: SI.Unit.Femtometer,
attometer: SI.Unit.Attometer
],
electric_current: [
ampere: SI.Unit.Ampere,
exaampere: SI.Unit.Exaampere,
petaampere: SI.Unit.Petaampere,
teraampere: SI.Unit.Teraampere,
gigaampere: SI.Unit.Gigaampere,
megaampere: SI.Unit.Megaampere,
kiloampere: SI.Unit.Kiloampere,
hectoampere: SI.Unit.Hectoampere,
decaampere: SI.Unit.Decaampere,
deciampere: SI.Unit.Deciampere,
centiampere: SI.Unit.Centiampere,
milliampere: SI.Unit.Milliampere,
microampere: SI.Unit.Microampere,
nanoampere: SI.Unit.Nanoampere,
picoampere: SI.Unit.Picoampere,
femtoampere: SI.Unit.Femtoampere,
attoampere: SI.Unit.Attoampere
],
amount_of_substance: [
mole: SI.Unit.Mole,
examole: SI.Unit.Examole,
petamole: SI.Unit.Petamole,
teramole: SI.Unit.Teramole,
gigamole: SI.Unit.Gigamole,
megamole: SI.Unit.Megamole,
kilomole: SI.Unit.Kilomole,
hectomole: SI.Unit.Hectomole,
decamole: SI.Unit.Decamole,
decimole: SI.Unit.Decimole,
centimole: SI.Unit.Centimole,
millimole: SI.Unit.Millimole,
micromole: SI.Unit.Micromole,
nanomole: SI.Unit.Nanomole,
picomole: SI.Unit.Picomole,
femtomole: SI.Unit.Femtomole,
attomole: SI.Unit.Attomole
],
mass: [
gram: SI.Unit.Gram,
exagram: SI.Unit.Exagram,
petagram: SI.Unit.Petagram,
teragram: SI.Unit.Teragram,
gigagram: SI.Unit.Gigagram,
megagram: SI.Unit.Megagram,
kilogram: SI.Unit.Kilogram,
hectogram: SI.Unit.Hectogram,
decagram: SI.Unit.Decagram,
decigram: SI.Unit.Decigram,
centigram: SI.Unit.Centigram,
milligram: SI.Unit.Milligram,
microgram: SI.Unit.Microgram,
nanogram: SI.Unit.Nanogram,
picogram: SI.Unit.Picogram,
femtogram: SI.Unit.Femtogram,
attogram: SI.Unit.Attogram
]
]
```
### Prefixes
Every single basic unit by default has "prefixed" definitions.
#### Example for `SI.Unit.Gram`
| Module | Name | Symbol | Multiplier |
|---------------------|-----------|--------|------------------|
| `SI.Unit.Exagram` | exagram | `Eg` | 10<sup>18</sup> |
| `SI.Unit.Petagram` | petagram | `Pg` | 10<sup>15</sup> |
| `SI.Unit.Teragram` | teragram | `Tg` | 10<sup>12</sup> |
| `SI.Unit.Gigagram` | gigagram | `Gg` | 10<sup>9</sup> |
| `SI.Unit.Megagram` | megagram | `Mg` | 10<sup>6</sup> |
| `SI.Unit.Kilogram` | kilogram | `kg` | 10<sup>3</sup> |
| `SI.Unit.Hectogram` | hectogram | `hg` | 10<sup>2</sup> |
| `SI.Unit.Decagram` | decagram | `dag` | 10<sup>1</sup> |
| `SI.Unit.Gram` | gram | `dag` | 10<sup>0</sup> |
| `SI.Unit.Decigram` | decigram | `dg` | 10<sup>-1</sup> |
| `SI.Unit.Centigram` | centigram | `cg` | 10<sup>-2</sup> |
| `SI.Unit.Milligram` | milligram | `mg` | 10<sup>-3</sup> |
| `SI.Unit.Microgram` | microgram | `ug` | 10<sup>-6</sup> |
| `SI.Unit.Nanogram` | nanogram | `ng` | 10<sup>-9</sup> |
| `SI.Unit.Picogram` | picogram | `pg` | 10<sup>-12</sup> |
| `SI.Unit.Femtogram` | femtogram | `fg` | 10<sup>-15</sup> |
| `SI.Unit.Attogram` | attogram | `ag` | 10<sup>-18</sup> |
Every "prefixed" unit has been created using multiplier module
| Name | Prefix | Multiplier | Module |
|-------|--------|------------|-----------------------|
| exa | `E` | 18 | `SI.Multiplier.Exa` |
| peta | `P` | 15 | `SI.Multiplier.Peta` |
| tera | `T` | 12 | `SI.Multiplier.Tera` |
| giga | `G` | 9 | `SI.Multiplier.Giga` |
| mega | `M` | 6 | `SI.Multiplier.Mega` |
| kilo | `k` | 3 | `SI.Multiplier.Kilo` |
| hecto | `h` | 2 | `SI.Multiplier.Hecto` |
| deca | `da` | 1 | `SI.Multiplier.Deca` |
| - | - | 0 | - |
| deci | `d` | -1 | `SI.Multiplier.Deci` |
| centi | `c` | -2 | `SI.Multiplier.Centi` |
| milli | `m` | -3 | `SI.Multiplier.Milli` |
| micro | `u` | -6 | `SI.Multiplier.Micro` |
| nano | `n` | -9 | `SI.Multiplier.Nano` |
| pico | `p` | -12 | `SI.Multiplier.Pico` |
| femto | `f` | -15 | `SI.Multiplier.Femto` |
| atto | `a` | -18 | `SI.Multiplier.Atto` |
## Docs
The docs can be found at [https://hexdocs.pm/si](https://hexdocs.pm/si).
## License
The `SI` is released under the Apache License 2.0 - see the [LICENSE](LICENSE) file.