 
 
 import CoreGraphics
+import simd
 
 // MARK: Initializers
 public extension CGRect {
     /// Creates a rectangle with the specified size.
-    @inlinable
-    init(size: CGSize) {
+    @inlinable init(size: CGSize) {
         self.init(origin: .zero, size: size)
     }
     
     /// Creates a rectangle with the specified center and size.
-    @inlinable
-    init(center: CGPoint, size: CGSize) {
-        let r = CGRect(origin: .zero, size: size)
-        self = r.centered(at: center)
-    }
-
-    @inlinable
-    init(ratio: Ratio, maxSize: CGFloat) {
+    @inlinable init(center: CGPoint, size: CGSize) {
+        let origin = CGPoint(simd2: center.simd2 - (size.simd2 / 2))
+        self.init(origin: origin, size: size)
+    }
+
+    @inlinable init(ratio: Ratio, maxSize: CGFloat) {
         let width: CGFloat, height: CGFloat
         switch ratio.orientation {
         case .landscape:

public extension CGRect {

    /// Returns a copy of `self` centered relative to the given rectangle.
    @inlinable
    func centered(in rect: CGRect) -> CGRect {
        guard !self.isEmpty && !self.isInfinite else { return self }
        let rectCenter = rect.center
        let origin = CGPoint(x: rectCenter.x - self.width / 2.0, y: rectCenter.y - self.height / 2.0)
        return CGRect(origin: origin, size: self.size)
    }

    /// Centers `self` relative to the given rect.
    @inlinable
    mutating func center(in rect: CGRect) {
        self = self.centered(in: rect)
    }

    /// Returns a copy of `self` centered to the given point.
    @inlinable
    func centered(at point: CGPoint) -> CGRect {
        guard !self.isEmpty && !self.isInfinite else { return self }
        let origin = CGPoint(x: point.x - self.width / 2.0, y: point.y - self.height / 2.0)
        return CGRect(origin: origin, size: self.size)
    }
    
    /// Returns a copy of `self` centered at `(x,y)`.
    @inlinable
    func centered<I: BinaryInteger>(atX x: I, y: I) -> CGRect {
        self.centered(atX: CGFloat(x), y: CGFloat(y))
    }
    
    /// Returns a copy of `self` centered at `(x,y)`.
    @inlinable
    func centered<F: BinaryFloatingPoint>(atX x: F, y: F) -> CGRect {
        self.centered(atX: CGFloat(x), y: CGFloat(y))
    }
    
    /// Returns a copy of `self` centered at `(x,y)`.
    @inlinable
    func centered(atX x: CGFloat, y: CGFloat) -> CGRect {
        let center = CGPoint(x: x, y: y)
        return self.centered(at: center)
    }
    
    /// Centers `self` relative to the given point.
    @inlinable
    mutating func center(at point: CGPoint) {
        self = self.centered(at: point)
    }

    /// Centers `self` at `(x,y)`
    @inlinable
    mutating func center<I: BinaryInteger>(atX x: I, y: I) {
        self = self.centered(atX: x, y: y)
    }
    
    /// Centers `self` at `(x,y)`
    @inlinable
    mutating func center<F: BinaryFloatingPoint>(atX x: F, y: F) {
        self = self.centered(atX: x, y: y)
    }
    
    /// Centers `self` at `(x,y)`
    @inlinable
    mutating func center(atX x: CGFloat, y: CGFloat) {
        self = self.centered(atX: x, y: y)
    }
}


public extension CGRect {
    
    /// The biggest square rectangle that `self` can contain.
    @inlinable var maxSquare: CGRect {
        let maxEdge = max(self.width, self.height)
        return CGRect(origin: .zero, size: .init(width: maxEdge, height: maxEdge))
    }
    
    /// The smallest square rectangle that can contain `self`.
    @inlinable var minSquare: CGRect {
        let minEdge = min(self.width, self.height)
        return CGRect(origin: .zero, size: .init(width: minEdge, height: minEdge))
    }
    
    /// The ratio of `self`.
    @inlinable var ratio: CGFloat {
        return width / height
    }
    
    
    /// The diagonal of `self`.
    @inlinable var diagonal: CGFloat {
        length(size.simd2).cgFloat
    }
    
    /// The orientation of `self`.
    @inlinable var orientation: Orientation {
        switch ratio {
        case let x where x < 1.0: return .portrait
        case let x where x > 1.0: return .landscape
        default: return .square
        }
    }
}
