/* Appellation: macros Contrib: FL03 */ #![allow(unused_variables)] #![feature(fn_traits, tuple_trait, unboxed_closures)] #![cfg(all(test, feature = "macros"))] extern crate acme; use acme::prelude::autodiff; use utils::*; #[test] #[ignore = "Custom function calls are not yet supported"] fn test_func_handler() { let (x, y) = (1_f64, 2_f64); assert_eq!(autodiff!(x: Sample(x)), 2.0 * x); // assert_eq!(autodiff!(x: Sample::mul_item), y); } #[test] #[ignore = "Custom function calls are not yet supported"] fn test_function_call() { let (x, y) = (1_f64, 2_f64); // differentiating a function call w.r.t. x assert_eq!(autodiff!(x: add(x, y)), 1.0); // differentiating a function call w.r.t. some variable assert_eq!(autodiff!(a: add(x, y)), 0.0); assert_eq!(autodiff!(y: sigmoid::(y)), sigmoid_prime(y)); } #[test] #[ignore = "Custom trait methods are not yet supported"] fn test_method() { let (x, y) = (1_f64, 2_f64); // assert_eq!(autodiff!(x: x.sigmoid()), sigmoid_prime(x)); } #[allow(unused)] mod utils { use core::ops::Mul; use num::traits::{Float, Pow}; use std::ops::FnOnce; pub fn sigmoid(x: T) -> T where T: Float, { (T::one() + x.neg().exp()).recip() } pub trait Sigmoid { fn sigmoid(self) -> Self; } impl Sigmoid for T where T: Float, { fn sigmoid(self) -> Self { (T::one() + self.neg().exp()).recip() } } pub fn add(a: A, b: B) -> C where A: std::ops::Add, { a + b } pub fn sigmoid_prime(x: T) -> T where T: Float, { x.neg().exp() / (T::one() + x.neg().exp()).powi(2) } trait Square { fn square(self) -> Self; } impl Square for T where T: Pow, { fn square(self) -> Self { self.pow(2) } } pub struct Sample; impl Sample { pub fn sqr(x: T) -> T where T: Copy + Mul, { x * x } pub fn item_fn(&self) -> fn(T) -> T where T: Copy + Mul, { Self::sqr } } impl FnOnce<(T,)> for Sample where T: Copy + Mul, { type Output = T; extern "rust-call" fn call_once(self, args: (T,)) -> Self::Output { Self::sqr(args.0) } } }