Improve Number Type


(James Campbell) #1

There is a number of deficiencies with Swift and Numbers. Especially when
trying to be clever with generics.

- The API exposes built in types like`BuiltIn.Word` as the return type of
some APIs but there is no way to use said types.
- We have a Float and a Float80. Float and Doubles can't be initialised
(via init) with anything but Integer values but Float80 can be initialized
with both Floating Point and Integer
- We have a SignedNumberType but no UnsignedNumberType, All the floating
points use this protocol, so shouldn't this be NumberType ?
- SignedIntegerType and UnsignedIntegerType have a way of generically
constructing an Int as long as you cast it to the Maximum Int or UInt. But
there is no such thing for Floating Point Numbers.
- We have Float80 and a typealised Float32 and Float64. Why couldn't have
triple as an extra type name, as having one true type with a number is
confusing ?
- If all number types could be initilized with all number types, then a lot
of the constructors could be in the NumberType protocol.

Just in general it was hard to extend integers and floating point types.
For example in my code I wanted to pass a struct that contained a value to
any Floating Point or Integer and it would convert.

This is what I had to do, which is far too much and even sure I'm not
convinced it will work in every condition.

*protocol Box: CustomStringConvertible, CustomDebugStringConvertible {*

* typealias BoxType = Any*

* var value: BoxType { get set }*

* init()*

* init(_ value: BoxType)*

*}*

*protocol AngleType: Box {*

* typealias BoxType = Double*

*}*

*//Mark:- Box - FloatingPointType Conversion*

*extension SignedIntegerType {*

* init<T: Box where T.BoxType == Float80>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Double>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Float>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int8>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int16>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int32>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int64>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt8>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt16>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt32>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt64>(_ value: T) {*

* self.init(IntMax(value.value))*

* }*

*}*

*extension UnsignedIntegerType {*

* init<T: Box where T.BoxType == Float80>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Double>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Float>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int8>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int16>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int32>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == Int64>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt8>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt16>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt32>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

* init<T: Box where T.BoxType == UInt64>(_ value: T) {*

* self.init(UIntMax(value.value))*

* }*

*}*

*extension Float*

*{*

* init<T: Box where T.BoxType == Float>(_ value: T)*

* {*

* self.value = value.value.value*

* }*

*}*

*extension Double*

*{*

* init<T: Box where T.BoxType == Double>(_ value: T)*

* {*

* self.value = value.value.value*

* }*

*}*

*extension Float80*

*{*

* init<T: Box where T.BoxType == Float80>(_ value: T)*

* {*

* self.init(value.value)*

* }*

*}*

*extension FloatingPointType {*

* init<T: Box where T.BoxType == Int>(_ value: T) {*

* self.init(value.value)*

* }*

* init<T: Box where T.BoxType == Int8>(_ value: T) {*

* self.init(value.value)*

* }*

* init<T: Box where T.BoxType == Int16>(_ value: T) {*

* self.init(value.value)*

* }*

* init<T: Box where T.BoxType == Int32>(_ value: T) {*

* self.init(value.value)*

* }*

* init<T: Box where T.BoxType == Int64>(_ value: T) {*

* self.init(value.value)*

* }*

* init<T: Box where T.BoxType == UInt>(_ value: T) {*

* self.init(value.value)*

* }*

* init<T: Box where T.BoxType == UInt8>(_ value: T) {*

* self.init(value.value)*

* }*

* init<T: Box where T.BoxType == UInt16>(_ value: T) {*

* self.init(value.value)*

* }*

* init<T: Box where T.BoxType == UInt32>(_ value: T) {*

* self.init(value.value)*

* }*

* init<T: Box where T.BoxType == UInt64>(_ value: T) {*

* self.init(value.value)*

* }*

*}*

···

--
 Wizard
james@supmenow.com
+44 7523 279 698


(Dave Abrahams) #2

We’re currently working on improving most of these things. You can see some of our work in progress here:
https://github.com/apple/swift/blob/master/test/Prototypes/Integers.swift.gyb
https://github.com/apple/swift/blob/master/test/Prototypes/FloatingPoint.swift

-Dave

···

On Jan 6, 2016, at 3:32 PM, James Campbell via swift-evolution <swift-evolution@swift.org> wrote:

There is a number of deficiencies with Swift and Numbers. Especially when trying to be clever with generics.

- The API exposes built in types like`BuiltIn.Word` as the return type of some APIs but there is no way to use said types.
- We have a Float and a Float80. Float and Doubles can't be initialised (via init) with anything but Integer values but Float80 can be initialized with both Floating Point and Integer
- We have a SignedNumberType but no UnsignedNumberType, All the floating points use this protocol, so shouldn't this be NumberType ?
- SignedIntegerType and UnsignedIntegerType have a way of generically constructing an Int as long as you cast it to the Maximum Int or UInt. But there is no such thing for Floating Point Numbers.
- We have Float80 and a typealised Float32 and Float64. Why couldn't have triple as an extra type name, as having one true type with a number is confusing ?
- If all number types could be initilized with all number types, then a lot of the constructors could be in the NumberType protocol.


(David Sweeris) #3

While we’re (sorta) on the topic, is there any chance the bitwise operators (“&”, “|”, and "^") could be renamed to ".&”, ".|”, and ".^”? Or maybe only defined for some sort of Bitfield<T> wrapper type? “^” already has a numeric meaning (3^2 = 9), and “|” and “&” are a convenient custom operators (they’re easy to recognize and I think are the only two single-character vclid operators that doesn’t require obscure keystrokes to type and don’t already have a fairly obvious meaning).

(Mostly I’m interested in “|” and “^”, but it’d be weird and confusing to treat “&” specially.)

···

On Jan 6, 2016, at 15:39, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 6, 2016, at 3:32 PM, James Campbell via swift-evolution <swift-evolution@swift.org> wrote:

There is a number of deficiencies with Swift and Numbers. Especially when trying to be clever with generics.

- The API exposes built in types like`BuiltIn.Word` as the return type of some APIs but there is no way to use said types.
- We have a Float and a Float80. Float and Doubles can't be initialised (via init) with anything but Integer values but Float80 can be initialized with both Floating Point and Integer
- We have a SignedNumberType but no UnsignedNumberType, All the floating points use this protocol, so shouldn't this be NumberType ?
- SignedIntegerType and UnsignedIntegerType have a way of generically constructing an Int as long as you cast it to the Maximum Int or UInt. But there is no such thing for Floating Point Numbers.
- We have Float80 and a typealised Float32 and Float64. Why couldn't have triple as an extra type name, as having one true type with a number is confusing ?
- If all number types could be initilized with all number types, then a lot of the constructors could be in the NumberType protocol.

We’re currently working on improving most of these things. You can see some of our work in progress here:
https://github.com/apple/swift/blob/master/test/Prototypes/Integers.swift.gyb
https://github.com/apple/swift/blob/master/test/Prototypes/FloatingPoint.swift

-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #4

Almost certainly no. The bar for diverging for the C family precedent on this is very high. Saying that you want to rename (e.g.) ^ to .^ so that you can repurpose ^ for some other thing is extremely unlikely to happen.

If you are really interested in exponentiation, ** is a better path to follow. However, even that has a number of problems that the numerics folks will jump onto :-)

-Chris

···

On Jan 7, 2016, at 8:42 PM, Dave via swift-evolution <swift-evolution@swift.org> wrote:

While we’re (sorta) on the topic, is there any chance the bitwise operators (“&”, “|”, and "^") could be renamed to ".&”, ".|”, and ".^”? Or maybe only defined for some sort of Bitfield<T> wrapper type? “^” already has a numeric meaning (3^2 = 9), and “|” and “&” are a convenient custom operators (they’re easy to recognize and I think are the only two single-character vclid operators that doesn’t require obscure keystrokes to type and don’t already have a fairly obvious meaning).