use crate::*;
pub fn convert_power(measured_power_diopters: f64, n_assumed: f64, n_actual: f64) -> f64 {
assert!(n_assumed > 1.0, "n_assumed must be > 1.0");
assert!(n_actual > 1.0, "n_actual must be > 1.0");
let k_assumed = n_assumed - 1.0;
let k_actual = n_actual - 1.0;
measured_power_diopters * (k_actual / k_assumed)
}
pub fn convert_rx(
measured: SpheroCyl,
n_assumed: f64,
n_actual: f64,
) -> SpheroCyl {
let s = convert_power(measured.sphere, n_assumed, n_actual);
let c = convert_power(measured.cylinder, n_assumed, n_actual);
SpheroCyl {
sphere: s,
cylinder: c,
axis_deg: measured.axis_deg,
}
}
pub fn simulate_lensmeter_reading(
true_rx: SpheroCyl,
n_assumed: f64,
n_actual: f64,
) -> SpheroCyl {
let s = convert_power(true_rx.sphere, n_actual, n_assumed);
let c = convert_power(true_rx.cylinder, n_actual, n_assumed);
SpheroCyl {
sphere: s,
cylinder: c,
axis_deg: true_rx.axis_deg,
}
}
#[cfg(test)]
mod tests {
use super::*;
use approx::{assert_abs_diff_eq, assert_relative_eq};
const EPS: f64 = 1e-3;
#[test]
fn convert_power_poly_example_true_from_measured() {
let n_assumed = 1.523;
let n_actual = 1.586;
let measured = -4.463;
let true_power = convert_power(measured, n_assumed, n_actual);
assert_abs_diff_eq!(true_power, -5.00, epsilon = EPS);
}
#[test]
fn convert_power_measured_from_true_inverse() {
let n_assumed = 1.523;
let n_actual = 1.586;
let true_power = -5.00;
let measured = convert_power(true_power, n_actual, n_assumed);
assert_abs_diff_eq!(measured, -4.463, epsilon = EPS);
}
#[test]
fn convert_power_zero_is_stable() {
let z = convert_power(0.0, 1.523, 1.586);
assert_abs_diff_eq!(z, 0.0, epsilon = EPS);
}
#[test]
fn convert_rx_scales_sphere_and_cylinder_axis_unchanged() {
let n_assumed = 1.523;
let n_actual = 1.586;
let measured = SpheroCyl { sphere: -2.00, cylinder: -1.00, axis_deg: 180.0 };
let out = convert_rx(measured, n_assumed, n_actual);
let factor = (n_actual - 1.0) / (n_assumed - 1.0); let expected_s = measured.sphere * factor; let expected_c = measured.cylinder * factor;
assert_abs_diff_eq!(out.sphere, expected_s, epsilon = EPS);
assert_abs_diff_eq!(out.cylinder, expected_c, epsilon = EPS);
assert_abs_diff_eq!(out.axis_deg, measured.axis_deg, epsilon = 1e-9);
}
#[test]
fn convert_rx_handles_plus_cylinder_notation() {
let n_assumed = 1.523;
let n_actual = 1.586;
let measured = SpheroCyl { sphere: -1.00, cylinder: 1.00, axis_deg: 90.0 };
let out = convert_rx(measured, n_assumed, n_actual);
let factor = (n_actual - 1.0) / (n_assumed - 1.0);
assert_abs_diff_eq!(out.sphere, measured.sphere * factor, epsilon = EPS);
assert_abs_diff_eq!(out.cylinder, measured.cylinder * factor, epsilon = EPS);
assert_abs_diff_eq!(out.axis_deg, 90.0, epsilon = 1e-9);
}
#[test]
fn simulate_lensmeter_reading_inverse_of_convert_rx() {
let n_assumed = 1.523;
let n_actual = 1.586;
let true_rx = SpheroCyl { sphere: -3.25, cylinder: -2.25, axis_deg: 37.0 };
let reading = simulate_lensmeter_reading(true_rx, n_assumed, n_actual);
let recovered = convert_rx(reading, n_assumed, n_actual);
assert_abs_diff_eq!(recovered.sphere, true_rx.sphere, epsilon = EPS);
assert_abs_diff_eq!(recovered.cylinder, true_rx.cylinder, epsilon = EPS);
assert_abs_diff_eq!(recovered.axis_deg, true_rx.axis_deg, epsilon = 1e-9);
}
#[test]
fn convert_rx_zero_cylinder_passes_through() {
let n_assumed = 1.523;
let n_actual = 1.586;
let measured = SpheroCyl { sphere: 2.50, cylinder: 0.0, axis_deg: 5.0 };
let out = convert_rx(measured, n_assumed, n_actual);
let factor = (n_actual - 1.0) / (n_assumed - 1.0);
assert_abs_diff_eq!(out.sphere, 2.50 * factor, epsilon = EPS);
assert_abs_diff_eq!(out.cylinder, 0.0, epsilon = EPS);
assert_abs_diff_eq!(out.axis_deg, 5.0, epsilon = 1e-9);
}
#[test]
#[should_panic(expected = "n_assumed must be > 1.0")]
fn convert_power_panics_on_bad_assumed_index() {
let _ = convert_power(1.0, 1.0, 1.586);
}
#[test]
#[should_panic(expected = "n_actual must be > 1.0")]
fn convert_power_panics_on_bad_actual_index() {
let _ = convert_power(1.0, 1.523, 1.0);
}
#[test]
fn relative_tolerance_example_factor() {
let n_assumed = 1.523;
let n_actual = 1.586;
let factor = (n_actual - 1.0) / (n_assumed - 1.0);
assert_relative_eq!(factor, 1.120458, max_relative = 1e-6);
}
}