summaryrefslogtreecommitdiff
path: root/docs/log-operators.md
blob: cc13b492924dbce667eca12f773f4126e886ba4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# Logarithm RPN Operators

`gt` provides three logarithm operators: `lg` (base 2), `log` (base 10), and
`ln` (natural log, base *e*). Each is a unary operator that pops a single value
from the stack, computes the logarithm, and pushes the result.

Logarithm results are always unitless (Cool metric), regardless of whether the
input carried a metric.

## How RPN Works

For unary operators, the operand precedes the operator:

```
Input:  8  lg

  Step  Stack
  ----  -----
   8    [8]
   lg   [3]

Result: 3
```

## Operators

### `lg` — Logarithm Base 2

Computes the base-2 logarithm: log₂(*x*).

#### Mathematical explanation

log₂(*x*) = *y* means 2^*y* = *x*. It answers: "To what power must 2 be raised
to produce *x*?"

#### Examples

```
$ echo "8 lg" | gt
3

$ echo "1024 lg" | gt
10

$ echo "1 lg" | gt
0

$ echo "1e-10 lg" | gt
-33.21928095
```

#### Practical use cases

- **Information theory** — Number of bits needed to represent *x* distinct
  values (e.g., log₂(1024) = 10 bits).
- **Algorithms** — Time complexity of divide-and-conquer algorithms (O(log n)).
- **Digital audio** — Bit-depth calculations.
- **Computer science** — Tree height, binary search steps.

---

### `log` — Logarithm Base 10

Computes the base-10 logarithm: log₁₀(*x*).

#### Mathematical explanation

log₁₀(*x*) = *y* means 10^*y* = *x*. It answers: "To what power must 10 be
raised to produce *x*?"

#### Examples

```
$ echo "1000 log" | gt
3

$ echo "100 log" | gt
2

$ echo "10 log" | gt
1

$ echo "1 log" | gt
0

$ echo "1e-10 log" | gt
-10
```

#### Practical use cases

- **Decibels (dB)** — Sound intensity and signal power ratios:
  L = 10 · log₁₀(P/P₀). Example: `1000 10 / log 10 *` → 30 dB.
- **pH scale** — Acidity/alkalinity: pH = -log₁₀([H⁺]). Example:
  `1e-7 log 0 -` → 7 (neutral water).
- **Richter scale** — Earthquake magnitude.
- **Order of magnitude** — Quick estimate of size: log₁₀(500) ≈ 2.7 means
  "between 100 and 1000".
- **Scientific notation** — The integer part of log₁₀(*x*) gives the exponent.

---

### `ln` — Natural Logarithm

Computes the natural logarithm: ln(*x*) = logₑ(*x*), where *e* ≈ 2.718281828.

#### Mathematical explanation

ln(*x*) = *y* means *e*^*y* = *x*. It is the inverse of the exponential function
and the integral of 1/*t* from 1 to *x*.

#### Examples

```
$ echo "e ln" | gt
1

$ echo "2.718281828 ln" | gt
0.9999999998

$ echo "1 ln" | gt
0

$ echo "7.38905609893065 ln" | gt
2
```

#### Practical use cases

- **Continuous growth** — Compound interest, population growth:
  A = A₀ · e^(rt). Solve for t: t = ln(A/A₀) / r.
- **Probability & statistics** — Normal distribution, likelihood functions.
- **Calculus** — Derivative of ln(*x*) is 1/*x*; integral of 1/*x* is ln(|*x*|).
- **Entropy** — Shannon entropy uses natural log in thermodynamics.
- **Chemistry** — Arrhenius equation for reaction rates.

---

## Edge Cases

All three operators are **undefined for non-positive numbers**. Zero and negative
inputs produce an error:

```
$ echo "0 lg" | gt
Error: lg undefined for non-positive numbers

$ echo "-5 log" | gt
Error: log undefined for non-positive numbers

$ echo "0 ln" | gt
Error: ln undefined for non-positive numbers

$ echo "-1 ln" | gt
Error: ln undefined for non-positive numbers
```

### Summary table

| Input    | Result                        |
|----------|-------------------------------|
| *x* > 0  | Computed normally             |
| *x* = 0  | Error (undefined)             |
| *x* < 0  | Error (undefined)             |
| *x* = 1  | 0 (for all three operators)   |
| empty    | Error (stack underflow)       |

---

## Metric Handling

Logarithms always produce unitless results. Even when the input carries a metric,
the result is Cool (no metric):

```
$ echo "100Mbps lg" | gt          # treats as number with metric, result is Cool
```

This is mathematically correct — taking a logarithm of a dimensioned quantity
requires a reference value (e.g., log₁₀(P/P₀) for decibels), so gt treats the
operands as their numeric values.

---

## Implementation

- Source: `internal/rpn/operations_arithmetic.go` — `Log2`, `Log10`, `Ln`
- Uses `math.Log2`, `math.Log10`, `math.Log` from Go's standard library
- Shared helper: `logOp(stack, opName, logFn)` handles pop, validate, compute,
  and push
- Tests: `internal/rpn/operations_test.go` — `TestLog2`, `TestLog10`, `TestLn`
  plus boolean coercion and hyper-operator variants