summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-24 11:38:47 +0300
committerPaul Buetow <paul@buetow.org>2026-05-24 11:38:47 +0300
commitbfd5742f38d6548f015497e1b1cd2a03b8f76e5b (patch)
tree01d15d93a8acdf794e62b1dfa6abebf14581fcec
parentbb83c0b2634856300c608f882dabf308980d09e6 (diff)
docs: add log operators documentation (lg, log, ln)
Cover lg (log base 2), log (log base 10), and ln (natural log) with: - Mathematical explanations - RPN examples from live testing - Edge cases (zero and negative number errors) - Practical use cases (information theory, decibels, pH, growth) - Metric handling notes - Implementation references
-rw-r--r--docs/log-operators.md192
1 files changed, 192 insertions, 0 deletions
diff --git a/docs/log-operators.md b/docs/log-operators.md
new file mode 100644
index 0000000..cc13b49
--- /dev/null
+++ b/docs/log-operators.md
@@ -0,0 +1,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