blob: 897c245260a6575dc5a2a14c5daa71cd4f9a2a12 [file] [log] [blame]
// RUN: %target-swift-frontend -typecheck -verify %s
// ~~~~~~~~~~~~~ Test top-level functions. ~~~~~~~~~~~~~
func linearFunc(_ x: Float) -> Float {
return x
}
@transposing(linearFunc, wrt: 0)
func transposingLinearFunc(x: Float) -> Float {
return x
}
func twoParams(_ x: Float, _ y: Double) -> Double {
return Double(x) + y
}
@transposing(twoParams, wrt: 0)
func twoParamsT1(_ y: Double, _ t: Double) -> Float {
return Float(t + y)
}
@transposing(twoParams, wrt: 1)
func twoParamsT2(_ x: Float, _ t: Double) -> Double {
return Double(x) + t
}
@transposing(twoParams, wrt: (0, 1))
func twoParamsT3(_ t: Double) -> (Float, Double) {
return (Float(t), t)
}
func threeParams(_ x: Float, _ y: Double, _ z: Float) -> Double {
return Double(x) + y
}
@transposing(threeParams, wrt: 0)
func threeParamsT1(_ y: Double, _ z: Float, _ t: Double) -> Float {
return Float(t + y) + z
}
@transposing(threeParams, wrt: 1)
func threeParamsT2(_ x: Float, _ z: Float, _ t: Double) -> Double {
return Double(x + z) + t
}
@transposing(threeParams, wrt: 2)
func threeParamsT3(_ x: Float, _ y: Double, _ t: Double) -> Float {
return Float(y + t) + x
}
@transposing(threeParams, wrt: (0, 1))
func threeParamsT4(_ z: Float, _ t: Double) -> (Float, Double) {
return (z + Float(t), Double(z) + t)
}
@transposing(threeParams, wrt: (0, 2))
func threeParamsT5(_ y: Double, _ t: Double) -> (Float, Float) {
let ret = Float(y + t)
return (ret, ret)
}
@transposing(threeParams, wrt: (0, 1, 2))
func threeParamsT5(_ t: Double) -> (Float, Double, Float) {
let ret = Float(t)
return (ret, t, ret)
}
// Generics
func generic<T: Differentiable>(x: T) -> T where T == T.TangentVector {
return x
}
@transposing(generic, wrt: 0)
func genericT<T: Differentiable>(x: T) -> T where T == T.TangentVector {
return x
}
func genericThreeParam<
T: Differentiable & BinaryFloatingPoint,
U: Differentiable & BinaryFloatingPoint,
V: Differentiable & BinaryFloatingPoint>(
t: T, u: U, v: V
) -> T where T == T.TangentVector,
U == U.TangentVector,
V == V.TangentVector {
return t
}
@transposing(genericThreeParam, wrt: 1)
func genericThreeParamT2<
T: Differentiable & BinaryFloatingPoint,
U: Differentiable & BinaryFloatingPoint,
V: Differentiable & BinaryFloatingPoint>(
t: T, v: V, s: T
) -> U where T == T.TangentVector,
U == U.TangentVector,
V == V.TangentVector {
return U(1)
}
@transposing(genericThreeParam, wrt: (0, 1, 2))
func genericThreeParamT2<
T: Differentiable & BinaryFloatingPoint,
U: Differentiable & BinaryFloatingPoint,
V: Differentiable & BinaryFloatingPoint>(
t: T
) -> (T, U, V) where T == T.TangentVector,
U == U.TangentVector,
V == V.TangentVector {
return (T(1), U(1), V(1))
}
func genericOneParamFloatOneParam<T: Differentiable & BinaryFloatingPoint>(
t: T, f: Float
) -> T where T == T.TangentVector {
return T(f)
}
@transposing(genericOneParamFloatOneParam, wrt: 0)
func genericOneParamFloatOneParamT1<T: Differentiable & BinaryFloatingPoint>(
f: Float, t: T
) -> T where T == T.TangentVector {
return t
}
@transposing(genericOneParamFloatOneParam, wrt: 1)
func genericOneParamFloatOneParamT1<T: Differentiable & BinaryFloatingPoint>(
t1: T, t2: T
) -> Float where T == T.TangentVector {
return 1
}
@transposing(genericOneParamFloatOneParam, wrt: (0, 1))
func genericOneParamFloatOneParamT1<T: Differentiable & BinaryFloatingPoint>(
t: T
) -> (T, Float) where T == T.TangentVector {
return (T(1), 1)
}
func withInt(x: Float, y: Int) -> Float {
if y >= 0 {
return x
} else {
return x
}
}
@transposing(withInt, wrt: 0)
func withIntT(x: Int, t: Float) -> Float {
return t
}
func missingDiffSelfRequirement<T: AdditiveArithmetic>(x: T) -> T {
return x
}
// expected-error @+1 {{'@transposing' attribute requires original function result to conform to 'Differentiable'}}
@transposing(missingDiffSelfRequirement, wrt: 0)
func missingDiffSelfRequirementT<T: AdditiveArithmetic>(x: T) -> T {
return x
}
// TODO: error should be "can only transpose with respect to parameters that conform to 'Differentiable' and where 'Int == Int.TangentVector'"
// but currently there is an assertion failure.
/*func missingSelfRequirement<T: Differentiable>(x: T)
-> T where T.TangentVector == T {
return x
}
@transposing(missingSelfRequirement, wrt: 0)
func missingSelfRequirementT<T: Differentiable>(x: T) -> T {
return x
}*/
func differentGenericConstraint<T: Differentiable & BinaryFloatingPoint>(x: T)
-> T where T == T.TangentVector {
return x
}
// expected-error @+2 {{type 'T' does not conform to protocol 'BinaryFloatingPoint'}}
// expected-error @+1 {{could not find function 'differentGenericConstraint' with expected type '<T where T : _Differentiable, T == T.TangentVector> (T) -> T'}}
@transposing(differentGenericConstraint, wrt: 0)
func differentGenericConstraintT<T: Differentiable>(x: T)
-> T where T == T.TangentVector {
return x
}
func transposingInt(x: Float, y: Int) -> Float {
if y >= 0 {
return x
} else {
return x
}
}
// expected-error @+1 {{can only transpose with respect to parameters that conform to 'Differentiable' and where 'Int == Int.TangentVector'}}
@transposing(transposingInt, wrt: 1)
func transposingIntT1(x: Float, t: Float) -> Int {
return Int(x)
}
// expected-error @+1 {{'@transposing' attribute requires original function result to conform to 'Differentiable'}}
@transposing(transposingInt, wrt: 0)
func tangentNotLast(t: Float, y: Int) -> Float {
return t
}
// ~~~~~~~~~~~~~ Test methods. ~~~~~~~~~~~~~
// // Method no parameters.
extension Float {
func getDouble() -> Double {
return Double(self)
}
}
extension Double {
@transposing(Float.getDouble, wrt: self)
func structTranspose() -> Float {
return Float(self)
}
}
// Method with one parameter.
extension Float {
func adding(_ double: Double) -> Float {
return self + Float(double)
}
@transposing(Float.adding, wrt: 0)
func addingT1(t: Float) -> Double {
return Double(self + t)
}
@transposing(Float.adding, wrt: self)
func addingT2(_ double: Double) -> Float {
return self + Float(double)
}
@transposing(Float.adding, wrt: (self, 0))
func addingT3() -> (Float, Double) {
return (self, Double(self))
}
}
// Different self type/result type.
extension Int {
func myAdding(_ double: Double) -> Float {
return Float(double)
}
}
extension Float {
@transposing(Int.myAdding, wrt: 0)
func addingT3(t: Int) -> Double {
return Double(self)
}
// TODO: throw an error due to Int not being differentiable.
// @transposing(Int.myAdding, wrt: (self, 0))
// func addingT3() -> (Int, Double) {
// return (Int(self), Double(self))
// }
}
// Static methods.
struct A : Differentiable & AdditiveArithmetic {
typealias TangentVector = A
var x: Double
static prefix func -(a: A) -> A {
return A(x: -a.x)
}
@transposing(A.-, wrt: 0)
func negationT(a: A.Type) -> A {
return A(x: 1)
}
}
extension Float {
static func myMultiply(lhs: Float, rhs: Float) -> Float {
return lhs * rhs
}
@transposing(Float.myMultiply, wrt: 0)
@transposing(Float.myMultiply, wrt: 1)
func myMultiplyT(selfType: Float.Type, param: Float) -> Float {
return self + param
}
static func threeParamsStatic(_ x: Float, _ y: Double, _ z: Float) -> Double {
return Double(x + z) + y
}
}
extension Double {
@transposing(Float.threeParamsStatic, wrt: (0, 1, 2))
func threeParamsT12(staticSelf: Float.Type) -> (Float, Double, Float) {
return (Float(self), self, Float(self))
}
@transposing(Float.threeParamsStatic, wrt: (0, 2))
func threeParamsT12(staticSelf: Float.Type, _ y: Double) -> (Float, Float) {
let ret = Float(self + y)
return (ret, ret)
}
@transposing(Float.threeParamsStatic, wrt: 1)
func threeParamsT12(staticSelf: Float.Type, _ x: Float, _ z: Float) -> Double {
return self + Double(x + z)
}
}
// Method with 3 parameters.
extension Float {
func threeParams(_ x: Float, _ y: Double, _ z: Float) -> Double {
return Double(self + x + z) + y
}
}
extension Double {
@transposing(Float.threeParams, wrt: 0)
func threeParamsT1(_ s: Float, _ y: Double, _ z: Float) -> Float {
return Float(self + y) + s + z
}
@transposing(Float.threeParams, wrt: 1)
func threeParamsT2(_ s: Float, _ x: Float, _ y: Float) -> Double {
return self + Double(x + s + y)
}
@transposing(Float.threeParams, wrt: 2)
func threeParamsT3(_ s: Float, _ x: Float, _ y: Double) -> Float {
return s + x + Float(self + y)
}
@transposing(Float.threeParams, wrt: (0, 1))
func threeParamsT4(_ s: Float, _ z: Float) -> (Float, Double) {
return (Float(self) + s + z, self + Double(s + z))
}
@transposing(Float.threeParams, wrt: (0, 2))
func threeParamsT5(_ s: Float, _ y: Double) -> (Float, Float) {
let ret = Float(self + y) + s
return (ret, ret)
}
@transposing(Float.threeParams, wrt: (0, 1, 2))
func threeParamsT6(s: Float) -> (Float, Double, Float) {
return (s + Float(self), Double(s) + self, s + Float(self))
}
@transposing(Float.threeParams, wrt: self)
func threeParamsT6(_ x: Float, _ y: Double, _ z: Float) -> Float {
return Float(self + y) + x
}
@transposing(Float.threeParams, wrt: (self, 0))
func threeParamsT7(_ y: Double, _ z: Float) -> (Float, Float) {
let ret = Float(self) + Float(y) + z
return (ret, ret)
}
@transposing(Float.threeParams, wrt: (self, 1))
func threeParamsT7(_ x: Float, _ z: Float) -> (Float, Double) {
return (Float(self) + x + z, self + Double(x + z))
}
@transposing(Float.threeParams, wrt: (self, 2))
func threeParamsT9(_ x: Float, _ y: Double) -> (Float, Float) {
let ret = Float(self + y) + x
return (ret, ret)
}
@transposing(Float.threeParams, wrt: (self, 0, 1))
func threeParamsT10(_ z: Float) -> (Float, Float, Double) {
let retF = Float(self) + z
return (retF, retF, self + Double(z))
}
@transposing(Float.threeParams, wrt: (self, 0, 2))
func threeParamsT11(_ y: Double) -> (Float, Float, Float) {
let ret = Float(self + y)
return (ret, ret, ret)
}
@transposing(Float.threeParams, wrt: (self, 0, 1, 2))
func threeParamsT12() -> (Float, Float, Double, Float) {
return (Float(self), Float(self), self, Float(self))
}
}
// Nested struct
struct level1 {
struct level2 {
func foo(x: Float) -> Float {
return x
}
}
}
extension Float {
@transposing(level1.level2.foo, wrt: 0)
func t(x: level1.level2) -> Float {
return self
}
@transposing(level1.level2.foo, wrt: (self, 0))
func t() -> (level1.level2, Float) {
return (level1.level2(), self)
}
}
// Generics
extension Float {
func genericOneParamFloatOneParam<T: Differentiable & BinaryFloatingPoint>(
t: T, f: Float
) -> Float where T == T.TangentVector {
return f
}
@transposing(Float.genericOneParamFloatOneParam, wrt: 0)
func genericOneParamFloatOneParamT1<T: Differentiable & BinaryFloatingPoint>(
f1: Float, f2: Float
) -> T where T == T.TangentVector {
return T(1)
}
@transposing(Float.genericOneParamFloatOneParam, wrt: (0, 1))
func genericOneParamFloatOneParamT2<T: Differentiable & BinaryFloatingPoint>(
f1: Float
) -> (T, Float) where T == T.TangentVector {
return (T(1), 1)
}
@transposing(Float.genericOneParamFloatOneParam, wrt: (self, 1))
func genericOneParamFloatOneParamT1<T: Differentiable & BinaryFloatingPoint>(
t: T
) -> (Float, Float) where T == T.TangentVector {
return (1, 1)
}
@transposing(Float.genericOneParamFloatOneParam, wrt: (self, 0, 1))
func genericOneParamFloatOneParamT1<
T: Differentiable & BinaryFloatingPoint
>() -> (Float, T, Float) where T == T.TangentVector {
return (1, T(1), 1)
}
}