use std::f64::consts::PI;
use tracing::{instrument, warn};
use crate::constants::{C, G, HBAR, K_B};
use crate::error::{MimamsaError, ensure_finite, require_finite};
use crate::relativity::black_hole::bekenstein_hawking_entropy;
#[instrument(level = "trace")]
#[inline]
pub fn bekenstein_bound(radius_m: f64, energy_j: f64) -> Result<f64, MimamsaError> {
require_finite(radius_m, "bekenstein_bound")?;
require_finite(energy_j, "bekenstein_bound")?;
if radius_m <= 0.0 {
warn!(radius_m, "bekenstein_bound: radius must be positive");
return Err(MimamsaError::Computation(
"bekenstein_bound: radius must be positive".to_string(),
));
}
if energy_j <= 0.0 {
warn!(energy_j, "bekenstein_bound: energy must be positive");
return Err(MimamsaError::Computation(
"bekenstein_bound: energy must be positive".to_string(),
));
}
ensure_finite(
2.0 * PI * K_B * radius_m * energy_j / (HBAR * C),
"bekenstein_bound",
)
}
#[instrument(level = "trace")]
#[inline]
pub fn holographic_bound(area_m2: f64) -> Result<f64, MimamsaError> {
require_finite(area_m2, "holographic_bound")?;
if area_m2 <= 0.0 {
warn!(area_m2, "holographic_bound: area must be positive");
return Err(MimamsaError::Computation(
"holographic_bound: area must be positive".to_string(),
));
}
let lp2 = HBAR * G / C.powi(3);
ensure_finite(K_B * area_m2 / (4.0 * lp2), "holographic_bound")
}
#[instrument(level = "trace")]
#[inline]
pub fn information_content_bits(entropy_j_per_k: f64) -> Result<f64, MimamsaError> {
require_finite(entropy_j_per_k, "information_content_bits")?;
if entropy_j_per_k < 0.0 {
warn!(
entropy_j_per_k,
"information_content_bits: entropy must be non-negative"
);
return Err(MimamsaError::Computation(
"information_content_bits: entropy must be non-negative".to_string(),
));
}
ensure_finite(
entropy_j_per_k / (K_B * 2.0_f64.ln()),
"information_content_bits",
)
}
#[instrument(level = "trace")]
pub fn black_hole_information_bits(mass_kg: f64) -> Result<f64, MimamsaError> {
require_finite(mass_kg, "black_hole_information_bits")?;
if mass_kg <= 0.0 {
warn!(
mass_kg,
"black_hole_information_bits: mass must be positive"
);
return Err(MimamsaError::Computation(
"black_hole_information_bits: mass must be positive".to_string(),
));
}
let entropy = bekenstein_hawking_entropy(mass_kg)?;
information_content_bits(entropy)
}
#[instrument(level = "trace")]
#[inline]
pub fn cosmological_horizon_entropy(hubble_param_si: f64) -> Result<f64, MimamsaError> {
require_finite(hubble_param_si, "cosmological_horizon_entropy")?;
if hubble_param_si <= 0.0 {
warn!(
hubble_param_si,
"cosmological_horizon_entropy: H must be positive"
);
return Err(MimamsaError::Computation(
"cosmological_horizon_entropy: H must be positive".to_string(),
));
}
let h2 = hubble_param_si * hubble_param_si;
ensure_finite(
PI * K_B * C.powi(5) / (G * HBAR * h2),
"cosmological_horizon_entropy",
)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::relativity::metric::schwarzschild_radius;
const M_SUN: f64 = 1.989e30;
#[test]
fn test_bekenstein_bound_positive() {
let s = bekenstein_bound(1.0, 1.0).unwrap();
assert!(s > 0.0);
}
#[test]
fn test_holographic_bound_matches_bh_entropy() {
let rs = schwarzschild_radius(M_SUN).unwrap();
let area = 4.0 * PI * rs * rs;
let s_holo = holographic_bound(area).unwrap();
let s_bh = bekenstein_hawking_entropy(M_SUN).unwrap();
let rel_diff = (s_holo - s_bh).abs() / s_bh;
assert!(rel_diff < 1e-6, "holographic vs BH entropy: {rel_diff}");
}
#[test]
fn test_information_1_bit() {
let one_bit_entropy = K_B * 2.0_f64.ln();
let bits = information_content_bits(one_bit_entropy).unwrap();
assert!((bits - 1.0).abs() < 1e-10);
}
#[test]
fn test_black_hole_information_positive() {
let bits = black_hole_information_bits(M_SUN).unwrap();
assert!(bits > 1e70, "solar mass BH info: {bits:.2e} bits");
}
#[test]
fn test_cosmological_horizon_entropy_positive() {
let h0_si = 67.4 / 3.085_677_581e19;
let s = cosmological_horizon_entropy(h0_si).unwrap();
assert!(s > 1e90, "cosmic horizon entropy: {s:.2e}");
}
#[test]
fn test_negative_inputs_rejected() {
assert!(bekenstein_bound(-1.0, 1.0).is_err());
assert!(bekenstein_bound(1.0, -1.0).is_err());
assert!(holographic_bound(-1.0).is_err());
assert!(information_content_bits(-1.0).is_err());
assert!(black_hole_information_bits(-1.0).is_err());
assert!(cosmological_horizon_entropy(-1.0).is_err());
}
}