use plotters::prelude::*;
use fixed_trigonometry::*;
use mixed_num::traits::*;
#[test]
fn atan2_comparison() -> Result<(), Box<dyn std::error::Error>>
{
use fixed::FixedI32 as F;
use fixed::types::extra::U28 as U;
use std::f32::consts::PI as PI;
let root = BitMapBackend::new("figures/atan2_comparisons.png", (1000, 500)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.margin(10)
.x_label_area_size(40)
.y_label_area_size(50)
.build_cartesian_2d( -PI..PI, -PI..PI)?;
chart
.configure_mesh()
.disable_x_mesh()
.bold_line_style(&WHITE.mix(0.3))
.y_desc("atan2( Im{e^(iθ)) , Re{e^(iθ))} )")
.x_desc("θ")
.axis_desc_style(("sans-serif", 15))
.draw()?;
chart.configure_mesh().draw()?;
let atan2_series = LineSeries::new(
(-500..=500).map(|x| x as f32 *PI / 500.0).map(|x| (x, atan::atan2(F::<U>::from_num(x.sin()), F::<U>::from_num(x.cos()) ).to_num::<f32>() )),
&RED);
chart
.draw_series( atan2_series )?
.label("atan::atan2")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
let std_atan_series = LineSeries::new(
(-500..=500).map(|x| x as f32 *PI / 500.0).map(|x| (x, f32::atan2(x.sin(),x.cos()) )),
&BLUE);
chart
.draw_series( std_atan_series )?
.label("f32::atan2")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE));
chart
.configure_series_labels()
.background_style(&WHITE.mix(0.8))
.border_style(&BLACK)
.draw()?;
Ok(())
}
#[test]
fn atan_comparison() -> Result<(), Box<dyn std::error::Error>>
{
use fixed::FixedI32 as F;
use fixed::types::extra::U22 as U;
use std::f32::consts::PI as PI;
let root = BitMapBackend::new("figures/atan_comparisons.png", (1000, 500)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.margin(10)
.x_label_area_size(40)
.y_label_area_size(50)
.right_y_label_area_size(60)
.build_cartesian_2d( -10f32..10f32, -PI/2.0..PI/2.0)?
.set_secondary_coord( -10f32..10f32, 0f32..0.005f32);
chart
.configure_mesh()
.disable_x_mesh()
.bold_line_style(&WHITE.mix(0.3))
.y_desc("atan(θ)")
.x_desc("θ")
.axis_desc_style(("sans-serif", 15))
.draw()?;
chart
.configure_secondary_axes()
.y_desc("Error")
.draw()?;
chart.configure_mesh().draw()?;
let trig_atan_series = LineSeries::new(
(-500..=500).map(|x| x as f32 *10.0 / 500.0).map(|x| (x, atan::atan( F::<U>::mixed_from_num(x) ).to_num::<f32>() )),
&RED);
chart
.draw_series( trig_atan_series )?
.label("atan::atan")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
let std_atan_error = LineSeries::new(
(-500..=500).map(|x| x as f32 *10.0 / 500.0).map(|x| (x, f32::abs(f32::atan(x) - atan::atan( F::<U>::mixed_from_num(x) ).to_num::<f32>()) )),
&BLUE);
chart
.draw_secondary_series( std_atan_error )?
.label("Error")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE));
chart
.configure_series_labels()
.background_style(&WHITE.mix(0.8))
.border_style(&BLACK)
.draw()?;
Ok(())
}
#[test]
fn atan_error_comparison() -> Result<(), Box<dyn std::error::Error>>
{
use fixed::FixedI32 as F;
use fixed::types::extra::U22 as U;
use cordic;
let root = BitMapBackend::new("figures/atan_error_comparisons.png", (1000, 500)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.margin(10)
.x_label_area_size(40)
.y_label_area_size(70)
.right_y_label_area_size(70)
.build_cartesian_2d( -10f32..10f32, 0f32..0.005f32)?
.set_secondary_coord( -10f32..10f32, 0f32..1e-4f32);
chart
.configure_mesh()
.disable_x_mesh()
.bold_line_style(&WHITE.mix(0.3))
.y_desc("Error (atan::atan)")
.x_desc("θ")
.axis_desc_style(("sans-serif", 15))
.draw()?;
chart
.configure_secondary_axes()
.y_desc("Error (cordic)")
.draw()?;
chart.configure_mesh().draw()?;
let std_atan_error = LineSeries::new(
(-500..=500).map(|x| x as f32 *10.0 / 500.0).map(|x| (x, f32::abs(f32::atan(x) - atan::atan( F::<U>::mixed_from_num(x) ).to_num::<f32>()) )),
&RED);
chart
.draw_series( std_atan_error )?
.label("atan::atan error")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
let cordic_std_atan_error = LineSeries::new(
(-500..=500).map(|x| x as f32 *10.0 / 500.0).map(|x| (x, f32::abs(f32::atan(x) - cordic::atan( F::<U>::from_num(x) ).to_num::<f32>()) )),
&BLUE);
chart
.draw_secondary_series( cordic_std_atan_error )?
.label("cordic::atan error")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE));
chart
.configure_series_labels()
.background_style(&WHITE.mix(0.8))
.border_style(&BLACK)
.draw()?;
Ok(())
}