polylog 2.6.0

Rust implementation of polylogarithms.
Documentation
use num::complex::Complex;
use std::fmt::Debug;
use std::fs::File;
use std::io::{BufReader, BufRead, Error, ErrorKind};
use std::path::PathBuf;
use std::str::FromStr;


#[macro_export]
macro_rules! assert_eq_float {
    ($a:expr, $b:expr, $eps:expr) => {
        if ($a - $b).abs() >= $eps*(1.0 + $a.abs().max($b.abs())) {
            println!("Numbers differ by more than {}: {} != {}", $eps, $a, $b);
            assert!(false);
        }
    }
}


#[macro_export]
macro_rules! assert_eq_complex {
    ($a:expr, $b:expr, $eps:expr) => {
        assert_eq_float!($a.re, $b.re, $eps);
        assert_eq_float!($a.im, $b.im, $eps);
    }
}


pub trait CLn<T> {
    fn cln(&self) -> T;
}


impl CLn<Complex<f64>> for Complex<f64> {
    fn cln(&self) -> Complex<f64> {
        Complex::new(
            if self.re == 0. { 0. } else { self.re },
            if self.im == 0. { 0. } else { self.im },
        ).ln()
    }
}


fn data_path(filename: &str) -> PathBuf {
    let mut path = PathBuf::from(file!());
    path.pop();
    path.pop();
    path.pop();
    path.push("tests");
    path.push("data");
    path.push(filename);
    path
}


pub fn read_data_file<T: Copy + FromStr>(filename: &str) -> Result<Vec<(Complex<T>, Complex<T>)>, Error> where <T as FromStr>::Err: Debug {
    let file = File::open(data_path(filename))?;
    let br = BufReader::new(file);
    let mut vec = Vec::new();

    for line in br.lines() {
        let vals = line?
            .split_whitespace()
            .map(|s| s.parse::<T>().unwrap())
            .collect::<Vec<T>>();

        if vals.len() != 4 {
            return Err(Error::new(ErrorKind::UnexpectedEof, "line does not contain 4 real numbers"));
        }

        vec.push((Complex::new(vals[0], vals[1]), Complex::new(vals[2], vals[3])));
    }

    Ok(vec)
}