An Angle type already exists in Foundation; see Measurement<UnitAngle>. You could add some convenience methods in an extension pretty easily.
import Foundation
typealias Angle = Measurement<UnitAngle>
extension Measurement where UnitType == UnitAngle {
var sine: Double {
let radians = self.converted(to: .radians).value
return sin(radians)
}
static var threeQuarterTurn: Angle {
return Angle(value: 0.75, unit: .revolutions)
}
}
let x = Angle.threeQuarterTurn
x.sine // -1
-BJ
Maybe it would be good to pitch such improvements to the Foundation API? âAngleâ is certainly a lot more discoverable and convenient to type than âMeasurement<UnitAngle>â. That said, I tend not to use Foundationâs Measurement API. Itâs pretty heavyweight.
test.swift:
import Foundation
@available(macOS 10.12, *)
func a() {
let a = Measurement(value: 20, unit: UnitDuration.minutes).converted(to: .seconds)
}
Generated IR:
define hidden swiftcc void @_T04test1ayyF() #0 {
entry:
%0 = call %swift.type* @_T0So12UnitDurationCMa() #3
%1 = getelementptr inbounds %swift.type, %swift.type* %0, i32 0, i32 0
%.kind = load i64, i64* %1, align 8
%isObjCClassWrapper = icmp eq i64 %.kind, 14
br i1 %isObjCClassWrapper, label %isWrapper, label %metadataForClass.cont
isWrapper: ; preds = %entry
%2 = bitcast %swift.type* %0 to %swift.type**
%3 = getelementptr inbounds %swift.type*, %swift.type** %2, i64 1
%4 = load %swift.type*, %swift.type** %3, align 8, !invariant.load !31
br label %metadataForClass.cont
metadataForClass.cont: ; preds = %isWrapper, %entry
%.class = phi %swift.type* [ %0, %entry ], [ %4, %isWrapper ]
%5 = bitcast %swift.type* %.class to %objc_class*
%6 = load i8*, i8** @"\01L_selector(minutes)", align 8
%7 = bitcast %objc_class* %5 to i8*
%8 = call %0* bitcast (void ()* @objc_msgSend to %0* (i8*, i8*)*)(i8* %7, i8* %6)
%9 = bitcast %0* %8 to i8*
%10 = call i8* @objc_retainAutoreleasedReturnValue(i8* %9) #4
%11 = bitcast i8* %10 to %0*
%12 = bitcast %0* %11 to %TSo12UnitDurationC*
%.asUnsubstituted = bitcast %TSo12UnitDurationC* %12 to %TSo4UnitC*
%13 = call swiftcc { %TSo4UnitC*, double } @_T010Foundation11MeasurementVACyxGSd5value_x4unittcfC(double 2.000000e+01, %TSo4UnitC* %.asUnsubstituted, %swift.type* %0)
%14 = extractvalue { %TSo4UnitC*, double } %13, 0
%15 = extractvalue { %TSo4UnitC*, double } %13, 1
%.asSubstituted = bitcast %TSo4UnitC* %14 to %TSo12UnitDurationC*
%16 = getelementptr inbounds %swift.type, %swift.type* %0, i32 0, i32 0
%.kind1 = load i64, i64* %16, align 8
%isObjCClassWrapper2 = icmp eq i64 %.kind1, 14
br i1 %isObjCClassWrapper2, label %isWrapper3, label %metadataForClass.cont4
isWrapper3: ; preds = %metadataForClass.cont
%17 = bitcast %swift.type* %0 to %swift.type**
%18 = getelementptr inbounds %swift.type*, %swift.type** %17, i64 1
%19 = load %swift.type*, %swift.type** %18, align 8, !invariant.load !31
br label %metadataForClass.cont4
metadataForClass.cont4: ; preds = %isWrapper3, %metadataForClass.cont
%.class5 = phi %swift.type* [ %0, %metadataForClass.cont ], [ %19, %isWrapper3 ]
%20 = bitcast %swift.type* %.class5 to %objc_class*
%21 = load i8*, i8** @"\01L_selector(seconds)", align 8
%22 = bitcast %objc_class* %20 to i8*
%23 = call %0* bitcast (void ()* @objc_msgSend to %0* (i8*, i8*)*)(i8* %22, i8* %21)
%24 = bitcast %0* %23 to i8*
%25 = call i8* @objc_retainAutoreleasedReturnValue(i8* %24) #4
%26 = bitcast i8* %25 to %0*
%27 = bitcast %0* %26 to %TSo12UnitDurationC*
%.asUnsubstituted6 = bitcast %TSo12UnitDurationC* %27 to %TSo9DimensionC*
%.asSubstituted.asUnsubstituted = bitcast %TSo12UnitDurationC* %.asSubstituted to %TSo9DimensionC*
%28 = call swiftcc { %TSo9DimensionC*, double } @_T010Foundation11MeasurementVAASo9DimensionCRbzlE9convertedACyxGx2to_tF(%TSo9DimensionC* %.asUnsubstituted6, %TSo9DimensionC* %.asSubstituted.asUnsubstituted, double %15, %swift.type* %0)
%29 = extractvalue { %TSo9DimensionC*, double } %28, 0
%30 = extractvalue { %TSo9DimensionC*, double } %28, 1
%.asSubstituted7 = bitcast %TSo9DimensionC* %29 to %TSo12UnitDurationC*
call void bitcast (void (%objc_object*)* @objc_release to void (%TSo12UnitDurationC*)*)(%TSo12UnitDurationC* %.asSubstituted) #4
call void bitcast (void (%objc_object*)* @objc_release to void (%TSo12UnitDurationC*)*)(%TSo12UnitDurationC* %.asSubstituted7) #4
ret void
}
declare swiftcc { %TSo9DimensionC*, double } @_T010Foundation11MeasurementVAASo9DimensionCRbzlE9convertedACyxGx2to_tF(%TSo9DimensionC*, %TSo9DimensionC*, double, %swift.type*) #0
declare swiftcc { %TSo4UnitC*, double } @_T010Foundation11MeasurementVACyxGSd5value_x4unittcfC(double, %TSo4UnitC*, %swift.type*) #0
; Function Attrs: nounwind readnone
define linkonce_odr hidden %swift.type* @_T0So12UnitDurationCMa() #1 {
entry:
%0 = load %swift.type*, %swift.type** @_T0So12UnitDurationCML, align 8
%1 = icmp eq %swift.type* %0, null
br i1 %1, label %cacheIsNull, label %cont
cacheIsNull: ; preds = %entry
%2 = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_NSUnitDuration", align 8
%3 = call %objc_class* @swift_rt_swift_getInitializedObjCClass(%objc_class* %2)
%4 = call %swift.type* @swift_getObjCClassMetadata(%objc_class* %3) #3
store atomic %swift.type* %4, %swift.type** @_T0So12UnitDurationCML release, align 8
br label %cont
cont: ; preds = %cacheIsNull, %entry
%5 = phi %swift.type* [ %0, %entry ], [ %4, %cacheIsNull ]
ret %swift.type* %5
}
; Function Attrs: noinline nounwind
define linkonce_odr hidden %objc_class* @swift_rt_swift_getInitializedObjCClass(%objc_class*) #2 {
entry:
%load = load %objc_class* (%objc_class*)*, %objc_class* (%objc_class*)** @_swift_getInitializedObjCClass
%1 = tail call %objc_class* %load(%objc_class* %0)
ret %objc_class* %1
}
declare %swift.type* @swift_getObjCClassMetadata(%objc_class*)
declare void @objc_msgSend()
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
declare void @objc_release(%objc_object*)
⊠which, personally, I think is just excessive. Maybe for complex conversions itâs worth it, but Iâm not sure it is for simple conversions.
- Karl
···
On 14. Jan 2018, at 06:04, BJ Homer via swift-evolution <swift-evolution@swift.org> wrote:
On Jan 13, 2018, at 9:31 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I would like to see a full Geometry implementation but I don't think it should be part of the standard library.
I've kicked around some ideas here:
* angle.swift · GitHub
* Angle+Trig.swift · GitHub
and
* GitHub - erica/SwiftGeometry: CGHeck
On Jan 13, 2018, at 7:49 PM, Jonathan Hull via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hi Evolution,
I would really like to see Swift gain an Angle type in the standard library. Every time I have to deal with an angle in an api, I have to go figure out the conventions for that call. Is it in degrees? Is it in radians? What if it is in radians, but I want to think about it in degrees?
I ended up writing an Angle type for my own code a few years back, and I have to say it is really wonderful. It has greatly simplified my graphics work. It takes a lot of mental load off of my brain when dealing with Angles.
I can of course initialize it either as degrees or radians (or revolutions), but I can also just say things like â.threeQuarterTurnâ, and then I can get the value back out in whatever format I like. There are also useful additions that let me normalize the angle to different ranges and which let me snap to the nearest multiple of an angle. Both of these are enormously useful for user facing features. I can also do math on angles in a way that makes geometric sense for angles. It is also really useful for interacting with CGVectors in intelligent ways.
Using Doubles or CGFloats to represent angles everywhere is just semantically wrong IMHO, and it stops us from adding all of these angle-specific niceties.
Happy to provide code if there is interestâŠ
Thanks,
Jon
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution