 extension CoreGraphics.CGSize: Interpolatable {
 
     public static func interpolate(with ease: Ease,
-                                   startValue: InterpolationValue,
-                                   endValue: InterpolationValue,
+                                   startValue: CoreGraphics.CGSize, endValue: CoreGraphics.CGSize,
                                    elapsed: Foundation.TimeInterval,
-                                   duration: Foundation.TimeInterval) throws -> InterpolationValue {
-
-        guard let _startValue = startValue as? CoreGraphics.CGSize else {
-            throw InterpolationError.valueNotConvertible(value: startValue, to: CoreGraphics.CGSize.self)
-        }
-
-        guard let _endValue = endValue as? CoreGraphics.CGSize else {
-            throw InterpolationError.valueNotConvertible(value: endValue, to: CoreGraphics.CGSize.self)
-        }
+                                   duration: Foundation.TimeInterval) -> CoreGraphics.CGSize {
 
         let interpolate: (CoreGraphics.CGFloat, CoreGraphics.CGFloat) -> CoreGraphics.CGFloat = { (start, end) in
             return ease.interpolate(startValue: start, endValue: end, elapsed: elapsed, duration: duration)
         }
 
-        let width = interpolate(_startValue.width, _endValue.width)
-        let height = interpolate(_startValue.height, _endValue.height)
+        let width = interpolate(startValue.width, endValue.width)
+        let height = interpolate(startValue.height, endValue.height)
 
         return CoreGraphics.CGSize(width: width, height: height)
     }
+
 }
 
 extension CoreGraphics.CGRect: Interpolatable {
 
     public static func interpolate(with ease: Ease,
-                                   startValue: InterpolationValue,
-                                   endValue: InterpolationValue,
+                                   startValue: CoreGraphics.CGRect, endValue: CoreGraphics.CGRect,
                                    elapsed: Foundation.TimeInterval,
-                                   duration: Foundation.TimeInterval) throws -> InterpolationValue {
-
-        guard let _startValue = startValue as? CoreGraphics.CGRect else {
-            throw InterpolationError.valueNotConvertible(value: startValue, to: CoreGraphics.CGRect.self)
-        }
-
-        guard let _endValue = endValue as? CoreGraphics.CGRect else {
-            throw InterpolationError.valueNotConvertible(value: endValue, to: CoreGraphics.CGRect.self)
-        }
+                                   duration: Foundation.TimeInterval) -> CoreGraphics.CGRect {
 
         let interpolate: (CoreGraphics.CGFloat, CoreGraphics.CGFloat) -> CoreGraphics.CGFloat = { (start, end) in
             return ease.interpolate(startValue: start, endValue: end, elapsed: elapsed, duration: duration)
         }
 
-        let x = interpolate(_startValue.origin.x, _endValue.origin.x)
-        let y = interpolate(_startValue.origin.y, _endValue.origin.y)
-        let width = interpolate(_startValue.size.width, _endValue.size.width)
-        let height = interpolate(_startValue.size.height, _endValue.size.height)
-
+        let x = interpolate(startValue.origin.x, endValue.origin.x)
+        let y = interpolate(startValue.origin.y, endValue.origin.y)
+        let width = interpolate(startValue.size.width, endValue.size.width)
+        let height = interpolate(startValue.size.height, endValue.size.height)
+        
         return CoreGraphics.CGRect(x: x, y: y, width: width, height: height)
     }
-
+    
 }


extension Swift.UInt: Interpolatable {

}

extension Swift.Int: Interpolatable {

}

extension Swift.Double: Interpolatable {

}

extension Swift.Float: Interpolatable {

}

extension CoreGraphics.CGFloat: Interpolatable {

}

extension CoreGraphics.CGPoint: Interpolatable {

    public static func interpolate(with ease: Ease,
                                   startValue: InterpolationValue,
                                   endValue: InterpolationValue,
                                   elapsed: Foundation.TimeInterval,
                                   duration: Foundation.TimeInterval) throws -> InterpolationValue {

        guard let _startValue = startValue as? CoreGraphics.CGPoint else {
            throw InterpolationError.valueNotConvertible(value: startValue, to: CoreGraphics.CGPoint.self)
        }

        guard let _endValue = endValue as? CoreGraphics.CGPoint else {
            throw InterpolationError.valueNotConvertible(value: endValue, to: CoreGraphics.CGPoint.self)
        }

        let interpolate: (CoreGraphics.CGFloat, CoreGraphics.CGFloat) -> CoreGraphics.CGFloat = { (start, end) in
            return ease.interpolate(startValue: start, endValue: end, elapsed: elapsed, duration: duration)
        }

        let x = interpolate(_startValue.x, _endValue.x)
        let y = interpolate(_startValue.y, _endValue.y)

        return CoreGraphics.CGPoint(x: x, y: y)
    }

public protocol Interpolatable {

    /**
     A class method to calculate the value between a start and end value at a
     specific point in time.

     - Parameters:
        - ease: The `Ease` used to interpolate values.
        - startValue: The start value passed to the `ease` algorithm.
        - endValue: The end value passed to the `ease` algorithm.
        - elapsed: The elapsed amount of time passed to the `ease` algorithm.
        - duration: The duration of time passed to the `ease` algorithm.

     - Returns: The value interpolated between the start and end value.
     */
    static func interpolate(with ease: Ease,
                            startValue: Self, endValue: Self,
                            elapsed: Foundation.TimeInterval,
                            duration: Foundation.TimeInterval) -> Self


    /**
     A class method to calculate the value between a set of values at a
     specific point in time.

     - Parameters:
        - ease: The `Ease` used to interpolate values.
        - values: The start and end value passed to the `ease` algorithm.
        - elapsed: The elapsed amount of time passed to the `ease` algorithm.
        - duration: The duration of time passed to the `ease` algorithm.

     - Returns: The value interpolated between `values.start` and `values.end`.
     */
    static func interpolate(with ease: Ease,
                            values: InterpolationValues<Self>,
                            elapsed: Foundation.TimeInterval,
                            duration: Foundation.TimeInterval) -> Self

}

// MARK: - Default Implementation

extension Interpolatable {

    public static func interpolate(with ease: Ease,
                                   values: InterpolationValues<Self>,
                                   elapsed: Foundation.TimeInterval,
                                   duration: Foundation.TimeInterval) -> Self {

        return Self.interpolate(with: ease, startValue: values.start, endValue: values.end,
                                elapsed: elapsed, duration: duration)
    }

}
