# `calc`

[![Build and Test Status](https://github.com/coriolinus/calc/workflows/Build%20and%20Test/badge.svg?branch=main)](https://github.com/coriolinus/calc/actions?query=branch%3Amain+workflow%3A%22Build+and+Test%22)

Yet another CLI calculator. Inspired by the excellent <https://github.com/alfredxing/calc>.

## Installation

With a Rust installation, you can always install the head of `main` with:

```sh
cargo install --force --git https://github.com/coriolinus/calc.git --branch main
```

Alternately, you can download a precompiled executable of the most recent [release](https://github.com/coriolinus/calc/releases).

## Usage

### Expression Mode

```sh
$ calc "1/(2+(3*(4-5)))"
-1
$ calc "round(12345 / 543)"
23
```

When non-flag arguments are present, `calc` interprets them as an expression and evaluates them immediately.

### Shell Mode

```sh
$ calc
[0]: 1 + 1
2
[1]: 3*(5/(3-4))
-15
[2]: 3*pi**2
29.608813203268074
[3]: @+1
30.608813203268074
[4]: @@@*2
-30
[5]: ln(-1)
NaN
```

In the absence of non-flag arguments, `calc` launches a simple shell which just evaluates each line of input.

## Reference

### Data Types

Every invocation of `calc` interprets all arguments as a single data type. By default, `calc` uses `f64`, but other data types
can be chosen by command-line flag:

- `f64` (default): signed 64-bit floating point operations
- `u64`: unsigned 64-bit integer operations
- `i64`: signed 64-bit integer operations

Note that the data type chosen will restrict the available operators, functions, and constants. For example, trigonometric operations
are not available on integers, and bit-shifting operations are not available on floats.

### Numeric Input Format

Numbers may contain `_` characters at any point. Those symbols are ignored; they are for user convenience and readability only.

`calc` can handle inputs in several numeric bases.

- Un-annotated numbers are assumed to be base 10. Example: `123.45`.

  Note: this is the only format which is legal for non-integral numbers.

- Numbers with a `0b` prefix are in base 2. Example: `0b0110_1010`.
- Numbers with a `0o` prefix are in base 8. Example: `0o755`.

  Note: a leading `0` is not in itself an octal prefix. Example: `0755` equals `0d755`.

- Numbers with a `0d` prefix are in base 10. Example: `1234_5678`.
- Numbers with a `0x` prefix are in base 16. Example: `0xdead_beef`.

It is legal to intermix inputs of varying bases.

### Order of Operations

The following order of operations is used to resolve expressions:

- Parentheses (`(...)`)
- Unary Prefix Operators (`-` `!`)
- Shifts and Exponentiation (`<<` `>>` `<<<` `>>>` `**`)
- Bitwise operations (`&` `|` `^`)
- Multiplication and Division (`*` `/` `//` `%`)
- Addition and Subtraction (`+` `-`)

Operations at the same level of precedence are resolved from left to right.

### Unary Prefix Operators

- `-`: Negation
- `!`: Bitwise Not

### Infix Operators

- `+`: Addition
- `-`: Subtraction
- `*`: Multiplication
- `/`: Division
- `//`: Truncating Division: divides, truncating all data after the decimal point.
- `**`: Exponentiation
- `%` : Arithmetic remainder
- `<<`: Left Shift
- `>>`: Right Shift
- `<<<`: Wrapping Left Shift (Rotate Left)
- `>>>`: Wrappping Right Shift (Rotate Right)
- `&`: Bitwise And
- `|`: Bitwise Or
- `^`: Bitwise Xor

### Functions

- `abs`: Absolute Value
- `ceil`: Smallest integer greater than or equal to the input
- `floor`: Greatest integer less than or equal to the input
- `round`: Nearest integer to the input; halfway cases away from 0.0
- `sin`: Sine
- `cos`: Cosine
- `tan`: Tangent
- `sinh`: Hyperbolic Sine
- `cosh`: Hyperbolic Cosine
- `tanh`: Hyperbolic Tangent
- `asin`: Arcine
- `acos`: Arccosine
- `atan`: Arctangent
- `asinh`: Inverse Hyperbolic Sine
- `acosh`: Inverse Hyperbolic Cosine
- `atanh`: Inverse Hyperbolic Tangent
- `rad`: Convert a number in degrees to radians
- `dec`: Convert a number in radians to degrees
- `sqrt`: Square Root
- `cbrt`: Cube Root
- `log`: Base-10 Logarithm
- `lg`: Base-2 Logarithm
- `ln`: Natural (Base-e) Logarithm
- `exp`: `e**x`

Trigonometric functions operate on radians.

### Constants

- `e`: Euler's Number
- `pi`: Archimedes' Constant
- `π`: Archimedes' Constant

### History

In shell mode, `calc` keeps the results of all expressions in memory until it is quit.

The pseudovariable `@` always refers to the result of the previous expression.
The pseudovariable `@@` always refers to the result of the expression before the previous.
Any number of `@` symbols can be chained this way.

Simply chaining `@` symbols can get cumbersome. The syntax `@{N}`, where `N` is an integer,
refers to the `N`th previous result. `@{1}` always refers to the result of the previous expression;
it is equivalent to `@`. `@{3}` refers to the result 3 expressions ago; it is equivalent to `@@@`.

The pseuaovariable `@[0]` always refers to the result of the first expression in this shell session.
Likewise, `@[1]` refers to the second, and so on. The shell interface indicates the current expression.

## Warnings

### No Implicit Multiplication

Implicit multiplication is not supported. Use a multiplication operator such as `*`.

### Floating Point Errors

Floating point operations can compound lossily, and `calc` makes no special efforts to guard against
this kind of error. For example:

```sh
$ calc 'sin(rad(45)) - (sqrt(2) / 2)'
-0.00000000000000011102230246251565
```

## Crate Structure

This crate includes both library code and CLI code. The CLI code is all gated behind feature `cli`; the
`cli` feature is in the default features. This means that the CLI is built by default. However, it is
possible to use this crate as a library without building any of the CLI code by including in your
`Cargo.toml`:

```toml
[dependencies]
calc = { version = "*", default-features = false }
```
