Files
swift-mirror/stdlib/public/core/Integers.swift.gyb
2016-07-29 13:31:21 +03:00

1191 lines
35 KiB
Swift

//===--- Integers.swift.gyb -----------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
%{
#
# Utility code for later in this template
#
from SwiftIntTypes import all_integer_types, int_max_bits, should_define_truncating_bit_pattern_init
from string import maketrans, capitalize
# Number of bits in the Builtin.Word type
word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
# Number of bits in integer literals.
builtinIntLiteralBits = 2048
IntLiteral = 'Int%s' % builtinIntLiteralBits
class struct(object):
def __init__(self, **kw):
self.__dict__ = kw
def __repr__(self):
return 'struct(%r)' % self.__dict__
binaryArithmetic = {
'Arithmetic' : [
struct(operator='+', name='adding', mutatingName='add', firstArg='_', llvmName='add', kind='+'),
struct(operator='-', name='subtracting', mutatingName='subtract', firstArg='_', llvmName='sub', kind='-'),
struct(operator='*', name='multiplied', mutatingName='multiply', firstArg='by', llvmName='mul', kind='*'),
struct(operator='/', name='divided', mutatingName='divide', firstArg='by', llvmName='div', kind='/'),
],
'BinaryInteger' : [
struct(operator='%', name='remainder', mutatingName='formRemainder', firstArg='dividingBy', llvmName='rem', kind='/'),
],
}
binaryBitwise = [
struct(operator='&', name='bitwiseAnd', llvmName='and'),
struct(operator='|', name='bitwiseOr', llvmName='or'),
struct(operator='^', name='bitwiseXor', llvmName='xor'),
]
maskingShifts = [
struct(
operator='&>>', nonMaskingOperator='>>', description='right shift',
name='maskingShiftRight', llvmName=lambda s:['lshr','ashr'][s]),
struct(
operator='&<<', nonMaskingOperator='<<', description='left shift',
name='maskingShiftLeft', llvmName=lambda _: 'shl'),
]
IntMax = 'Int%s' % int_max_bits
UIntMax = 'UInt%s' % int_max_bits
}%
// FIXME(integers): remove these two aliases
/// The largest native signed integer type.
public typealias IntMax = ${IntMax}
/// The largest native unsigned integer type.
public typealias UIntMax = ${UIntMax}
infix operator &<< : BitwiseShiftPrecedence
infix operator &<<= : AssignmentPrecedence
infix operator &>> : BitwiseShiftPrecedence
infix operator &>>= : AssignmentPrecedence
//===----------------------------------------------------------------------===//
//===--- Bits for the Stdlib ----------------------------------------------===//
//===----------------------------------------------------------------------===//
//FIXME(integers): This should go in the stdlib separately, probably.
extension ExpressibleByIntegerLiteral
where Self : _ExpressibleByBuiltinIntegerLiteral {
/// Create an instance initialized to `value`.
@_transparent
public init(integerLiteral value: Self) {
self = value
}
}
//===----------------------------------------------------------------------===//
//===--- Arithmetic -------------------------------------------------------===//
//===----------------------------------------------------------------------===//
/// Declares methods backing binary arithmetic operatorssuch as `+`, `-` and
/// `*`and their mutating counterparts.
///
/// It provides a suitable basis for arithmetic on scalars such as integers and
/// floating point numbers.
///
/// Both mutating and non-mutating operations are declared in the protocol,
/// however only the mutating ones are required, as default implementations of
/// the non-mutating ones are provided by a protocol extension.
///
/// The `Magnitude` associated type is able to hold the absolute value of any
/// possible value of `Self`. Concrete types do not have to provide a typealias
/// for it, as it can be inferred from the `magnitude` property. This property
/// can be useful in operations that are simpler to implement in terms of
/// unsigned values, for example, printing a value of an integer, which is just
/// printing a '-' character in front of an absolute value.
///
/// Please note that for ordinary work, the `magnitude` property **should not**
/// be preferred to the `abs(_)` function, whose return value is of the same
/// type as its argument.
public protocol Arithmetic : Equatable, ExpressibleByIntegerLiteral {
// FIXME(integers): implement
init?<T : BinaryInteger>(exactly source: T)
// FIXME(ABI): should be just Arithmetic
associatedtype Magnitude : Equatable, ExpressibleByIntegerLiteral
var magnitude: Magnitude { get }
% for x in binaryArithmetic['Arithmetic']:
// defaulted using an in-place counterpart, but can be used as an
// optimization hook
func ${x.name}(${x.firstArg} rhs: Self) -> Self
// implementation hook
mutating func ${x.mutatingName}(${x.firstArg} rhs: Self)
% end
}
extension Arithmetic {
@_transparent
public init() {
self = 0
}
}
% for Protocol in binaryArithmetic:
extension ${Protocol} {
% for x in binaryArithmetic[Protocol]:
% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
public func ${x.name}(${x.firstArg} rhs: Self) -> Self {
var lhs = self
lhs.${x.mutatingName}(${callLabel}rhs)
return lhs
}
% end
}
% end
public protocol SignedArithmetic : Arithmetic {
func negated() -> Self
mutating func negate()
}
extension SignedArithmetic {
@_transparent
public func negated() -> Self {
return Self().subtracting(self)
}
@_transparent
public mutating func negate() {
self = negated()
}
}
//===----------------------------------------------------------------------===//
//===--- Arithmetic operators ---------------------------------------------===//
//===----------------------------------------------------------------------===//
% for Protocol in binaryArithmetic:
% for x in binaryArithmetic[Protocol]:
% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
@_transparent
public func ${x.operator} <T: ${Protocol}>(lhs: T, rhs: T) -> T {
return lhs.${x.name}(${callLabel}rhs)
}
@_transparent
public func ${x.operator}= <T: ${Protocol}>(lhs: inout T, rhs: T) {
lhs.${x.mutatingName}(${callLabel}rhs)
}
% end
% end
@_transparent
public prefix func - <T: SignedArithmetic>(x: T) -> T {
return x.negated()
}
//===----------------------------------------------------------------------===//
//===--- BinaryInteger ----------------------------------------------------===//
//===----------------------------------------------------------------------===//
public protocol BinaryInteger :
Comparable, Hashable, Arithmetic, CustomStringConvertible, Strideable {
static var isSigned: Bool { get }
// Dispatching through these puts less stress on the user reading
// the interface and error messages (and on the type checker) than
// does having many operator overloads.
func isEqual(to rhs: Self) -> Bool
func isLess(than rhs: Self) -> Bool
init?<T : FloatingPoint>(exactly source: T)
init<T : FloatingPoint>(_ source: T)
init<T : BinaryInteger>(_ source: T)
init<T : BinaryInteger>(extendingOrTruncating source: T)
init<T : BinaryInteger>(clamping source: T)
func word(at n: Int) -> UInt
var bitWidth : Int { get }
var minimumSignedRepresentationBitWidth: Int { get }
% for x in binaryArithmetic['BinaryInteger']:
// defaulted using an in-place counterpart, but can be used as an
// optimization hook
func ${x.name}(${x.firstArg} rhs: Self) -> Self
// implementation hook
mutating func ${x.mutatingName}(${x.firstArg} rhs: Self)
% end
func quotientAndRemainder(dividingBy rhs: Self) -> (Self, Self)
/// Returns `-1` if the value of `self` is negative, `1` if it's positive,
/// `0` otherwise.
func signum() -> Self
}
extension BinaryInteger {
public init?<T : FloatingPoint>(exactly source: T) {
// FIXME(integers): implement
fatalError()
}
public init<T : FloatingPoint>(_ source: T) {
// FIXME(integers): implement
fatalError()
}
public func signum() -> Self {
// FIXME(integers): implement
fatalError()
}
public var countRepresentedWords: Int {
return (self.bitWidth + ${word_bits} - 1) / ${word_bits}
}
public func quotientAndRemainder(dividingBy rhs: Self) -> (Self, Self) {
return (self.divided(by: rhs), self.remainder(dividingBy: rhs))
}
}
// Strideable conformance
extension BinaryInteger {
// FIXME(ABI): using Int as the return value is wrong.
@_transparent
public func distance(to other: Self) -> Int {
// FIXME(integers)
fatalError()
}
// FIXME(ABI): using Int as the return value is wrong.
@_transparent
public func advanced(by n: Int) -> Self {
// FIXME(integers)
fatalError()
}
}
//===----------------------------------------------------------------------===//
//===--- Homogeneous comparison -------------------------------------------===//
//===----------------------------------------------------------------------===//
@_transparent
public func == <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
return lhs.isEqual(to: rhs)
}
@_transparent
public func < <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
return lhs.isLess(than: rhs)
}
// FIXME(integers): these seem to be important for Int-backed enums
@_transparent
public func ==(lhs: Int, rhs: Int) -> Bool {
return lhs.isEqual(to: rhs)
}
@_transparent
public func < (lhs: Int, rhs: Int) -> Bool {
return lhs.isLess(than: rhs)
}
//===----------------------------------------------------------------------===//
//===--- Heterogeneous comparison -----------------------------------------===//
//===----------------------------------------------------------------------===//
@_transparent
public func == <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
return (lhs > 0) == (rhs > 0)
&& T(extendingOrTruncating: rhs) == lhs
&& U(extendingOrTruncating: lhs) == rhs
}
@_transparent
public func != <T : BinaryInteger, U : BinaryInteger>(lhs:T, rhs: U) -> Bool {
return !(lhs == rhs)
}
@_transparent
public func < <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
let lhsSign = lhs < 0 ? -1 : lhs > 0 ? 1 : 0
let rhsSign = rhs < 0 ? -1 : rhs > 0 ? 1 : 0
if lhsSign != rhsSign { return lhsSign < rhsSign }
// if we get here, lhs and rhs have the same sign. If they're
// negative, then T and U are both signed types, and one of them can
// represent values of the other type. Otherwise, lhs and rhs are
// positive, and one of T, U may be signed and the other unsigned.
// In this case, we can conceptually subtract 1 from the bitWidth of
// any signed type, and either the resulting bitWidths are the same
// or one can represent every value of the other.
let rT = T(extendingOrTruncating: rhs)
// Can we round-trip rhs through T?
if U(extendingOrTruncating: rT) == rhs {
return lhs < rT
}
return U(extendingOrTruncating: lhs) < rhs
}
@inline(__always)
public func <= <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
return !(rhs < lhs)
}
@inline(__always)
public func >= <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
return !(lhs < rhs)
}
@inline(__always)
public func > <T : BinaryInteger, U : BinaryInteger>(lhs: T, rhs: U) -> Bool {
return rhs < lhs
}
//===----------------------------------------------------------------------===//
//===--- Ambiguity breakers -----------------------------------------------===//
// These two versions of the operators are not ordered with respect to
// one another:
//
// <T : Comparable>(T, T) -> Bool
// <T : BinaryInteger, U : BinaryInteger>(T, U) -> Bool
//
// so we define:
//
// <T : BinaryInteger>(T, T) -> Bool
//===----------------------------------------------------------------------===//
@_transparent
public func != <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
return !(lhs == rhs)
}
@inline(__always)
public func <= <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
return !(rhs < lhs)
}
@inline(__always)
public func >= <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
return !(lhs < rhs)
}
@inline(__always)
public func > <T : BinaryInteger>(lhs: T, rhs: T) -> Bool {
return rhs < lhs
}
//===----------------------------------------------------------------------===//
//===--- FixedWidthInteger ------------------------------------------------===//
//===----------------------------------------------------------------------===//
public enum ArithmeticOverflow {
@_transparent
public init(_ overflow: Bool) { self = overflow ? .overflow : .none }
case none, overflow
}
public protocol FixedWidthInteger : BinaryInteger {
static var bitWidth : Int { get }
static var max: Self { get }
static var min: Self { get }
% for x in binaryArithmetic['Arithmetic']:
%{
comment = '''
/// Return a pair consisting of `self` {} `rhs`,
/// truncated to fit if necessary, and a flag indicating whether an
/// arithmetic overflow occurred.'''.format(x.operator) + ('''
///
/// - Precondition: `rhs != 0`''' if x.kind == '/' else '')
}%
${comment}
func ${x.name}WithOverflow(
${x.firstArg} rhs: Self
) -> (partialValue: Self, overflow: ArithmeticOverflow)
% end
% for x in binaryBitwise + maskingShifts:
func ${x.name}(_ rhs: Self) -> Self
% end
static func doubleWidthMultiply(_ lhs: Self, _ rhs: Self)
-> (high: Self, low: Magnitude)
static func doubleWidthDivide(
_ lhs: (high: Self, low: Magnitude), _ rhs: Self)
-> (quotient: Self, remainder: Self)
init(_truncatingBits bits: UInt)
var popcount: Int { get }
var leadingZeros: Int { get }
}
//===----------------------------------------------------------------------===//
//===--- Operators on FixedWidthInteger -----------------------------------===//
//===----------------------------------------------------------------------===//
@inline(__always)
public prefix func ~ <T: FixedWidthInteger>(x: T) -> T {
return 0 &- x &- 1
}
% for x in binaryBitwise:
@_transparent
public func ${x.operator} <T: FixedWidthInteger>(lhs: T, rhs: T) -> T {
return lhs.${x.name}(rhs)
}
@_transparent
public func ${x.operator}= <T: FixedWidthInteger>(lhs: inout T, rhs: T) {
lhs = lhs.${x.name}(rhs)
}
% end
% for x in maskingShifts:
@_transparent
public func ${x.operator} <T: FixedWidthInteger>(lhs: T, rhs: T) -> T {
return lhs.${x.name}(rhs)
}
@_transparent
public func ${x.operator}= <T: FixedWidthInteger>(lhs: inout T, rhs: T) {
lhs = lhs ${x.operator} rhs
}
@_transparent
public func ${x.operator} <
T: FixedWidthInteger, U: BinaryInteger
>(lhs: T, rhs: U) -> T {
return lhs.${x.name}(T(extendingOrTruncating: rhs))
}
@_transparent
public func ${x.operator}= <
T: FixedWidthInteger, U: BinaryInteger
>(lhs: inout T, rhs: U) {
lhs = lhs ${x.operator} rhs
}
@_transparent
public func ${x.nonMaskingOperator} <
T: FixedWidthInteger, U: BinaryInteger
>(lhs: T, rhs: U) -> T {
// FIXME(integers): uncomment once Int conforms to BinaryInteger
//let shift = rhs < -T.bitWidth ? -T.bitWidth
//: rhs > T.bitWidth ? T.bitWidth
//: Int(rhs)
//return lhs ${x.nonMaskingOperator} shift
fatalError()
}
//===----------------------------------------------------------------------===//
//=== "Smart ${x.description}", supporting overshifts and negative shifts -===//
//===----------------------------------------------------------------------===//
@_transparent
public func ${x.nonMaskingOperator} <
T: FixedWidthInteger
>(lhs: T, rhs: Int) -> T {
// FIXME(integers): uncomment once Int conforms to BinaryInteger
fatalError()
//let overshiftR = T.isSigned ? lhs &>> (T.bitWidth - 1) : 0
//let overshiftL: T = 0
//if _fastPath(rhs >= 0) {
//if _fastPath(rhs < T.bitWidth) {
//return lhs.${x.name}(T(extendingOrTruncating: rhs))
//}
//return overshift${'LR'['R' in x.name]}
//}
//if _slowPath(rhs <= -T.bitWidth) {
//return overshift${'RL'['R' in x.name]}
//}
//return lhs ${x.operator.translate(maketrans('<>', '><'))} -rhs
}
@_transparent
public func ${x.nonMaskingOperator}= <
T: FixedWidthInteger
>(lhs: inout T, rhs: T) {
lhs = lhs ${x.nonMaskingOperator} rhs
}
@_transparent
public func ${x.nonMaskingOperator}= <
T: FixedWidthInteger, U: BinaryInteger
>(lhs: inout T, rhs: U) {
lhs = lhs ${x.nonMaskingOperator} rhs
}
% end # maskingShifts
extension FixedWidthInteger {
public init<Other: BinaryInteger>(clamping source: Other) {
if _slowPath(source < Self.min) {
self = Self.min
}
else if _slowPath(source > Self.max) {
self = Self.max
}
else { self = Self(extendingOrTruncating: source) }
}
% for x in binaryArithmetic['Arithmetic']:
% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
@_transparent
// FIXME(integers): rename `rhs` to `other`
public mutating func ${x.mutatingName}(${x.firstArg} rhs: Self) {
let (result, _ /*overflow*/) = self.${x.name}WithOverflow(${callLabel}rhs)
// FIXME(integers): overflow check
//_assertCond(overflow == .none, "overflow in ${x.name}")
self = result
}
/// Return `self ${x.operator} rhs`. If an arithmetic overflow
/// occurs, the behavior is undefined.
///
/// Note: use this function to avoid the cost of overflow checking
/// when you are sure that the operation won't overflow.
@_transparent
public func unsafe${capitalize(x.name)}(rhs: Self) -> Self {
let (result, overflow) = self.${x.name}WithOverflow(${callLabel}rhs)
if (overflow != .none) {
if (_isDebugAssertConfiguration()) {
_preconditionFailure("overflow in unsafe${capitalize(x.name)}")
}
else {
Builtin.conditionallyUnreachable()
}
}
return result
}
% end
@_transparent
public mutating func formRemainder(dividingBy other: Self) {
// FIXME(integers): implement
fatalError()
}
@_transparent
public init<T : BinaryInteger>(extendingOrTruncating source: T) {
if Self.bitWidth <= ${word_bits} {
self = Self.init(_truncatingBits: source.word(at: 0))
}
else {
var result: Self = source < 0 ? ~0 : 0
// start with the most significant word
var n = source.countRepresentedWords
while n >= 0 {
// masking is OK here because this we have already ensured
// that Self.bitWidth > ${word_bits}. Not masking results in
// infinite recursion.
result &<<= ${word_bits}
result |= Self(_truncatingBits: source.word(at: n))
n -= 1
}
self = result
}
}
@_transparent
// FIXME(integers): give it a better name. _highBitIndex is **NOT** what it is
public // transparent
static var _highBitIndex: Self {
// FIXME(integers): uncomment once UInt conforms to BinaryInteger
//return Self.init(_truncatingBits: UInt(Self.bitWidth._storage) &- 1)
fatalError()
}
public var popcount: Int {
fatalError()
}
public static func doubleWidthDivide(
_ lhs: (high: Self, low: Magnitude), _ rhs: Self)
-> (quotient: Self, remainder: Self) {
fatalError()
}
}
% for x in [op for ops in binaryArithmetic.values() for op in ops]:
% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
% if x.kind != '/':
public func &${x.operator} <T: FixedWidthInteger>(lhs: T, rhs: T) -> T {
return lhs.${x.name}WithOverflow(${callLabel}rhs).partialValue
}
% end
% end
//===----------------------------------------------------------------------===//
//===--- UnsignedInteger --------------------------------------------------===//
//===----------------------------------------------------------------------===//
/// This protocol is an implementation detail of `UnsignedInteger`;
/// do not use it directly.
@_show_in_interface
public protocol _DisallowMixedSignArithmetic : BinaryInteger {
// Used to create a deliberate ambiguity in cases like UInt(1) +
// Int(1), which would otherwise compile due to the arithmetic
// operators defined for Strideable types (unsigned types are
// Strideable).
associatedtype _DisallowMixedSignArithmetic : SignedInteger = Int
}
public protocol UnsignedInteger : _DisallowMixedSignArithmetic, BinaryInteger {
associatedtype Magnitude : BinaryInteger
}
extension UnsignedInteger {
@_transparent
public var magnitude: Self { return self }
@_transparent
public static var isSigned: Bool { return false }
public var description: String {
// FIXME(integers): uncomment once Int conforms to BinaryInteger
fatalError()
//if self == 0 {
//return "0"
//}
//let ascii0 = 48
//var buf: [UnicodeScalar] = []
//var x = self
//repeat {
//let r = x % 10
//x /= 10
//buf.append(
//UnicodeScalar(
//ascii0 + Int(Word(extendingOrTruncating: r)._storage)))
//}
//while x != 0
//return String(buf.reversed().lazy.map { Character($0) })
}
}
extension UnsignedInteger where Self : FixedWidthInteger {
@_transparent
public init<T : BinaryInteger>(_ source: T) {
// FIXME(integers): uncomment checks
//_assertCond(
//source >= 0, "negative value \(source) not representable by \(Self.self)")
//let requiredBits = source.minimumSignedRepresentationBitWidth - 1
//_assertCond(
//requiredBits <= Self.bitWidth,
//"\(Self.self) cannot store all \(requiredBits) bits "
//+ "needed for unsigned representation of \(source)")
self.init(extendingOrTruncating: source)
}
@_transparent
public init?<T : BinaryInteger>(exactly source: T) {
// FIXME(integers): uncomment checks
//_assertCond(
//source >= 0, "negative value \(source) not representable by \(Self.self)")
let requiredBits = source.minimumSignedRepresentationBitWidth - 1
if requiredBits > Self.bitWidth {
return nil
}
self.init(extendingOrTruncating: source)
}
@_transparent
public static var max: Self {
return ~0
}
@_transparent
public static var min: Self {
return 0
}
}
//===----------------------------------------------------------------------===//
//===--- SignedInteger ----------------------------------------------------===//
//===----------------------------------------------------------------------===//
public protocol SignedInteger : BinaryInteger, SignedArithmetic {
associatedtype Magnitude : BinaryInteger
}
extension SignedInteger {
public var description: String {
let base = String(describing: magnitude)
return self < 0 ? "-" + base : base
}
@_transparent
public static var isSigned: Bool { return true }
}
extension SignedInteger where Self : FixedWidthInteger {
@_transparent
public init<T : BinaryInteger>(_ source: T) {
// FIXME(integers): uncomment checks
//let requiredBits = source.minimumSignedRepresentationBitWidth
//_assertCond(
//requiredBits <= Self.bitWidth,
//"\(Self.self) cannot store all \(requiredBits) bits "
//+ "needed for signed representation of \(source)")
self.init(extendingOrTruncating: source)
}
@_transparent
public init?<T : BinaryInteger>(exactly source: T) {
let requiredBits = source.minimumSignedRepresentationBitWidth
if requiredBits > Self.bitWidth {
return nil
}
self.init(extendingOrTruncating: source)
}
@_transparent
public static var max: Self {
return ~min
}
@_transparent
public static var min: Self {
return -1 &<< Self._highBitIndex
}
}
//===----------------------------------------------------------------------===//
//===--- Concrete FixedWidthIntegers --------------------------------------===//
//===----------------------------------------------------------------------===//
% for self_type in all_integer_types(word_bits):
% bits = self_type.bits
% signed = self_type.is_signed
% BuiltinName = self_type.builtin_name
% Self = self_type.stdlib_name
% OtherSelf = self_type.get_opposite_signedness().stdlib_name
% Unsigned = 'Signed' if signed else 'Unsigned'
% u = 's' if signed else 'u'
% U = 'U' if signed else ''
% z = 's' if signed else 'z'
public struct ${Self}
: FixedWidthInteger, ${Unsigned}Integer,
_ExpressibleByBuiltinIntegerLiteral {
@_transparent
public init(_builtinIntegerLiteral x: _MaxBuiltinIntegerType) {
_storage = Builtin.truncOrBitCast_${IntLiteral}_Int${bits}(x)
Builtin.condfail(
Builtin.cmp_ne_${IntLiteral}(
Builtin.${z}extOrBitCast_Int${bits}_${IntLiteral}(
_storage), x))
}
/// Construct a `${Self}` having the same memory representation as
/// the `${OtherSelf}` `bitPattern`. No range or overflow checking
/// occurs, and the resulting `${Self}` may not have the same numeric
/// value as `bitPattern`--it is only guaranteed to use the same
/// pattern of bits.
@_transparent
public init(bitPattern x: ${OtherSelf}) {
_storage = x._storage
}
public func isEqual(to rhs: ${Self}) -> Bool {
return Bool(Builtin.cmp_eq_Int${bits}(_storage, rhs._storage))
}
public func isLess(than rhs: ${Self}) -> Bool {
return Bool(Builtin.cmp_${u}lt_Int${bits}(_storage, rhs._storage))
}
% for x in [op for ops in binaryArithmetic.values() for op in ops]:
% callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
/// Return a pair consisting of `self` ${x.operator} `rhs`,
/// truncated to fit if necessary, and a flag indicating whether an
/// arithmetic overflow occurred.
@_transparent
public func ${x.name}WithOverflow(
${x.firstArg} rhs: ${Self}
) -> (partialValue: ${Self}, overflow: ArithmeticOverflow) {
% if x.kind == '/':
// No LLVM primitives for checking overflow of division
// operations, so we check manually.
if _slowPath(
rhs == 0
${'|| self == %s.min && rhs == -1' % Self if signed else ''}
) {
return (partialValue: self, overflow: .overflow)
}
let (newStorage, overflow) = (
Builtin.${u}${x.llvmName}_Int${bits}(self._storage, rhs._storage),
false._value)
% else:
let (newStorage, overflow)
= Builtin.${u}${x.llvmName}_with_overflow_Int${bits}(
self._storage, rhs._storage, false._value)
% end
return (
partialValue: ${Self}(newStorage),
overflow: ArithmeticOverflow(Bool(overflow)))
}
% end
@_transparent
public init(_ _storage: Builtin.Int${bits}) {
self._storage = _storage
}
% for x in binaryBitwise:
@_transparent
public func ${x.name}(_ rhs: ${Self}) -> ${Self} {
return ${Self}(
Builtin.${x.llvmName}_Int${bits}(self._storage, rhs._storage))
}
% end
% for x in maskingShifts:
@_transparent
public func ${x.name}(_ rhs: ${Self}) -> ${Self} {
let rhs_ = rhs & ${Self}._highBitIndex
return ${Self}(
Builtin.${x.llvmName(signed)}_Int${bits}(self._storage, rhs_._storage))
}
% end
@_transparent
public static var bitWidth : Int { return ${bits} }
public var bitWidth: Int { return ${bits} }
@_transparent
public var minimumSignedRepresentationBitWidth: Int {
% if signed:
let x = self < 0 ? ~self : self
return (x == 0) ? 1 : (${Self}.bitWidth - x.leadingZeros + 1)
% else:
return (self == 0) ? 1 : (${Self}.bitWidth - self.leadingZeros + 1)
% end
}
@_transparent
public var leadingZeros: Int {
fatalError()
// FIXME(integers): uncomment when Int conforms to Integer
//return Int(
//${Self}(
//Builtin.int_ctlz_Int${bits}(self._storage, false._value)
//)._lowUWord._storage)
}
@_transparent
public func word(at n: Int) -> UInt {
fatalError()
// FIXME(integers): uncomment when Int conforms to Integer
/*_precondition(n >= 0, "Negative word index")*/
/*if _fastPath(n < countRepresentedWords) {*/
/*let shift = UInt(n._storage) &* ${word_bits}*/
/*let bitWidth = UInt(self.bitWidth._storage)*/
/*_sanityCheck(shift < bitWidth)*/
/*return (self &>> ${Self}(_truncatingBits: shift))._lowUWord*/
/*}*/
/*return self < 0 ? ~0 : 0*/
}
@_transparent
public // transparent
var _lowUWord: UInt {
% truncOrExt = z + 'ext' if bits <= word_bits else 'trunc'
return UInt(
Builtin.${truncOrExt}OrBitCast_Int${bits}_Int${word_bits}(_storage)
)
}
@_transparent
public // transparent
init(_truncatingBits bits: UInt) {
// FIXME(integers): uncomment when Int conforms to Integer
fatalError()
/*% truncOrExt = 'zext' if bits > word_bits else 'trunc'*/
/*self.init(*/
/*Builtin.${truncOrExt}OrBitCast_Int${word_bits}_Int${bits}(bits._storage))*/
}
% if signed:
public typealias Magnitude = U${Self}
@_transparent
public var magnitude: U${Self} {
let base = U${Self}(_storage)
return self < 0 ? ~base + 1 : base
}
% end
% dbits = bits*2
public static func doubleWidthMultiply(_ self_: ${Self}, _ other: ${Self})
-> (high: ${Self}, low: ${Self}.Magnitude) {
% if bits > 64:
fatalError("${bits}-bit integer multiplication is not supported")
% else:
// FIXME(integers): uncomment when Int conforms to Integer
fatalError()
/*let lhs = Builtin.${z}ext_Int${bits}_Int${dbits}(self_._storage)*/
/*let rhs = Builtin.${z}ext_Int${bits}_Int${dbits}(other._storage)*/
/*let res = Builtin.mul_Int${dbits}(lhs, rhs)*/
/*let low = ${Self}.Magnitude(Builtin.truncOrBitCast_Int${dbits}_Int${bits}(res))*/
/*let shift: UInt8 = ${bits}*/
/*let shifted = Builtin.ashr_Int${dbits}(res,*/
/*Builtin.zextOrBitCast_Int8_Int${dbits}(shift._storage))*/
/*let high = ${Self}(Builtin.truncOrBitCast_Int${dbits}_Int${bits}(shifted))*/
/*return (high: high, low: low)*/
% end
}
% if bits > 8:
/// Creates an integer from its big-endian representation, changing the
/// byte order if necessary.
@_transparent
public init(bigEndian value: ${Self}) {
#if _endian(big)
self = value
#else
self = ${Self}(Builtin.int_bswap_${BuiltinName}(value._storage) )
#endif
}
/// Creates an integer from its little-endian representation, changing the
/// byte order if necessary.
@_transparent
public init(littleEndian value: ${Self}) {
#if _endian(little)
self = value
#else
self = ${Self}(Builtin.int_bswap_${BuiltinName}(value._storage) )
#endif
}
/// Returns the big-endian representation of the integer, changing the
/// byte order if necessary.
public var bigEndian: ${Self} {
#if _endian(big)
return self
#else
return ${Self}(Builtin.int_bswap_${BuiltinName}(_storage))
#endif
}
/// Returns the little-endian representation of the integer, changing the
/// byte order if necessary.
public var littleEndian: ${Self} {
#if _endian(little)
return self
#else
return ${Self}(Builtin.int_bswap_${BuiltinName}(_storage))
#endif
}
/// Returns the current integer with the byte order swapped.
public var byteSwapped: ${Self} {
return ${Self}(Builtin.int_bswap_${BuiltinName}(_storage))
}
% end
// Implementation details
public var _storage: Builtin.Int${bits}
% if self_type.is_word:
@_transparent
public // @testable
init(_ _v: Builtin.Word) {
% if BuiltinName == 'Int32':
self._storage = Builtin.truncOrBitCast_Word_Int32(_v)
% elif BuiltinName == 'Int64':
self._storage = Builtin.zextOrBitCast_Word_Int64(_v)
% end
}
@_transparent
public // @testable
var _builtinWordValue: Builtin.Word {
% if BuiltinName == 'Int32':
return Builtin.zextOrBitCast_Int32_Word(_storage)
% elif BuiltinName == 'Int64':
return Builtin.truncOrBitCast_Int64_Word(_storage)
% end
}
% end
}
%# end of concrete type: ${Self}
extension ${Self} : Hashable {
/// The hash value.
///
/// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`.
///
/// - Note: The hash value is not guaranteed to be stable across
/// different invocations of the same program. Do not persist the
/// hash value across program runs.
public var hashValue: Int {
@inline(__always)
get {
% if bits <= word_bits and signed:
// Sign extend the value.
return Int(self)
% elif bits <= word_bits and not signed:
// Sign extend the value.
return Int(${OtherSelf}(bitPattern: self))
% elif bits == word_bits * 2:
// We have twice as many bits as we need to return.
return
Int(extendingOrTruncating: self) ^
Int(extendingOrTruncating: self &>> 32)
% else:
_Unimplemented()
% end
}
}
}
// Create an ambiguity when indexing or slicing
// Range[OfStrideable]<${Self}> outside a generic context. See
// Range.swift for details.
extension ${Self} {
public typealias _DisabledRangeIndex = ${Self}
}
% for src_type in all_integer_types(word_bits):
% srcBits = src_type.bits
% srcSigned = src_type.is_signed
% Src = src_type.stdlib_name
// FIXME(integers): consider merging with
// FixedWidthInteger.init(_truncatingBits:)
% if should_define_truncating_bit_pattern_init(src_ty=src_type, dst_ty=self_type):
extension ${Self} {
/// Construct a `${Self}` having the same bitwise representation as
/// the least significant bits of the provided bit pattern.
///
/// No range or overflow checking occurs.
@_transparent
public init(truncatingBitPattern: ${Src}) {
let src = truncatingBitPattern._storage
% if self_type.bits == src_type.bits:
let dstNotWord = src
% else:
let dstNotWord = Builtin.trunc_Int${srcBits}_Int${bits}(src)
% end
self._storage = dstNotWord
}
}
% end
% end
% if signed:
// TODO: Consider removing the underscore.
/// Returns the argument and specifies that the value is not negative.
/// It has only an effect if the argument is a load or call.
@_transparent
public func _assumeNonNegative(_ x: ${Self}) -> ${Self} {
_sanityCheck(x >= 0)
return ${Self}(Builtin.assumeNonNegative_${BuiltinName}(x._storage))
}
% end
% end # end of concrete FixedWidthInteger section
//===----------------------------------------------------------------------===//
// FIXME(integers): Remove these operators in favour of the generic ones on
// Arithmetic
//===----------------------------------------------------------------------===//
// Operations with potentially-static overflow checking
//
// FIXME: must use condfail in these operators, rather than
// overflowChecked, pending <rdar://problem/16271923> so that we don't
// foil static checking for numeric overflows.
% for op, method, label in [
% ('+', 'adding', ''),
% ('*', 'multiplied', 'by: '),
% ('-','subtracting', ''),
% ('/', 'divided', 'by: '),
% ('%', 'remainder', 'dividingBy: ')
% ]:
@_transparent
public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
return lhs.${method}(${label}rhs)
}
% end
//===--- end of FIXME(integers) -------------------------------------------===//
// FIXME(integers): inline manually everywhere
public func numericCast<T : BinaryInteger, U : BinaryInteger>(_ x: T) -> U {
return U(x)
}
internal func _unsafePlus(_ lhs: Int, _ rhs: Int) -> Int {
#if INTERNAL_CHECKS_ENABLED
return lhs + rhs
#else
return lhs &+ rhs
#endif
}
internal func _unsafeMinus(_ lhs: Int, _ rhs: Int) -> Int {
#if INTERNAL_CHECKS_ENABLED
return lhs - rhs
#else
return lhs &- rhs
#endif
}
internal func _unsafeMultiply(_ lhs: Int, _ rhs: Int) -> Int {
#if INTERNAL_CHECKS_ENABLED
return lhs * rhs
#else
return lhs &* rhs
#endif
}