use core::ops::{Add, Div, Mul, Rem, Sub};
pub fn fibbonacci<T>(n: T) -> T
where
T: From<u8>
+ Add<Output = T>
+ Sub<Output = T>
+ Mul<Output = T>
+ Div<Output = T>
+ Rem<Output = T>
+ PartialEq
+ Copy,
{
fn __fib<T>(n: T) -> (T, T)
where
T: From<u8>
+ Add<Output = T>
+ Sub<Output = T>
+ Mul<Output = T>
+ Div<Output = T>
+ Rem<Output = T>
+ PartialEq
+ Copy,
{
if n == T::from(0) {
(T::from(0), T::from(1))
} else {
let (a, b) = __fib(n / T::from(2));
let c = a * ((b * T::from(2)) - a);
let d = a * a + b * b;
if n % T::from(2) == T::from(0) {
(c, d)
} else {
(d, c + d)
}
}
}
__fib(n).0
}
pub fn fibbonacci_range<T, U>(range: T) -> Vec<U>
where
T: IntoIterator<Item = U>,
U: From<u8>
+ Add<Output = U>
+ Sub<Output = U>
+ Mul<Output = U>
+ Div<Output = U>
+ Rem<Output = U>
+ PartialEq
+ Copy,
{
let mut result = Vec::new();
for i in range {
result.push(fibbonacci(i));
}
result
}
#[cfg(test)]
mod tests {
use super::fibbonacci;
#[test]
fn calc_1() {
let result = fibbonacci(2);
assert_eq!(result, 1);
}
#[test]
fn calc_2() {
let result = fibbonacci(20);
assert_eq!(result, 6765);
}
#[test]
fn calc_3() {
let result = fibbonacci(30);
assert_eq!(result, 832040);
}
#[test]
fn calc_4() {
let result = fibbonacci::<u128>(100);
assert_eq!(result, 354224848179261915075);
}
}