This Python script generates the Mathematical Reference Tables used by several Category 2 (Reference Data) documents. It produces tables of logarithms, trigonometric functions, square roots, reciprocals, factorials, powers, unit conversions, and physical constants.
Requirements: Python 3.6+ with standard library only (no external dependencies).
Usage:
python scripts/generate_math_tables.py [output_file]
# Default output: tables-mathematical.md
Output: tables-mathematical.md —
approximately 1,500 lines of markdown tables, converted to HTML by
the site build process.
Source Code
#!/usr/bin/env python3
"""
Generate mathematical reference tables for the Recovery Library.
Produces tables-mathematical.md with:
- 4-figure common logarithms (1.00–9.99)
- Trigonometric functions (sin, cos, tan at 1° intervals)
- Natural logarithms (1.0–10.0)
- Square roots (1–100)
- Reciprocals (1–100)
- Powers of 2, e, 10
- Unit conversion factors
- Physical and mathematical constants
All values computed using Python's math module (IEEE 754 double precision).
Output is markdown formatted for pandoc conversion to HTML.
Usage:
python generate_math_tables.py [output_file]
Default output: ../tables-mathematical.md
"""
import math
import sys
import os
from datetime import datetime
def header():
return f"""---
title: "Mathematical Reference Tables"
subtitle: "Recovery Library — Computed Reference Data"
date: "{datetime.now().strftime('%Y-%m-%d')}"
---
# Mathematical Reference Tables
*Recovery Library — Computed Reference Data*
**Computation method:** All values computed using Python's `math` module (IEEE 754 double-precision floating point, ~15 significant digits). Tables are rounded to the displayed precision. Any computer with Python (or equivalent) can reproduce and extend these tables by running the generation script (`scripts/generate_math_tables.py`).
**Verification:** Values can be checked against any standard mathematical reference. The generation script is included in the library for reproducibility.
---
"""
def log_tables():
"""4-figure common logarithms for 1.00 to 9.99."""
out = "## Common Logarithms (Base 10)\n\n"
out += "log₁₀(N) for N = 1.00 to 9.99. To find log₁₀ of any number, "
out += "use log₁₀(a × 10ⁿ) = log₁₀(a) + n.\n\n"
# Header row
out += "| N | .00 | .01 | .02 | .03 | .04 | .05 | .06 | .07 | .08 | .09 |\n"
out += "|---|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|\n"
for row in range(10, 100): # 1.0 to 9.9
n_base = row / 10.0
out += f"| {n_base:.1f}"
for col in range(10):
n = n_base + col / 100.0
val = math.log10(n)
out += f" | {val:.4f}"
out += " |\n"
out += "\n---\n\n"
return out
def trig_tables():
"""Trigonometric functions at 1° intervals."""
out = "## Trigonometric Functions\n\n"
out += "Values of sin, cos, and tan for 0° to 90° in 1° increments.\n\n"
out += "| Deg | sin | cos | tan | Deg | sin | cos | tan |\n"
out += "|-----|------|------|------|-----|------|------|------|\n"
for deg in range(0, 46):
rad = math.radians(deg)
sin_v = math.sin(rad)
cos_v = math.cos(rad)
tan_v = math.tan(rad) if deg != 90 else "—"
deg2 = deg + 45
if deg2 <= 90:
rad2 = math.radians(deg2)
sin_v2 = math.sin(rad2)
cos_v2 = math.cos(rad2)
if deg2 == 90:
tan_v2 = "∞"
else:
tan_v2 = f"{math.tan(rad2):.4f}"
if isinstance(tan_v, float):
tan_v = f"{tan_v:.4f}"
out += f"| {deg}° | {sin_v:.4f} | {cos_v:.4f} | {tan_v} | {deg2}° | {sin_v2:.4f} | {cos_v2:.4f} | {tan_v2} |\n"
else:
if isinstance(tan_v, float):
tan_v = f"{tan_v:.4f}"
out += f"| {deg}° | {sin_v:.4f} | {cos_v:.4f} | {tan_v} | | | | |\n"
out += "\n---\n\n"
return out
def trig_fine_tables():
"""Trigonometric functions at 0.1° intervals for navigation use."""
out = "## Trigonometric Functions — Fine Resolution (0.1°)\n\n"
out += "For celestial navigation sight reduction. Values at 0.1° intervals, 0°–90°.\n\n"
out += "| Deg | sin | cos | tan |\n"
out += "|------|--------|--------|--------|\n"
for i in range(0, 901):
deg = i / 10.0
rad = math.radians(deg)
sin_v = math.sin(rad)
cos_v = math.cos(rad)
if deg == 90.0:
tan_v = "∞"
else:
tan_v = f"{math.tan(rad):.6f}"
out += f"| {deg:5.1f}° | {sin_v:.6f} | {cos_v:.6f} | {tan_v} |\n"
out += "\n---\n\n"
return out
def natural_log_table():
"""Natural logarithms for 1.0 to 10.0 in steps of 0.1."""
out = "## Natural Logarithms (ln)\n\n"
out += "ln(N) for N = 0.1 to 10.0. Use ln(a × eⁿ) = ln(a) + n.\n\n"
out += "| N | ln(N) | N | ln(N) | N | ln(N) | N | ln(N) |\n"
out += "|-----|--------|-----|--------|-----|--------|-----|--------|\n"
values = []
for i in range(1, 101):
n = i / 10.0
values.append((n, math.log(n)))
# 4 columns
rows = (len(values) + 3) // 4
for r in range(rows):
parts = []
for c in range(4):
idx = r + c * rows
if idx < len(values):
n, ln_n = values[idx]
parts.append(f"| {n:5.1f} | {ln_n:7.4f}")
else:
parts.append("| | ")
out += " ".join(parts) + " |\n"
out += "\n---\n\n"
return out
def sqrt_table():
"""Square roots of 1 to 200."""
out = "## Square Roots\n\n"
out += "√N for N = 1 to 200.\n\n"
out += "| N | √N | N | √N | N | √N | N | √N |\n"
out += "|---|------|---|------|---|------|---|------|\n"
rows = 50
for r in range(rows):
parts = []
for c in range(4):
n = r + 1 + c * rows
if n <= 200:
parts.append(f"| {n:3d} | {math.sqrt(n):.4f}")
else:
parts.append("| | ")
out += " ".join(parts) + " |\n"
out += "\n---\n\n"
return out
def reciprocal_table():
"""Reciprocals of 1 to 200."""
out = "## Reciprocals\n\n"
out += "1/N for N = 1 to 200.\n\n"
out += "| N | 1/N | N | 1/N | N | 1/N | N | 1/N |\n"
out += "|---|--------|---|--------|---|--------|---|--------|\n"
rows = 50
for r in range(rows):
parts = []
for c in range(4):
n = r + 1 + c * rows
if n <= 200:
parts.append(f"| {n:3d} | {1/n:.6f}")
else:
parts.append("| | ")
out += " ".join(parts) + " |\n"
out += "\n---\n\n"
return out
def powers_table():
"""Powers of 2, e, and 10."""
out = "## Powers and Exponentials\n\n"
out += "### Powers of 2\n\n"
out += "| n | 2ⁿ | n | 2ⁿ |\n"
out += "|---|-----|---|-----|\n"
for i in range(0, 17):
j = i + 17
if j <= 32:
out += f"| {i} | {2**i:,} | {j} | {2**j:,} |\n"
else:
out += f"| {i} | {2**i:,} | | |\n"
out += "\n### Powers of e\n\n"
out += "| x | eˣ | x | eˣ |\n"
out += "|-----|----------|-----|----------|\n"
e_values = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10]
half = (len(e_values) + 1) // 2
for i in range(half):
x1 = e_values[i]
v1 = math.exp(x1)
if i + half < len(e_values):
x2 = e_values[i + half]
v2 = math.exp(x2)
out += f"| {x1} | {v1:.6f} | {x2} | {v2:.4f} |\n"
else:
out += f"| {x1} | {v1:.6f} | | |\n"
out += "\n### Powers of 10\n\n"
out += "| n | 10ⁿ |\n"
out += "|---|-----|\n"
for i in range(-10, 11):
if i < 0:
out += f"| {i} | {10**i:.10f} |\n"
else:
out += f"| {i} | {10**i:,} |\n"
out += "\n---\n\n"
return out
def conversion_table():
"""Unit conversion factors."""
out = "## Unit Conversion Factors\n\n"
out += "### Length\n\n"
out += "| From | To | Multiply by |\n"
out += "|------|------|-------------|\n"
conversions_length = [
("metres", "feet", 3.28084),
("metres", "inches", 39.3701),
("metres", "yards", 1.09361),
("kilometres", "miles", 0.621371),
("kilometres", "nautical miles", 0.539957),
("nautical miles", "kilometres", 1.852),
("nautical miles", "statute miles", 1.15078),
("inches", "millimetres", 25.4),
("feet", "metres", 0.3048),
("miles", "kilometres", 1.60934),
("fathoms", "metres", 1.8288),
]
for f, t, v in conversions_length:
out += f"| {f} | {t} | {v} |\n"
out += "\n### Mass\n\n"
out += "| From | To | Multiply by |\n"
out += "|------|------|-------------|\n"
conversions_mass = [
("kilograms", "pounds", 2.20462),
("pounds", "kilograms", 0.453592),
("tonnes (metric)", "short tons", 1.10231),
("tonnes (metric)", "long tons", 0.984207),
("ounces", "grams", 28.3495),
("troy ounces", "grams", 31.1035),
]
for f, t, v in conversions_mass:
out += f"| {f} | {t} | {v} |\n"
out += "\n### Volume\n\n"
out += "| From | To | Multiply by |\n"
out += "|------|------|-------------|\n"
conversions_vol = [
("litres", "US gallons", 0.264172),
("litres", "imperial gallons", 0.219969),
("US gallons", "litres", 3.78541),
("imperial gallons", "litres", 4.54609),
("cubic metres", "litres", 1000),
("cubic feet", "litres", 28.3168),
]
for f, t, v in conversions_vol:
out += f"| {f} | {t} | {v} |\n"
out += "\n### Temperature\n\n"
out += "°F = °C × 9/5 + 32 \n"
out += "°C = (°F − 32) × 5/9 \n"
out += "K = °C + 273.15\n\n"
out += "| °C | °F | K |\n"
out += "|----|-----|------|\n"
temps = [-40, -30, -20, -10, 0, 5, 10, 15, 20, 25, 30, 37, 40, 50,
60, 80, 100, 150, 200, 500, 1000]
for c in temps:
f = c * 9 / 5 + 32
k = c + 273.15
out += f"| {c} | {f:.1f} | {k:.2f} |\n"
out += "\n### Pressure\n\n"
out += "| From | To | Multiply by |\n"
out += "|------|------|-------------|\n"
conversions_press = [
("atmospheres", "kPa", 101.325),
("atmospheres", "psi", 14.696),
("bar", "kPa", 100),
("psi", "kPa", 6.89476),
("mmHg (torr)", "kPa", 0.133322),
("inHg", "kPa", 3.38639),
]
for f, t, v in conversions_press:
out += f"| {f} | {t} | {v} |\n"
out += "\n### Energy\n\n"
out += "| From | To | Multiply by |\n"
out += "|------|------|-------------|\n"
conversions_energy = [
("kWh", "MJ", 3.6),
("kWh", "BTU", 3412.14),
("MJ", "kWh", 0.277778),
("calories", "joules", 4.184),
("BTU", "kJ", 1.05506),
("horsepower-hours", "kWh", 0.7457),
]
for f, t, v in conversions_energy:
out += f"| {f} | {t} | {v} |\n"
out += "\n---\n\n"
return out
def constants_table():
"""Physical and mathematical constants."""
out = "## Physical and Mathematical Constants\n\n"
out += "### Mathematical Constants\n\n"
out += "| Constant | Symbol | Value |\n"
out += "|----------|--------|-------|\n"
out += f"| Pi | π | {math.pi:.15f} |\n"
out += f"| Euler's number | e | {math.e:.15f} |\n"
out += f"| √2 | | {math.sqrt(2):.15f} |\n"
out += f"| √3 | | {math.sqrt(3):.15f} |\n"
out += f"| ln(2) | | {math.log(2):.15f} |\n"
out += f"| ln(10) | | {math.log(10):.15f} |\n"
out += f"| log₁₀(2) | | {math.log10(2):.15f} |\n"
out += f"| log₁₀(e) | | {math.log10(math.e):.15f} |\n"
out += f"| 1 radian | | {math.degrees(1):.10f}° |\n"
out += f"| 1 degree | | {math.radians(1):.15f} rad |\n"
out += "\n### Physical Constants\n\n"
out += "| Constant | Symbol | Value | Unit |\n"
out += "|----------|--------|-------|------|\n"
phys_constants = [
("Speed of light in vacuum", "c", "299,792,458", "m/s"),
("Gravitational constant", "G", "6.674 × 10⁻¹¹", "N⋅m²/kg²"),
("Planck constant", "h", "6.626 × 10⁻³⁴", "J⋅s"),
("Boltzmann constant", "k_B", "1.381 × 10⁻²³", "J/K"),
("Avogadro's number", "N_A", "6.022 × 10²³", "mol⁻¹"),
("Gas constant", "R", "8.314", "J/(mol⋅K)"),
("Stefan-Boltzmann constant", "σ", "5.670 × 10⁻⁸", "W/(m²⋅K⁴)"),
("Elementary charge", "e", "1.602 × 10⁻¹⁹", "C"),
("Electron mass", "m_e", "9.109 × 10⁻³¹", "kg"),
("Proton mass", "m_p", "1.673 × 10⁻²⁷", "kg"),
("Standard gravity", "g", "9.80665", "m/s²"),
("Standard atmosphere", "atm", "101,325", "Pa"),
("Absolute zero", "", "−273.15", "°C"),
("Water triple point", "", "273.16", "K"),
("Solar constant", "", "1,361", "W/m²"),
]
for name, sym, val, unit in phys_constants:
out += f"| {name} | {sym} | {val} | {unit} |\n"
out += "\n### Astronomical Constants\n\n"
out += "| Constant | Value | Unit |\n"
out += "|----------|-------|------|\n"
astro = [
("Earth equatorial radius", "6,378.137", "km"),
("Earth polar radius", "6,356.752", "km"),
("Earth mean radius", "6,371.0", "km"),
("Earth mass", "5.972 × 10²⁴", "kg"),
("Earth-Sun mean distance (1 AU)", "149,597,870.7", "km"),
("Earth orbital period (sidereal year)", "365.25636", "days"),
("Earth axial tilt (J2000)", "23.4393°", ""),
("Moon mean distance", "384,400", "km"),
("Moon orbital period (sidereal)", "27.322", "days"),
("Moon synodic period", "29.531", "days"),
("Solar radius", "695,700", "km"),
("Solar luminosity", "3.828 × 10²⁶", "W"),
]
for name, val, unit in astro:
out += f"| {name} | {val} | {unit} |\n"
out += "\n---\n\n"
return out
def factorial_table():
"""Factorials and common combinatorial values."""
out = "## Factorials\n\n"
out += "| n | n! | ln(n!) |\n"
out += "|---|------|--------|\n"
for n in range(0, 26):
fact = math.factorial(n)
ln_fact = math.lgamma(n + 1)
out += f"| {n} | {fact:,} | {ln_fact:.4f} |\n"
out += "\n---\n\n"
return out
def main():
output_file = sys.argv[1] if len(sys.argv) > 1 else os.path.join(
os.path.dirname(os.path.abspath(__file__)), "..", "tables-mathematical.md"
)
content = header()
content += log_tables()
content += trig_tables()
content += trig_fine_tables()
content += natural_log_table()
content += sqrt_table()
content += reciprocal_table()
content += factorial_table()
content += powers_table()
content += conversion_table()
content += constants_table()
content += "*Generated by `scripts/generate_math_tables.py` using Python's "
content += "`math` module (IEEE 754 double precision).*\n"
with open(output_file, 'w') as f:
f.write(content)
print(f"Written to {output_file}")
print(f"Total lines: {content.count(chr(10))}")
if __name__ == "__main__":
main()