// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#![allow(clippy::needless_raw_string_hashes)]

use super::{
    get_latex, write_latex_for_algebraic_number, write_latex_for_cartesian_form,
    write_latex_for_decimal_number, write_latex_for_polar_form, write_latex_for_real_number,
    write_latex_for_term, AlgebraicNumber, CartesianForm, ComplexNumber, DecimalNumber, PolarForm,
    RationalNumber, RealNumber, Term,
};
use crate::state::{is_fractional_part_significant, is_significant};
use expect_test::{expect, Expect};
use num_complex::Complex64;
use std::{f64::consts::PI, time::Instant};

#[test]
fn check_is_significant() {
    assert!(!is_significant(0.0));
    assert!(!is_significant(1e-10));
    assert!(!is_significant(-1e-10));
    assert!(is_significant(1.1e-9));
    assert!(is_significant(-1.1e-9));
    assert!(is_significant(1.0));
    assert!(is_significant(-1.0));
}

#[test]
fn check_is_fractional_part_significant() {
    assert!(!is_fractional_part_significant(0.0));
    assert!(!is_fractional_part_significant(1e-10));
    assert!(!is_fractional_part_significant(-1e-10));
    assert!(is_fractional_part_significant(1.1e-9));
    assert!(is_fractional_part_significant(-1.1e-9));
    assert!(!is_fractional_part_significant(1.000_000_000_1));
    assert!(!is_fractional_part_significant(-1.000_000_000_1));
    assert!(is_fractional_part_significant(1.000_000_001));
    assert!(is_fractional_part_significant(-1.000_000_001));
}

fn assert_rational_value(x: Option<RationalNumber>, expected: (i64, i64, i64)) {
    match x {
        None => panic!("Expected rational number."),
        Some(r) => assert!(
            r.sign == expected.0 && r.numerator == expected.1 && r.denominator == expected.2
        ),
    }
}

#[test]
fn check_construct_rational() {
    assert_rational_value(Some(RationalNumber::new(1, 2)), (1, 1, 2));
    assert_rational_value(Some(RationalNumber::new(-1, 2)), (-1, 1, 2));
    assert_rational_value(Some(RationalNumber::new(1, -2)), (-1, 1, 2));
    assert_rational_value(Some(RationalNumber::new(-1, -2)), (1, 1, 2));
    // Although 0 is never used in the code we check it for completeness.
    assert_rational_value(Some(RationalNumber::new(0, 1)), (0, 0, 1));
    expect!([r"
        RationalNumber {
            sign: 1,
            numerator: 1,
            denominator: 2,
        }
    "])
    .assert_debug_eq(&RationalNumber::new(1, 2));
}

#[test]
fn check_abs_rational() {
    assert_rational_value(Some(RationalNumber::new(1, 2).abs()), (1, 1, 2));
    assert_rational_value(Some(RationalNumber::new(-1, 2).abs()), (1, 1, 2));
    assert_rational_value(Some(RationalNumber::new(1, -2).abs()), (1, 1, 2));
    assert_rational_value(Some(RationalNumber::new(-1, -2).abs()), (1, 1, 2));
    // Although 0 is never used in the code we check it for completeness.
    assert_rational_value(Some(RationalNumber::new(0, 1).abs()), (0, 0, 1));
}

#[test]
fn check_recognize_rational() {
    assert_rational_value(RationalNumber::recognize(1.0 / 1.0), (1, 1, 1));
    assert_rational_value(RationalNumber::recognize(1.0 / 2.0), (1, 1, 2));
    assert_rational_value(RationalNumber::recognize(1.0 / 3.0), (1, 1, 3));
    assert_rational_value(RationalNumber::recognize(-5.0 / 7.0), (-1, 5, 7));
    assert!(RationalNumber::recognize(1.0 / 1000.0).is_none());
    assert!(RationalNumber::recognize(1000.0 / 1.0).is_none());
    // Although 0 is never used in the code we check it for completeness.
    assert_rational_value(RationalNumber::recognize(0.0), (0, 0, 1));
}

fn assert_algebraic_value(x: Option<AlgebraicNumber>, expected: (i64, i64, i64, i64, i64)) {
    match x {
        None => panic!("Expected algebraic number."),
        Some(a) => assert!(
            a.sign == expected.0
                && a.fraction.sign == expected.1
                && a.fraction.numerator == expected.2
                && a.fraction.denominator == expected.3
                && a.root == expected.4
        ),
    }
}

#[test]
fn check_construct_algebraic() {
    assert_algebraic_value(
        Some(AlgebraicNumber::new(&RationalNumber::new(1, 2), 3)),
        (1, 1, 1, 2, 3),
    );
    assert_algebraic_value(
        Some(AlgebraicNumber::new(&RationalNumber::new(-1, 2), 3)),
        (-1, 1, 1, 2, 3),
    );
    assert_algebraic_value(
        Some(AlgebraicNumber::new(&RationalNumber::new(1, -2), 3)),
        (-1, 1, 1, 2, 3),
    );
    assert_algebraic_value(
        Some(AlgebraicNumber::new(&RationalNumber::new(-1, -2), 3)),
        (1, 1, 1, 2, 3),
    );
    expect!([r"
        AlgebraicNumber {
            sign: 1,
            fraction: RationalNumber {
                sign: 1,
                numerator: 1,
                denominator: 2,
            },
            root: 3,
        }
    "])
    .assert_debug_eq(&AlgebraicNumber::new(&RationalNumber::new(1, 2), 3));
}

#[test]
fn check_recognize_algebraic() {
    assert_algebraic_value(AlgebraicNumber::recognize(5.0), (1, 1, 5, 1, 1));
    assert_algebraic_value(AlgebraicNumber::recognize(1.0 / 7.0), (1, 1, 1, 7, 1));
    assert_algebraic_value(AlgebraicNumber::recognize(7.0 / 10.0), (1, 1, 7, 10, 1));
    assert_algebraic_value(
        AlgebraicNumber::recognize(2.0 * 2.0_f64.sqrt()),
        (1, 1, 2, 1, 2),
    );
    assert_algebraic_value(AlgebraicNumber::recognize(8.0_f64.sqrt()), (1, 1, 2, 1, 2));
    assert_algebraic_value(
        AlgebraicNumber::recognize(5.0_f64.sqrt() / 15.0),
        (1, 1, 1, 15, 5),
    );
    assert_algebraic_value(
        AlgebraicNumber::recognize(3.0 / 5.0 * 2.0_f64.sqrt()),
        (1, 1, 3, 5, 2),
    );
    assert_algebraic_value(
        AlgebraicNumber::recognize(-3.0 / 5.0 * 2.0_f64.sqrt()),
        (-1, 1, 3, 5, 2),
    );
}

fn assert_decimal_value(x: &DecimalNumber, expected: (i64, f64)) {
    assert!(x.sign == expected.0 && (x.value - expected.1).abs() < f64::EPSILON);
}

#[test]
fn check_construct_decimal() {
    assert_decimal_value(&DecimalNumber::new(0.777), (1, 0.777));
    assert_decimal_value(&DecimalNumber::new(-0.777), (-1, 0.777));
    expect!([r"
        DecimalNumber {
            sign: 1,
            value: 1.0,
        }
    "])
    .assert_debug_eq(&DecimalNumber::new(1.0));
}

#[test]
fn check_recognize_decimal() {
    assert_decimal_value(&DecimalNumber::recognize(0.777), (1, 0.777));
    assert_decimal_value(&DecimalNumber::recognize(-0.777), (-1, 0.777));
}

#[test]
fn check_recognize_real_number() {
    expect!([r"
        Zero
    "])
    .assert_debug_eq(&RealNumber::recognize(0.0));

    expect!([r"
        Algebraic(
            AlgebraicNumber {
                sign: 1,
                fraction: RationalNumber {
                    sign: 1,
                    numerator: 5,
                    denominator: 3,
                },
                root: 2,
            },
        )
    "])
    .assert_debug_eq(&RealNumber::recognize(5.0 * 2.0_f64.sqrt() / 3.0));

    expect!([r"
        Algebraic(
            AlgebraicNumber {
                sign: 1,
                fraction: RationalNumber {
                    sign: 1,
                    numerator: 7,
                    denominator: 10,
                },
                root: 1,
            },
        )
    "])
    .assert_debug_eq(&RealNumber::recognize(7.0 / 10.0));

    expect!([r"
        Decimal(
            DecimalNumber {
                sign: 1,
                value: 0.00558659217877095,
            },
        )
    "])
    .assert_debug_eq(&RealNumber::recognize(1.0 / 179.0));

    expect!([r"
        Algebraic(
            AlgebraicNumber {
                sign: -1,
                fraction: RationalNumber {
                    sign: 1,
                    numerator: 2,
                    denominator: 3,
                },
                root: 1,
            },
        )
    "])
    .assert_debug_eq(&RealNumber::recognize(-2.0 / 3.0));

    expect!([r"
        Algebraic(
            AlgebraicNumber {
                sign: -1,
                fraction: RationalNumber {
                    sign: 1,
                    numerator: 5,
                    denominator: 7,
                },
                root: 3,
            },
        )
    "])
    .assert_debug_eq(&RealNumber::recognize(-5.0 * 3.0_f64.sqrt() / 7.0));
}

#[test]
fn check_recognize_polar() {
    expect!([r"
        Some(
            PolarForm {
                sign: 1,
                magnitude: AlgebraicNumber {
                    sign: 1,
                    fraction: RationalNumber {
                        sign: 1,
                        numerator: 5,
                        denominator: 2,
                    },
                    root: 1,
                },
                phase_multiplier: RationalNumber {
                    sign: 1,
                    numerator: 1,
                    denominator: 3,
                },
            },
        )
    "])
    .assert_debug_eq(&PolarForm::recognize(
        5.0 / 2.0 * (PI / 3.0).cos(),
        5.0 / 2.0 * (PI / 3.0).sin(),
    ));
    expect!([r"
        Some(
            PolarForm {
                sign: 1,
                magnitude: AlgebraicNumber {
                    sign: 1,
                    fraction: RationalNumber {
                        sign: 1,
                        numerator: 5,
                        denominator: 2,
                    },
                    root: 1,
                },
                phase_multiplier: RationalNumber {
                    sign: -1,
                    numerator: 1,
                    denominator: 3,
                },
            },
        )
    "])
    .assert_debug_eq(&PolarForm::recognize(
        5.0 / 2.0 * (PI / 3.0).cos(),
        5.0 / 2.0 * (-PI / 3.0).sin(),
    ));
}

#[test]
fn check_recognize_cartesian() {
    expect!([r"
        CartesianForm {
            sign: -1,
            real_part: Zero,
            imaginary_part: Algebraic(
                AlgebraicNumber {
                    sign: 1,
                    fraction: RationalNumber {
                        sign: 1,
                        numerator: 5,
                        denominator: 3,
                    },
                    root: 2,
                },
            ),
        }
    "])
    .assert_debug_eq(&CartesianForm::recognize(0.0, -5.0 / 3.0 * 2.0_f64.sqrt()));
    expect!([r"
        CartesianForm {
            sign: -1,
            real_part: Algebraic(
                AlgebraicNumber {
                    sign: 1,
                    fraction: RationalNumber {
                        sign: 1,
                        numerator: 7,
                        denominator: 3,
                    },
                    root: 1,
                },
            ),
            imaginary_part: Algebraic(
                AlgebraicNumber {
                    sign: -1,
                    fraction: RationalNumber {
                        sign: 1,
                        numerator: 2,
                        denominator: 9,
                    },
                    root: 3,
                },
            ),
        }
    "])
    .assert_debug_eq(&CartesianForm::recognize(
        -7.0 / 3.0,
        2.0 / 9.0 * 3.0_f64.sqrt(),
    ));
}

#[test]
fn check_recognize_complex() {
    expect!([r"
        Cartesian(
            CartesianForm {
                sign: -1,
                real_part: Zero,
                imaginary_part: Algebraic(
                    AlgebraicNumber {
                        sign: 1,
                        fraction: RationalNumber {
                            sign: 1,
                            numerator: 5,
                            denominator: 3,
                        },
                        root: 2,
                    },
                ),
            },
        )
    "])
    .assert_debug_eq(&ComplexNumber::recognize(0.0, -5.0 / 3.0 * 2.0_f64.sqrt()));

    expect!([r"
        Cartesian(
            CartesianForm {
                sign: -1,
                real_part: Algebraic(
                    AlgebraicNumber {
                        sign: 1,
                        fraction: RationalNumber {
                            sign: 1,
                            numerator: 7,
                            denominator: 3,
                        },
                        root: 1,
                    },
                ),
                imaginary_part: Algebraic(
                    AlgebraicNumber {
                        sign: -1,
                        fraction: RationalNumber {
                            sign: 1,
                            numerator: 2,
                            denominator: 9,
                        },
                        root: 3,
                    },
                ),
            },
        )
    "])
    .assert_debug_eq(&ComplexNumber::recognize(
        -7.0 / 3.0,
        2.0 / 9.0 * 3.0_f64.sqrt(),
    ));

    expect!([r"
        Polar(
            PolarForm {
                sign: 1,
                magnitude: AlgebraicNumber {
                    sign: 1,
                    fraction: RationalNumber {
                        sign: 1,
                        numerator: 5,
                        denominator: 2,
                    },
                    root: 1,
                },
                phase_multiplier: RationalNumber {
                    sign: 1,
                    numerator: 1,
                    denominator: 3,
                },
            },
        )
    "])
    .assert_debug_eq(&ComplexNumber::recognize(
        5.0 / 2.0 * (PI / 3.0).cos(),
        5.0 / 2.0 * (PI / 3.0).sin(),
    ));
}

fn assert_latex_for_algebraic(
    expected: &Expect,
    numerator: i64,
    denominator: i64,
    root: i64,
    render_one: bool,
) {
    let number = AlgebraicNumber::new(&RationalNumber::new(numerator, denominator), root);
    let mut latex = String::with_capacity(50);
    write_latex_for_algebraic_number(&mut latex, &number, render_one);
    expected.assert_debug_eq(&latex);
}

#[test]
fn check_get_latex_for_algebraic() {
    assert_latex_for_algebraic(
        &expect!([r#"
            "\\frac{5 \\sqrt{2}}{3}"
        "#]),
        5,
        3,
        2,
        false,
    );
    assert_latex_for_algebraic(
        &expect!([r#"
            "\\frac{5 \\sqrt{2}}{3}"
        "#]),
        -5,
        3,
        2,
        false,
    );
    assert_latex_for_algebraic(
        &expect!([r#"
            "\\frac{\\sqrt{2}}{3}"
        "#]),
        1,
        3,
        2,
        false,
    );
    assert_latex_for_algebraic(
        &expect!([r#"
            "5 \\sqrt{2}"
        "#]),
        5,
        1,
        2,
        false,
    );
    assert_latex_for_algebraic(
        &expect!([r#"
            "\\frac{5}{3}"
        "#]),
        5,
        3,
        1,
        false,
    );
    assert_latex_for_algebraic(
        &expect!([r#"
            "\\sqrt{2}"
        "#]),
        1,
        1,
        2,
        false,
    );
    assert_latex_for_algebraic(
        &expect!([r#"
            "5"
        "#]),
        5,
        1,
        1,
        false,
    );
    assert_latex_for_algebraic(
        &expect!([r#"
            "\\frac{1}{3}"
        "#]),
        1,
        3,
        1,
        false,
    );
    assert_latex_for_algebraic(
        &expect!([r#"
            ""
        "#]),
        1,
        1,
        1,
        false,
    );
    assert_latex_for_algebraic(
        &expect!([r#"
            "1"
        "#]),
        1,
        1,
        1,
        true,
    );
}

fn assert_latex_for_decimal(expected: &Expect, number: f64, render_one: bool) {
    let number = DecimalNumber::new(number);
    let mut latex = String::with_capacity(50);
    write_latex_for_decimal_number(&mut latex, &number, render_one);
    expected.assert_debug_eq(&latex);
}

#[test]
fn check_get_latex_for_decimal() {
    assert_latex_for_decimal(
        &expect!([r#"
            "0.25"
        "#]),
        0.25,
        false,
    );
    assert_latex_for_decimal(
        &expect!([r#"
            "0.25"
        "#]),
        -0.25,
        false,
    );
    assert_latex_for_decimal(
        &expect!([r#"
            ""
        "#]),
        -1.0,
        false,
    );
    assert_latex_for_decimal(
        &expect!([r#"
            ""
        "#]),
        1.0,
        false,
    );
    assert_latex_for_decimal(
        &expect!([r#"
            "1"
        "#]),
        1.0,
        true,
    );
}

fn assert_latex_for_real(expected: &Expect, x: f64, render_one: bool) {
    let number = RealNumber::recognize(x);
    let mut latex = String::with_capacity(50);
    write_latex_for_real_number(&mut latex, &number, render_one);
    expected.assert_debug_eq(&latex);
}

#[test]
fn check_get_latex_for_real() {
    assert_latex_for_real(
        &expect!([r#"
        "\\frac{1}{4}"
    "#]),
        1.0 / 4.0,
        false,
    );
    assert_latex_for_real(
        &expect!([r#"
        "\\frac{1}{4}"
    "#]),
        -1.0 / 4.0,
        false,
    );
    assert_latex_for_real(
        &expect!([r#"
            ""
        "#]),
        1.0,
        false,
    );
    assert_latex_for_real(
        &expect!([r#"
            "1"
        "#]),
        1.0,
        true,
    );
    assert_latex_for_real(
        &expect!([r#"
            "0"
        "#]),
        0.0,
        false,
    );
    assert_latex_for_real(
        &expect!([r#"
            "0.00025"
        "#]),
        1.0 / 4000.0,
        false,
    );
}

fn assert_latex_for_cartesian(expected: &Expect, re: f64, im: f64, render_plus: bool) {
    let number = CartesianForm::recognize(re, im);
    let mut latex = String::with_capacity(50);
    write_latex_for_cartesian_form(&mut latex, &number, render_plus);
    expected.assert_debug_eq(&latex);
}

#[test]
fn check_get_latex_for_cartesian() {
    assert_latex_for_cartesian(
        &expect!([r#"
            "\\left( \\frac{1}{2}+\\frac{1}{2}i \\right)"
        "#]),
        0.5,
        0.5,
        false,
    );
    assert_latex_for_cartesian(
        &expect!([r#"
            "-\\left( \\frac{1}{2}-\\frac{1}{2}i \\right)"
        "#]),
        -0.5,
        0.5,
        false,
    );
    assert_latex_for_cartesian(
        &expect!([r#"
            "\\left( \\frac{1}{2}-\\frac{1}{2}i \\right)"
        "#]),
        0.5,
        -0.5,
        false,
    );
    assert_latex_for_cartesian(
        &expect!([r#"
            "-\\left( \\frac{1}{2}+\\frac{1}{2}i \\right)"
        "#]),
        -0.5,
        -0.5,
        false,
    );
    assert_latex_for_cartesian(
        &expect!([r#"
            "-\\frac{1}{2}i"
        "#]),
        0.0,
        -0.5,
        false,
    );
    assert_latex_for_cartesian(
        &expect!([r#"
            "-\\frac{1}{2}"
        "#]),
        -0.5,
        0.0,
        false,
    );
    assert_latex_for_cartesian(
        &expect!([r#"
            ""
        "#]),
        1.0,
        0.0,
        false,
    );
    assert_latex_for_cartesian(
        &expect!([r#"
            "+"
        "#]),
        1.0,
        0.0,
        true,
    );
}

fn assert_latex_for_polar(expected: &Expect, re: f64, im: f64, render_plus: bool) {
    let number = PolarForm::recognize(re, im).expect("Polar form not recognized.");
    let mut latex = String::with_capacity(50);
    write_latex_for_polar_form(&mut latex, &number, render_plus);
    expected.assert_debug_eq(&latex);
}

#[test]
fn check_get_latex_for_polar() {
    assert_latex_for_polar(
        &expect!([r#"
            "+\\frac{1}{2} e^{ i \\pi / 3}"
        "#]),
        1.0 / 2.0 * (PI / 3.0).cos(),
        1.0 / 2.0 * (PI / 3.0).sin(),
        true,
    );
    assert_latex_for_polar(
        &expect!([r#"
            "+ e^{ i \\pi / 3}"
        "#]),
        (PI / 3.0).cos(),
        (PI / 3.0).sin(),
        true,
    );
    assert_latex_for_polar(
        &expect!([r#"
            "+\\frac{1}{2} e^{- i \\pi / 3}"
        "#]),
        1.0 / 2.0 * (-PI / 3.0).cos(),
        1.0 / 2.0 * (-PI / 3.0).sin(),
        true,
    );
    assert_latex_for_polar(
        &expect!([r#"
            "+\\frac{1}{2} e^{2 i \\pi / 3}"
        "#]),
        1.0 / 2.0 * (2.0 * PI / 3.0).cos(),
        1.0 / 2.0 * (2.0 * PI / 3.0).sin(),
        true,
    );
    assert_latex_for_polar(
        &expect!([r#"
            "+\\frac{1}{2} e^{-2 i \\pi / 3}"
        "#]),
        1.0 / 2.0 * (-2.0 * PI / 3.0).cos(),
        1.0 / 2.0 * (-2.0 * PI / 3.0).sin(),
        true,
    );
    assert_latex_for_polar(
        &expect!([r#"
            "\\frac{1}{2} e^{-2 i \\pi / 3}"
        "#]),
        1.0 / 2.0 * (-2.0 * PI / 3.0).cos(),
        1.0 / 2.0 * (-2.0 * PI / 3.0).sin(),
        false,
    );
}

fn assert_latex_for_term(expected: &Expect, re: f64, im: f64, render_plus: bool) {
    let t: Term = Term {
        basis_vector: 0_u8.into(),
        coordinate: ComplexNumber::recognize(re, im),
    };
    let mut latex = String::with_capacity(50);
    write_latex_for_term(&mut latex, &t, render_plus);
    expected.assert_debug_eq(&latex);
}

#[test]
fn check_get_latex_for_term() {
    assert_latex_for_term(
        &expect!([r#"
            "+\\frac{1}{2} e^{ i \\pi / 3}"
        "#]),
        1.0 / 2.0 * (PI / 3.0).cos(),
        1.0 / 2.0 * (PI / 3.0).sin(),
        true,
    );
    assert_latex_for_term(
        &expect!([r#"
            "+\\left( \\frac{1}{2}+\\frac{1}{2}i \\right)"
        "#]),
        1.0 / 2.0,
        1.0 / 2.0,
        true,
    );
    assert_latex_for_term(
        &expect!([r#"
            "\\left( \\frac{1}{2}+\\frac{1}{2}i \\right)"
        "#]),
        1.0 / 2.0,
        1.0 / 2.0,
        false,
    );
    assert_latex_for_term(
        &expect!([r#"
            "-\\left( \\frac{1}{2}-\\frac{1}{2}i \\right)"
        "#]),
        -1.0 / 2.0,
        1.0 / 2.0,
        true,
    );
    assert_latex_for_term(
        &expect!([r#"
            "-\\left( \\frac{1}{2}-\\frac{1}{2}i \\right)"
        "#]),
        -1.0 / 2.0,
        1.0 / 2.0,
        false,
    );
}

#[test]
fn check_get_latex() {
    expect!([r#"
        "$|\\psi\\rangle = \\left( \\frac{1}{2}+\\frac{1}{2}i \\right)|00\\rangle$"
    "#])
    .assert_debug_eq(&get_latex(
        &vec![(0_u8.into(), Complex64::new(0.5, 0.5))],
        2,
    ));
    expect!([r#"
        "$|\\psi\\rangle = -|00\\rangle$"
    "#])
    .assert_debug_eq(&get_latex(
        &vec![(0_u8.into(), Complex64::new(-1.0, 0.0))],
        2,
    ));
    expect!([r#"
        "$|\\psi\\rangle = -i|00\\rangle$"
    "#])
    .assert_debug_eq(&get_latex(
        &vec![(0_u8.into(), Complex64::new(0.0, -1.0))],
        2,
    ));
    expect!([r#"
        "$|\\psi\\rangle =  e^{-2 i \\pi / 3}|00\\rangle$"
    "#])
    .assert_debug_eq(&get_latex(
        &vec![(
            0_u8.into(),
            Complex64::new((-2.0 * PI / 3.0).cos(), (-2.0 * PI / 3.0).sin()),
        )],
        2,
    ));
    expect!([r#"
        "$|\\psi\\rangle = \\left( 1+\\frac{\\sqrt{2}}{2}i \\right)|00\\rangle+\\left( 1+\\frac{\\sqrt{2}}{2}i \\right)|10\\rangle$"
    "#])
    .assert_debug_eq(&get_latex(
        &vec![
            (0_u8.into(), Complex64::new(1.0, 1.0 / 2.0_f64.sqrt())),
            (2_u8.into(), Complex64::new(1.0, 1.0 / 2.0_f64.sqrt())),
        ],
        2,
    ));
}

#[test]
fn check_get_latex_perf() {
    // This is not a CI gate for performance, just prints out data.
    let state = vec![
        (0_u8.into(), Complex64::new(1.0 / 2.0, 0.0)),
        (
            1_u8.into(),
            Complex64::new(0.353_553_390_593_273_8, 0.353_553_390_593_273_8),
        ),
        (2_u8.into(), Complex64::new(0.0, 1.0 / 2.0)),
        (
            3_u8.into(),
            Complex64::new(-0.353_553_390_593_273_8, 0.353_553_390_593_273_8),
        ),
    ];

    expect!([r#"
        "$|\\psi\\rangle = \\frac{1}{2}|00\\rangle+\\frac{1}{2} e^{ i \\pi / 4}|01\\rangle+\\frac{1}{2}i|10\\rangle+\\frac{1}{2} e^{3 i \\pi / 4}|11\\rangle$"
    "#])
    .assert_debug_eq(&get_latex(
        &state,
        2,
    ));

    print!("Start...");
    let start = Instant::now();
    let mut l: usize = 0;
    for _ in 0..1_000 {
        let s = get_latex(&state, 2);
        l += s.len();
    }
    println!(
        "Done. {} bytes in {:?}.",
        l,
        Instant::now().duration_since(start)
    );
}
