Skip to content

Commit 61d1c59

Browse files
authored
[stdlib] Introducing the new Arithmetic protocol (#3479)
* [stdlib] Introducing the new Arithmetic protocol * [stdlib] conforming floating point types to the new Arithmetic protocol * [stdlib] removing AbsoluteValuable conformance from floating point types * [stdlib] removing the integers prototype
1 parent b7622b4 commit 61d1c59

File tree

9 files changed

+161
-1935
lines changed

9 files changed

+161
-1935
lines changed

benchmark/single-source/MonteCarloE.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ public func run_MonteCarloE(scale: Int) {
3333
"Incorrect results in MonteCarloE: no empty intervals.")
3434
let e_estimate = Double(N)/Double(numEmptyIntervals)
3535
let e = 2.71828
36-
CheckResults(Double.abs(e_estimate - e) < 0.1,
36+
CheckResults(abs(e_estimate - e) < 0.1,
3737
"Incorrect results in MonteCarloE: e_estimate == \(e_estimate)")
3838
}

benchmark/single-source/MonteCarloPi.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ public func run_MonteCarloPi(scale: Int) {
2525
}
2626
let pi_estimate: Double = Double(pointsInside)*4.0/Double(N)
2727
let pi = 3.1415
28-
CheckResults(Double.abs(pi_estimate - pi) < 0.1,
28+
CheckResults(abs(pi_estimate - pi) < 0.1,
2929
"Incorrect results in MonteCarloPi: pi_estimate == \(pi_estimate)")
3030
}

stdlib/public/SDK/CoreGraphics/CGFloat.swift.gyb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ public struct CGFloat {
174174
return CGFloat(native.nextUp)
175175
}
176176

177-
public static func abs(_ x: CGFloat) -> CGFloat {
178-
return CGFloat(NativeType.abs(x.native))
177+
public var magnitude: CGFloat {
178+
return CGFloat(abs(native))
179179
}
180180

181181
public mutating func negate() {
@@ -296,6 +296,11 @@ extension CGFloat {
296296
public static var max: CGFloat {
297297
fatalError("unavailable")
298298
}
299+
300+
@available(*, unavailable, message: "Please use the `abs(_:)` free function")
301+
public static func abs(_ x: CGFloat) -> CGFloat {
302+
fatalError("unavailable")
303+
}
299304
}
300305

301306
@available(*, unavailable, renamed: "CGFloat.leastNormalMagnitude")

stdlib/public/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ set(SWIFTLIB_ESSENTIAL
6262
InputStream.swift
6363
IntegerArithmetic.swift.gyb
6464
IntegerParsing.swift.gyb
65+
Integers.swift.gyb
6566
Join.swift
6667
LazyCollection.swift.gyb
6768
LazySequence.swift

stdlib/public/core/FloatingPoint.swift.gyb

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,12 @@ word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
2727
/// The BinaryFloatingPoint protocol refines these requirements, adds some
2828
/// additional operations that only make sense for a fixed radix, and also
2929
/// provides default implementations of some of the FloatingPoint APIs.
30-
public protocol FloatingPoint: Comparable, ExpressibleByIntegerLiteral,
31-
SignedNumber, AbsoluteValuable, Strideable {
30+
public protocol FloatingPoint: Comparable, Arithmetic,
31+
SignedNumber, Strideable {
3232

3333
/// An integer type that can represent any written exponent.
3434
associatedtype Exponent: SignedInteger
3535

36-
/// Initialize to zero
37-
init()
38-
3936
/// Initialize from sign, exponent, and significand.
4037
///
4138
/// The result is:
@@ -926,5 +923,11 @@ extension BinaryFloatingPoint {
926923
*/
927924
}
928925

926+
/// Returns the absolute value of `x`.
927+
@_transparent
928+
public func abs<T : FloatingPoint>(_ x: T) -> T where T.Magnitude == T {
929+
return x.magnitude
930+
}
931+
929932
@available(*, unavailable, renamed: "FloatingPoint")
930933
public typealias FloatingPointType = FloatingPoint

stdlib/public/core/FloatingPointTypes.swift.gyb

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -766,12 +766,10 @@ extension ${Self} : Hashable {
766766
}
767767
}
768768

769-
@_transparent
770-
extension ${Self} : AbsoluteValuable {
771-
/// Returns the absolute value of `x`.
769+
extension ${Self} : Arithmetic {
772770
@_transparent
773-
public static func abs(_ x: ${Self}) -> ${Self} {
774-
return ${Self}(_bits: Builtin.int_fabs_FPIEEE${bits}(x._value))
771+
public var magnitude: ${Self} {
772+
return ${Self}(_bits: Builtin.int_fabs_FPIEEE${bits}(_value))
775773
}
776774
}
777775

@@ -1008,4 +1006,13 @@ extension ${Self} {
10081006
% end
10091007
% end
10101008
}
1009+
1010+
1011+
extension ${Self} {
1012+
@available(*, unavailable, message: "Please use the `abs(_:)` free function")
1013+
public static func abs(_ x: ${Self}) -> ${Self} {
1014+
fatalError("unavailable")
1015+
}
1016+
}
1017+
10111018
% end # for (bits, signed) in allInts()

stdlib/public/core/GroupInfo.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
"BuiltinMath.swift",
101101
{
102102
"Integers": [
103+
"Integers.swift",
103104
"IntegerArithmetic.swift",
104105
"FixedPoint.swift",
105106
"IntegerParsing.swift"],

stdlib/public/core/Integers.swift.gyb

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//===--- Integers.swift.gyb -----------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
%{
13+
#
14+
# Utility code for later in this template
15+
#
16+
17+
# Number of bits in the Builtin.Word type
18+
word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
19+
20+
# Number of bits in integer literals.
21+
builtinIntLiteralBits = 2048
22+
IntLiteral = 'Int%s' % builtinIntLiteralBits
23+
24+
class struct(object):
25+
def __init__(self, **kw):
26+
self.__dict__ = kw
27+
def __repr__(self):
28+
return 'struct(%r)' % self.__dict__
29+
30+
binaryArithmetic = {
31+
'Arithmetic' : [
32+
struct(operator='+', name='adding', mutatingName='add', firstArg='_', llvmName='add', kind='+'),
33+
struct(operator='-', name='subtracting', mutatingName='subtract', firstArg='_', llvmName='sub', kind='-'),
34+
struct(operator='*', name='multiplied', mutatingName='multiply', firstArg='by', llvmName='mul', kind='*'),
35+
struct(operator='/', name='divided', mutatingName='divide', firstArg='by', llvmName='div', kind='/'),
36+
],
37+
}
38+
39+
}%
40+
41+
//===--- Bits for the Stdlib ----------------------------------------------===//
42+
43+
44+
//FIXME: This should go in the stdlib separately, probably.
45+
extension ExpressibleByIntegerLiteral
46+
where Self : _ExpressibleByBuiltinIntegerLiteral {
47+
/// Create an instance initialized to `value`.
48+
@_transparent
49+
public init(integerLiteral value: Self) {
50+
self = value
51+
}
52+
}
53+
54+
//===----------------------------------------------------------------------===//
55+
//===--- Arithmetic -------------------------------------------------------===//
56+
//===----------------------------------------------------------------------===//
57+
58+
/// Declares methods backing binary arithmetic operators—such as `+`, `-` and
59+
/// `*`—and their mutating counterparts.
60+
///
61+
/// It provides a suitable basis for arithmetic on scalars such as integers and
62+
/// floating point numbers.
63+
///
64+
/// Both mutating and non-mutating operations are declared in the protocol,
65+
/// however only the mutating ones are required, as default implementations of
66+
/// the non-mutating ones are provided by a protocol extension.
67+
///
68+
/// The `Magnitude` associated type is able to hold the absolute value of any
69+
/// possible value of `Self`. Concrete types do not have to provide a typealias
70+
/// for it, as it can be inferred from the `magnitude` property. This property
71+
/// can be useful in operations that are simpler to implement in terms of
72+
/// unsigned values, for example, printing a value of an integer, which is just
73+
/// printing a '-' character in front of an absolute value.
74+
///
75+
/// Please note that for ordinary work, the `magnitude` property **should not**
76+
/// be preferred to the `abs(_)` function, whose return value is of the same
77+
/// type as its argument.
78+
public protocol Arithmetic : Equatable, ExpressibleByIntegerLiteral {
79+
// FIXME: implement
80+
//init?<T : Integer>(exactly source: T)
81+
82+
// FIXME(ABI): should be just Arithmetic
83+
associatedtype Magnitude : Equatable, ExpressibleByIntegerLiteral
84+
85+
var magnitude: Magnitude { get }
86+
87+
88+
% for x in binaryArithmetic['Arithmetic']:
89+
// defaulted using an in-place counterpart, but can be used as an
90+
// optimization hook
91+
func ${x.name}(${x.firstArg} rhs: Self) -> Self
92+
93+
// implementation hook
94+
mutating func ${x.mutatingName}(${x.firstArg} rhs: Self)
95+
% end
96+
}
97+
98+
extension Arithmetic {
99+
@_transparent
100+
public init() {
101+
self = 0
102+
}
103+
}
104+
105+
% for Protocol in ['Arithmetic']:
106+
extension ${Protocol} {
107+
% for x in binaryArithmetic[Protocol]:
108+
% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
109+
public func ${x.name}(${x.firstArg} rhs: Self) -> Self {
110+
var lhs = self
111+
lhs.${x.mutatingName}(${callLabel}rhs)
112+
return lhs
113+
}
114+
% end
115+
}
116+
% end
117+
118+
public protocol SignedArithmetic : Arithmetic {
119+
func negated() -> Self
120+
mutating func negate()
121+
}
122+
123+
extension SignedArithmetic {
124+
public func negated() -> Self {
125+
return Self().subtracting(self)
126+
}
127+
public mutating func negate() {
128+
self = negated()
129+
}
130+
}

0 commit comments

Comments
 (0)