Skip to content

Commit 06910a5

Browse files
authored
Merge pull request #8 from alexheretic/master
Add generic f64 support
2 parents 6b668e4 + 3d258dc commit 06910a5

18 files changed

+523
-310
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ language: rust
33
addons:
44
apt:
55
packages:
6-
- libcurl14-openssl-dev
6+
- libcurl4-openssl-dev
77
- libelf-dev
88
- libdw-dev
99
- binutils-dev

Cargo.toml

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "easer"
3-
version = "0.1.1"
3+
version = "0.2.0"
44
authors = ["Orhan Balci <[email protected]>"]
55
description="Tiny library imlementing Robert Penner's easing functions"
66
documentation="http://orhanbalci.github.io/rust-easing"
@@ -10,11 +10,13 @@ keywords=["easing","animation","tween"]
1010
license="MIT"
1111
exclude=[".travis.yml"]
1212

13+
[dependencies]
14+
num-traits="0.1"
15+
1316
[dev-dependencies]
14-
approx="0.1.0"
15-
gnuplot="0.0.20"
17+
approx="0.1"
18+
gnuplot="0.0"
1619

1720
[[example]]
1821
name="easer_plotter"
1922
path="examples/easer_plotter.rs"
20-

examples/easer_plotter.rs

+24-67
Original file line numberDiff line numberDiff line change
@@ -3,71 +3,28 @@ extern crate easer;
33

44
use gnuplot::{Figure, Caption, Color, AxesCommon};
55
use easer::functions::*;
6+
use std::fmt::Debug;
67

78
fn main() {
89
let mut fg = Figure::new();
9-
plot_easing_function(&mut fg, Back::ease_in, Back::ease_out, Back::ease_in_out, 0);
10-
plot_easing_function(&mut fg,
11-
Bounce::ease_in,
12-
Bounce::ease_out,
13-
Bounce::ease_in_out,
14-
3);
15-
plot_easing_function(&mut fg, Circ::ease_in, Circ::ease_out, Circ::ease_in_out, 6);
16-
// plot_easing_function(&mut fg,
17-
// Cubic::ease_in,
18-
// Cubic::ease_out,
19-
// Cubic::ease_in_out,
20-
// 9);
21-
// plot_easing_function(&mut fg,
22-
// Elastic::ease_in,
23-
// Elastic::ease_out,
24-
// Elastic::ease_in_out,
25-
// 12);
26-
// plot_easing_function(&mut fg,
27-
// Expo::ease_in,
28-
// Expo::ease_out,
29-
// Expo::ease_in_out,
30-
// 15);
31-
// plot_easing_function(&mut fg,
32-
// Linear::ease_in,
33-
// Linear::ease_out,
34-
// Linear::ease_in_out,
35-
// 18);
36-
// plot_easing_function(&mut fg,
37-
// Quad::ease_in,
38-
// Quad::ease_out,
39-
// Quad::ease_in_out,
40-
// 21);
41-
// plot_easing_function(&mut fg,
42-
// Quart::ease_in,
43-
// Quart::ease_out,
44-
// Quart::ease_in_out,
45-
// 24);
46-
// plot_easing_function(&mut fg,
47-
// Quint::ease_in,
48-
// Quint::ease_out,
49-
// Quint::ease_in_out,
50-
// 27);
51-
// plot_easing_function(&mut fg,
52-
// Sine::ease_in,
53-
// Sine::ease_out,
54-
// Sine::ease_in_out,
55-
// 30);
10+
const ROWS: u32 = 3;
11+
12+
plot_easing(Back, &mut fg, 0, ROWS);
13+
plot_easing(Bounce, &mut fg, 1, ROWS);
14+
plot_easing(Circ, &mut fg, 2, ROWS);
15+
// plot_easing(Cubic, &mut fg, 3, ROWS);
16+
// plot_easing(Elastic, &mut fg, 4, ROWS);
17+
// plot_easing(Expo, &mut fg, 5, ROWS);
18+
// plot_easing(Linear, &mut fg, 6, ROWS);
19+
// plot_easing(Quad, &mut fg, 7, ROWS);
20+
// plot_easing(Quart, &mut fg, 8, ROWS);
21+
// plot_easing(Quint, &mut fg, 9, ROWS);
22+
// plot_easing(Sine, &mut fg, 10, ROWS);
5623

5724
fg.show();
58-
// rintln!("Hello, world!");
5925
}
6026

61-
fn plot_easing_function<F1, F2, F3>(fg: &mut Figure,
62-
fun_ease_in: F1,
63-
fun_ease_out: F2,
64-
fun_ease_in_out: F3,
65-
cell: u32)
66-
where F1: Fn(f32, f32, f32, f32) -> f32,
67-
F2: Fn(f32, f32, f32, f32) -> f32,
68-
F3: Fn(f32, f32, f32, f32) -> f32
69-
{
70-
27+
fn plot_easing<E: Easing<f32> + Debug>(easing: E, fg: &mut Figure, row_idx: u32, nrows: u32) {
7128
let mut x: [f32; 100] = [0.0; 100];
7229
let mut y: [f32; 100] = [0.0; 100];
7330
for i in 0..100 {
@@ -76,33 +33,33 @@ fn plot_easing_function<F1, F2, F3>(fg: &mut Figure,
7633
}
7734

7835
let back = y.iter()
79-
.map(|a| fun_ease_in(*a, 0f32, 100f32, 100f32))
36+
.map(|a| E::ease_in(*a, 0f32, 100f32, 100f32))
8037
.collect::<Vec<f32>>();
8138

8239
fg.axes2d()
8340
.lines(&x[..], &back, &[Caption("In Line"), Color("blue")])
84-
.set_title("Back Ease In", &[])
85-
.set_pos_grid(3, 3, cell);
41+
.set_title(&format!("{:?} Ease In", easing), &[])
42+
.set_pos_grid(nrows, 3, row_idx * 3);
8643
let back_ease_out = y.iter()
87-
.map(|a| fun_ease_out(*a, 0f32, 100f32, 100f32))
44+
.map(|a| E::ease_out(*a, 0f32, 100f32, 100f32))
8845
.collect::<Vec<f32>>();
8946

9047
fg.axes2d()
9148
.lines(&x[..],
9249
&back_ease_out,
9350
&[Caption("Out Line"), Color("blue")])
94-
.set_title("Back Ease Out", &[])
95-
.set_pos_grid(3, 3, cell + 1);
51+
.set_title(&format!("{:?} Ease Out", easing), &[])
52+
.set_pos_grid(nrows, 3, row_idx * 3 + 1);
9653

9754
let back_ease_in_out = y.iter()
98-
.map(|a| fun_ease_in_out(*a, 0f32, 100f32, 100f32))
55+
.map(|a| E::ease_in_out(*a, 0f32, 100f32, 100f32))
9956
.collect::<Vec<f32>>();
10057

10158
fg.axes2d()
10259
.lines(&x[..],
10360
&back_ease_in_out,
10461
&[Caption("In Out Line"), Color("blue")])
105-
.set_title("Back Ease In Out", &[])
106-
.set_pos_grid(3, 3, cell + 2);
62+
.set_title(&format!("{:?} Ease In Out", easing), &[])
63+
.set_pos_grid(nrows, 3, row_idx * 3 + 2);
10764

10865
}

src/functions/back.rs

+40-23
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,70 @@
11
use super::ease::Easing;
2+
use functions::util::*;
23

34
/// This struct captures Back easing functions
5+
#[derive(Debug)]
46
pub struct Back;
57

6-
impl Easing for Back {
7-
fn ease_in(t: f32, b: f32, c: f32, d: f32) -> f32 {
8-
let s = 1.70158_f32;
8+
impl<F: Float> Easing<F> for Back {
9+
fn ease_in(t: F, b: F, c: F, d: F) -> F {
10+
let s: F = f(1.70158);
911
let t = t / d;
10-
c * t * t * ((s + 1.0) * t - s) + b
12+
c * t * t * ((s + f(1.0)) * t - s) + b
1113
}
1214

13-
fn ease_out(t: f32, b: f32, c: f32, d: f32) -> f32 {
14-
let s = 1.70158_f32;
15-
let t = (t / d) - 1.0;
16-
c * (t * t * ((s + 1.0) * t + s) + 1.0) + b
15+
fn ease_out(t: F, b: F, c: F, d: F) -> F {
16+
let s: F = f(1.70158);
17+
let t = (t / d) - f(1.0);
18+
c * (t * t * ((s + f(1.0)) * t + s) + f(1.0)) + b
1719
}
1820

19-
fn ease_in_out(t: f32, b: f32, c: f32, d: f32) -> f32 {
20-
let s = 1.70158_f32;
21-
let t = t / (d / 2.0);
22-
if t < 1.0 {
23-
let s = s * 1.525f32;
24-
c / 2.0 * (t * t * ((s + 1.0) * t - s)) + b
21+
fn ease_in_out(t: F, b: F, c: F, d: F) -> F {
22+
let s: F = f(1.70158);
23+
let t = t / (d / f(2.0));
24+
if t < f(1.0) {
25+
let s = s * f(1.525);
26+
c / f(2.0) * (t * t * ((s + f(1.0)) * t - s)) + b
2527
}
2628
else {
27-
let t = t - 2.0;
28-
let s = s * 1.525f32;
29-
c / 2.0 * (t * t * ((s + 1.0) * t + s) + 2.0) + b
29+
let t = t - f(2.0);
30+
let s = s * f(1.525);
31+
c / f(2.0) * (t * t * ((s + f(1.0)) * t + s) + f(2.0)) + b
3032
}
3133
}
3234
}
3335

3436
#[cfg(test)]
3537
mod test {
36-
#[allow(unused_imports)]
37-
use functions::ease::Easing;
38+
use super::*;
39+
3840
#[test]
3941
fn ease_in() {
40-
assert_relative_eq!(super::Back::ease_in(1.0, 2.0, 3.0, 4.0), 1.8075902);
42+
assert_relative_eq!(Back::ease_in(1.0_f32, 2.0, 3.0, 4.0), 1.8075902);
4143
}
4244

4345
#[test]
4446
fn ease_out() {
45-
assert_relative_eq!(super::Back::ease_out(1.0, 2.0, 3.0, 4.0), 4.452229);
47+
assert_relative_eq!(Back::ease_out(1.0_f32, 2.0, 3.0, 4.0), 4.452229);
4648
}
4749

4850
#[test]
4951
fn ease_in_out() {
50-
assert_relative_eq!(super::Back::ease_in_out(1.0, 2.0, 3.0, 4.0), 1.7009544);
51-
assert_relative_eq!(super::Back::ease_in_out(51.0, 1.0, 100.0, 100.0), 56.432546);
52+
assert_relative_eq!(Back::ease_in_out(1.0_f32, 2.0, 3.0, 4.0), 1.7009544);
53+
assert_relative_eq!(Back::ease_in_out(51.0_f32, 1.0, 100.0, 100.0), 56.432546);
54+
}
55+
56+
const PRECISE_RESULT: f64 = 1.7458203824347307;
57+
58+
#[test]
59+
fn f32_precision() {
60+
let ease32 = Back::ease_in(10_f32.sqrt(), 2.0, 3.0, 10.0);
61+
assert_relative_ne!(ease32 as f64, PRECISE_RESULT); // f32 maths is actually happening
62+
assert_relative_eq!(ease32, PRECISE_RESULT as f32);
63+
}
64+
65+
#[test]
66+
fn f64_precision() {
67+
let ease64 = Back::ease_in(10_f64.sqrt(), 2.0, 3.0, 10.0);
68+
assert_relative_eq!(ease64, PRECISE_RESULT);
5269
}
5370
}

src/functions/bounce.rs

+46-28
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,78 @@
11
use super::ease::Easing;
2+
use functions::util::*;
23

34
/// This struct captures Bounce easing functions
5+
#[derive(Debug)]
46
pub struct Bounce;
57

6-
impl Easing for Bounce {
7-
fn ease_in(t: f32, b: f32, c: f32, d: f32) -> f32 {
8-
c - Bounce::ease_out(d - t, 0.0, c, d) + b
8+
impl<F: Float> Easing<F> for Bounce {
9+
fn ease_in(t: F, b: F, c: F, d: F) -> F {
10+
c - Bounce::ease_out(d - t, f(0.0), c, d) + b
911
}
1012

11-
fn ease_out(t: f32, b: f32, c: f32, d: f32) -> f32 {
13+
fn ease_out(t: F, b: F, c: F, d: F) -> F {
14+
cast_constants!(F; _1=1, _1_5=1.5, _2=2, _2_25=2.25, _2_5=2.5,
15+
_2_625=2.625, _7_5625=7.5625);
16+
1217
let t = t / d;
13-
if t < 1.0 / 2.75 {
14-
c * (7.5625 * t * t) + b
15-
} else if t < 2.0 / 2.75 {
16-
let t = t - 1.5 / 2.75;
17-
c * (7.5625 * t * t + 0.75) + b
18-
} else if t < 2.5 / 2.75 {
19-
let t = t - 2.25 / 2.75;
20-
c * (7.5625 * t * t + 0.9375) + b
18+
if t < _1 / f(2.75) {
19+
c * (_7_5625 * t * t) + b
20+
} else if t < _2 / f(2.75) {
21+
let t = t - _1_5 / f(2.75);
22+
c * (_7_5625 * t * t + f(0.75)) + b
23+
} else if t < _2_5 / f(2.75) {
24+
let t = t - _2_25 / f(2.75);
25+
c * (_7_5625 * t * t + f(0.9375)) + b
2126
} else {
22-
let t = t - 2.625 / 2.75;
23-
c * (7.5625 * t * t + 0.984375) + b
27+
let t = t - _2_625 / f(2.75);
28+
c * (_7_5625 * t * t + f(0.984375)) + b
2429
}
2530
}
2631

27-
fn ease_in_out(t: f32, b: f32, c: f32, d: f32) -> f32 {
28-
if t < (d / 2.0) {
29-
Bounce::ease_in(t * 2.0, 0.0, c, d) * 0.5 + b
32+
fn ease_in_out(t: F, b: F, c: F, d: F) -> F {
33+
if t < (d / f(2.0)) {
34+
Bounce::ease_in(t * f(2.0), f(0.0), c, d) * f(0.5) + b
3035
} else {
31-
Bounce::ease_out(t * 2.0 - d, 0.0, c, d) * 0.5 + c * 0.5 + b
36+
Bounce::ease_out(t * f(2.0) - d, f(0.0), c, d) * f(0.5) + c * f(0.5) + b
3237
}
3338

3439
}
3540
}
3641

3742
#[cfg(test)]
3843
mod test {
39-
#[allow(unused_imports)]
40-
use functions::ease::Easing;
44+
use super::*;
45+
4146
#[test]
4247
fn ease_out() {
43-
assert_relative_eq!(super::Bounce::ease_out(1.0, 2.0, 3.0, 4.0), 3.4179688);
44-
assert_relative_eq!(super::Bounce::ease_out(1.0, 2.0, 3.0, 2.0), 4.296875);
45-
assert_relative_eq!(super::Bounce::ease_out(100.0, 1.0, 100.0, 100.0),
46-
101.000000);
48+
assert_relative_eq!(Bounce::ease_out(1.0_f32, 2.0, 3.0, 4.0), 3.4179688);
49+
assert_relative_eq!(Bounce::ease_out(1.0_f32, 2.0, 3.0, 2.0), 4.296875);
50+
assert_relative_eq!(Bounce::ease_out(100.0_f32, 1.0, 100.0, 100.0), 101.000000);
4751
}
4852

4953
#[test]
5054
fn ease_in() {
51-
assert_relative_eq!(super::Bounce::ease_in(1.0, 2.0, 3.0, 4.0), 2.082031);
55+
assert_relative_eq!(Bounce::ease_in(1.0_f32, 2.0, 3.0, 4.0), 2.082031);
5256
}
5357

5458
#[test]
5559
fn ease_in_out() {
56-
assert_relative_eq!(super::Bounce::ease_in_out(1.0, 2.0, 3.0, 4.0), 2.3515625);
57-
assert_relative_eq!(super::Bounce::ease_in_out(51.0, 1.0, 100.0, 100.0),
58-
51.151250);
60+
assert_relative_eq!(Bounce::ease_in_out(1.0_f32, 2.0, 3.0, 4.0), 2.3515625);
61+
assert_relative_eq!(Bounce::ease_in_out(51.0_f32, 1.0, 100.0, 100.0), 51.151250);
62+
}
63+
64+
const PRECISE_RESULT: f64 = 2.3159476740972824;
65+
66+
#[test]
67+
fn f32_precision() {
68+
let ease32 = Bounce::ease_in(10_f32.sqrt(), 2.0, 3.0, 10.0);
69+
assert_relative_ne!(ease32 as f64, PRECISE_RESULT); // f32 maths is actually happening
70+
assert_relative_eq!(ease32, PRECISE_RESULT as f32);
71+
}
72+
73+
#[test]
74+
fn f64_precision() {
75+
let ease64 = Bounce::ease_in(10_f64.sqrt(), 2.0, 3.0, 10.0);
76+
assert_relative_eq!(ease64, PRECISE_RESULT);
5977
}
6078
}

0 commit comments

Comments
 (0)