// Exponentiation operator. (2.02)
 
import Foundation
 
precedencegroup ExponentiationPrecedence {
    associativity: right
    higherThan: MultiplicationPrecedence
}
 
infix operator ** : ExponentiationPrecedence
 
func ** <T: BinaryFloatingPoint>(_ x: T, _ y: T) -> Double {
    return pow(Double
(x
), Double
(y
)) }
 
func ** <T: BinaryInteger>(_ x: T, _ y: T) -> Int {
    let base = Int(x)
    let expt = Int(y)
 
    if expt == 0 {
        return 1
    } else if base == 0 || base == 1 {
        return base
    } else if base == -1 {
        return expt % 2 == 0 ? 1 : -1
    } else if expt < 0 {
        return 0
    }
 
    func detail(_ base: Int, _ expt: Int) -> Int {
        if expt == 1 {
            return base
        } else if expt % 2 == 0 {
            return detail(base * base, expt / 2)
        } else {
            return base * detail(base, expt - 1)
        }
    }
 
    return detail(base, expt)
}
 
// Test.
 
func check<T: Equatable>(_ f: () -> Any, expect: T) {
    let result = f()
    print(result, terminator: "\t")
    if let x = result as? T {
        print(x == expect ? "Pass." : "Fail: \(expect)")
    } else {
        print("Fail: \(type(of: result)) not \(T.self)")
    }
}
 
#if DEBUG
check({2   ** 0},        expect: 2)
check({2   ** Int8(1)},  expect: 2.0)
check({2.0 ** 2},        expect: 4)
#endif
 
// Zero.
 
check({0 ** -2},         expect: 0)
check({0 ** -1},         expect: 0)
check({0 **  0},         expect: 1)
check({0 **  1},         expect: 0)
check({0 **  2},         expect: 0)
 
// Positive.
 
check({1 ** -2},         expect: 1)
check({1 ** -1},         expect: 1)
check({1 **  0},         expect: 1)
check({1 **  1},         expect: 1)
check({1 **  2},         expect: 1)
 
check({2 ** -2},         expect: 0)
check({2 ** -1},         expect: 0)
check({2 **  0},         expect: 1)
check({2 **  1},         expect: 2)
check({2 **  2},         expect: 4)
 
// Negative.
 
check({-1 ** -2},        expect: 1)
check({-1 ** -1},        expect: -1)
check({-1 **  0},        expect: 1)
check({-1 **  1},        expect: -1)
check({-1 **  2},        expect: 1)
 
check({-2 ** -2},        expect: 0)
check({-2 ** -1},        expect: 0)
check({-2 **  0},        expect: 1)
check({-2 **  1},        expect: -2)
check({-2 **  2},        expect: 4)
 
// Floating point and mixed types.
 
check({2   ** Int8(1)},  expect: 2)
check({2.0 ** 2},        expect: 4.0)
check({2.0 ** Float(3)}, expect: 8.0)
check({2   ** 4.0},      expect: 16.0)
check({2.0 ** 5.0},      expect: 32.0)
 
// Precedence and associativity.
 
check({3  * 2 ** 2},     expect: 12)
check({2 ** 2 ** 3},     expect: 256)
check({2 ** 3 ** 2},     expect: 512)
				Ly8gRXhwb25lbnRpYXRpb24gb3BlcmF0b3IuICgyLjAyKQoKaW1wb3J0IEZvdW5kYXRpb24KCnByZWNlZGVuY2Vncm91cCBFeHBvbmVudGlhdGlvblByZWNlZGVuY2UgewogICAgYXNzb2NpYXRpdml0eTogcmlnaHQKICAgIGhpZ2hlclRoYW46IE11bHRpcGxpY2F0aW9uUHJlY2VkZW5jZQp9CgppbmZpeCBvcGVyYXRvciAqKiA6IEV4cG9uZW50aWF0aW9uUHJlY2VkZW5jZQoKZnVuYyAqKiA8VDogQmluYXJ5RmxvYXRpbmdQb2ludD4oXyB4OiBULCBfIHk6IFQpIC0+IERvdWJsZSB7CiAgICByZXR1cm4gcG93KERvdWJsZSh4KSwgRG91YmxlKHkpKQp9CgpmdW5jICoqIDxUOiBCaW5hcnlJbnRlZ2VyPihfIHg6IFQsIF8geTogVCkgLT4gSW50IHsKICAgIGxldCBiYXNlID0gSW50KHgpCiAgICBsZXQgZXhwdCA9IEludCh5KQoKICAgIGlmIGV4cHQgPT0gMCB7CiAgICAgICAgcmV0dXJuIDEKICAgIH0gZWxzZSBpZiBiYXNlID09IDAgfHwgYmFzZSA9PSAxIHsKICAgICAgICByZXR1cm4gYmFzZQogICAgfSBlbHNlIGlmIGJhc2UgPT0gLTEgewogICAgICAgIHJldHVybiBleHB0ICUgMiA9PSAwID8gMSA6IC0xCiAgICB9IGVsc2UgaWYgZXhwdCA8IDAgewogICAgICAgIHJldHVybiAwCiAgICB9CgogICAgZnVuYyBkZXRhaWwoXyBiYXNlOiBJbnQsIF8gZXhwdDogSW50KSAtPiBJbnQgewogICAgICAgIGlmIGV4cHQgPT0gMSB7CiAgICAgICAgICAgIHJldHVybiBiYXNlCiAgICAgICAgfSBlbHNlIGlmIGV4cHQgJSAyID09IDAgewogICAgICAgICAgICByZXR1cm4gZGV0YWlsKGJhc2UgKiBiYXNlLCBleHB0IC8gMikKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gYmFzZSAqIGRldGFpbChiYXNlLCBleHB0IC0gMSkKICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIGRldGFpbChiYXNlLCBleHB0KQp9CgovLyBUZXN0LgoKZnVuYyBjaGVjazxUOiBFcXVhdGFibGU+KF8gZjogKCkgLT4gQW55LCBleHBlY3Q6IFQpIHsKICAgIGxldCByZXN1bHQgPSBmKCkKICAgIHByaW50KHJlc3VsdCwgdGVybWluYXRvcjogIlx0IikKICAgIGlmIGxldCB4ID0gcmVzdWx0IGFzPyBUIHsKICAgICAgICBwcmludCh4ID09IGV4cGVjdCA/ICJQYXNzLiIgOiAiRmFpbDogXChleHBlY3QpIikKICAgIH0gZWxzZSB7CiAgICAgICAgcHJpbnQoIkZhaWw6IFwodHlwZShvZjogcmVzdWx0KSkgbm90IFwoVC5zZWxmKSIpCiAgICB9Cn0KCiNpZiBERUJVRwpjaGVjayh7MiAgICoqIDB9LCAgICAgICAgZXhwZWN0OiAyKQpjaGVjayh7MiAgICoqIEludDgoMSl9LCAgZXhwZWN0OiAyLjApCmNoZWNrKHsyLjAgKiogMn0sICAgICAgICBleHBlY3Q6IDQpCiNlbmRpZgoKLy8gWmVyby4KCmNoZWNrKHswICoqIC0yfSwgICAgICAgICBleHBlY3Q6IDApCmNoZWNrKHswICoqIC0xfSwgICAgICAgICBleHBlY3Q6IDApCmNoZWNrKHswICoqICAwfSwgICAgICAgICBleHBlY3Q6IDEpCmNoZWNrKHswICoqICAxfSwgICAgICAgICBleHBlY3Q6IDApCmNoZWNrKHswICoqICAyfSwgICAgICAgICBleHBlY3Q6IDApCgovLyBQb3NpdGl2ZS4KCmNoZWNrKHsxICoqIC0yfSwgICAgICAgICBleHBlY3Q6IDEpCmNoZWNrKHsxICoqIC0xfSwgICAgICAgICBleHBlY3Q6IDEpCmNoZWNrKHsxICoqICAwfSwgICAgICAgICBleHBlY3Q6IDEpCmNoZWNrKHsxICoqICAxfSwgICAgICAgICBleHBlY3Q6IDEpCmNoZWNrKHsxICoqICAyfSwgICAgICAgICBleHBlY3Q6IDEpCgpjaGVjayh7MiAqKiAtMn0sICAgICAgICAgZXhwZWN0OiAwKQpjaGVjayh7MiAqKiAtMX0sICAgICAgICAgZXhwZWN0OiAwKQpjaGVjayh7MiAqKiAgMH0sICAgICAgICAgZXhwZWN0OiAxKQpjaGVjayh7MiAqKiAgMX0sICAgICAgICAgZXhwZWN0OiAyKQpjaGVjayh7MiAqKiAgMn0sICAgICAgICAgZXhwZWN0OiA0KQoKLy8gTmVnYXRpdmUuCgpjaGVjayh7LTEgKiogLTJ9LCAgICAgICAgZXhwZWN0OiAxKQpjaGVjayh7LTEgKiogLTF9LCAgICAgICAgZXhwZWN0OiAtMSkKY2hlY2soey0xICoqICAwfSwgICAgICAgIGV4cGVjdDogMSkKY2hlY2soey0xICoqICAxfSwgICAgICAgIGV4cGVjdDogLTEpCmNoZWNrKHstMSAqKiAgMn0sICAgICAgICBleHBlY3Q6IDEpCgpjaGVjayh7LTIgKiogLTJ9LCAgICAgICAgZXhwZWN0OiAwKQpjaGVjayh7LTIgKiogLTF9LCAgICAgICAgZXhwZWN0OiAwKQpjaGVjayh7LTIgKiogIDB9LCAgICAgICAgZXhwZWN0OiAxKQpjaGVjayh7LTIgKiogIDF9LCAgICAgICAgZXhwZWN0OiAtMikKY2hlY2soey0yICoqICAyfSwgICAgICAgIGV4cGVjdDogNCkKCi8vIEZsb2F0aW5nIHBvaW50IGFuZCBtaXhlZCB0eXBlcy4KCmNoZWNrKHsyICAgKiogSW50OCgxKX0sICBleHBlY3Q6IDIpCmNoZWNrKHsyLjAgKiogMn0sICAgICAgICBleHBlY3Q6IDQuMCkKY2hlY2soezIuMCAqKiBGbG9hdCgzKX0sIGV4cGVjdDogOC4wKQpjaGVjayh7MiAgICoqIDQuMH0sICAgICAgZXhwZWN0OiAxNi4wKQpjaGVjayh7Mi4wICoqIDUuMH0sICAgICAgZXhwZWN0OiAzMi4wKQoKLy8gUHJlY2VkZW5jZSBhbmQgYXNzb2NpYXRpdml0eS4KCmNoZWNrKHszICAqIDIgKiogMn0sICAgICBleHBlY3Q6IDEyKQpjaGVjayh7MiAqKiAyICoqIDN9LCAgICAgZXhwZWN0OiAyNTYpCmNoZWNrKHsyICoqIDMgKiogMn0sICAgICBleHBlY3Q6IDUxMik=