//===--- FixedPoint.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 https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// %{ from SwiftIntTypes import all_integer_types, int_max_bits, should_define_truncating_bit_pattern_init from SwiftFloatingPointTypes import all_floating_point_types, getFtoIBounds # # Utility code for later in this template # def hexify(n): """Return a legible hex representation of n, using '_' separators """ z = '%X' % n l = len(z) r = [] while z: r.insert(0, z[-4:]) z = z[:-4] return '0x' + '_'.join(r) # Number of bits in the Builtin.Word type word_bits = int(CMAKE_SIZEOF_VOID_P) * 8 # Number of bits in integer literals. builtinIntLiteralBits = 2048 def maskBits(n): """Return an n-bit mask in hex""" return hexify((1 << n) - 1) IntMax = 'Int%s' % int_max_bits UIntMax = 'UInt%s' % int_max_bits }% /// The largest native signed integer type. public typealias IntMax = ${IntMax} /// The largest native unsigned integer type. public typealias UIntMax = ${UIntMax} /// This protocol is an implementation detail of `Integer`; do /// not use it directly. @_show_in_interface public protocol _Integer : _ExpressibleByBuiltinIntegerLiteral, ExpressibleByIntegerLiteral, CustomStringConvertible, Hashable, IntegerArithmetic, BitwiseOperations, _Incrementable { } /// A set of common requirements for Swift's integer types. public protocol Integer : _Integer, Strideable {} /// This protocol is an implementation detail of `SignedInteger`; /// do not use it directly. @_show_in_interface public protocol _SignedInteger : _Integer, SignedNumber { /// Represent this number using Swift's widest native signed integer /// type. func toIntMax() -> IntMax /// Convert from Swift's widest signed integer type, trapping on /// overflow. init(_: IntMax) } /// A set of common requirements for Swift's signed integer types. public protocol SignedInteger : _SignedInteger, Integer { /// Represent this number using Swift's widest native signed integer /// type. func toIntMax() -> IntMax /// Convert from Swift's widest signed integer type, trapping on /// overflow. init(_: IntMax) } extension SignedInteger { // FIXME(ABI)#29 : using Int as the return value is wrong. @_transparent public func distance(to other: Self) -> Int { return numericCast((numericCast(other) as IntMax) - numericCast(self)) } // FIXME(ABI)#30 : using Int as the argument is wrong. @_transparent public func advanced(by n: Int) -> Self { return numericCast((numericCast(self) as IntMax) + numericCast(n)) } } /// This protocol is an implementation detail of `UnsignedInteger`; /// do not use it directly. @_show_in_interface public protocol _DisallowMixedSignArithmetic : _Integer { // 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 } /// A set of common requirements for Swift's unsigned integer types. public protocol UnsignedInteger : _DisallowMixedSignArithmetic, Integer { /// Represent this number using Swift's widest native unsigned /// integer type. func toUIntMax() -> UIntMax /// Convert from Swift's widest unsigned integer type, trapping on /// overflow. init(_: UIntMax) } extension UnsignedInteger { // FIXME(ABI)#31 : using Int as the return value is wrong. @_transparent public func distance(to other: Self) -> Int { return numericCast((numericCast(other) as IntMax) - numericCast(self)) } // FIXME(ABI)#32 : using Int as the return value is wrong. @_transparent public func advanced(by n: Int) -> Self { return numericCast((numericCast(self) as IntMax) + numericCast(n)) } } /// Convert `x` to type `U`, trapping on overflow in -Onone and -O /// builds. /// /// Typically used to do conversion to any contextually-deduced /// integer type: /// /// func f(_ x: Int32) {} /// func g(_ x: Int64) { f(numericCast(x)) } public func numericCast< T : _SignedInteger, U : _SignedInteger >(_ x: T) -> U { return U(x.toIntMax()) } /// Convert `x` to type `U`, trapping on overflow in -Onone and -O /// builds. /// /// Typically used to do conversion to any contextually-deduced /// integer type: /// /// func f(_ x: UInt32) {} /// func g(_ x: UInt64) { f(numericCast(x)) } public func numericCast< T : UnsignedInteger, U : UnsignedInteger >(_ x: T) -> U { return U(x.toUIntMax()) } /// Convert `x` to type `U`, trapping on overflow in -Onone and -O /// builds. /// /// Typically used to do conversion to any contextually-deduced /// integer type: /// /// func f(_ x: UInt32) {} /// func g(_ x: Int64) { f(numericCast(x)) } public func numericCast< T : _SignedInteger, U : UnsignedInteger >(_ x: T) -> U { return U(UIntMax(x.toIntMax())) } /// Convert `x` to type `U`, trapping on overflow in -Onone and -O /// builds. /// /// Typically used to do conversion to any contextually-deduced /// integer type: /// /// func f(_ x: Int32) {} /// func g(_ x: UInt64) { f(numericCast(x)) } public func numericCast< T : UnsignedInteger, U : _SignedInteger >(_ x: T) -> U { return U(IntMax(x.toUIntMax())) } //===--- Loop over all integer types --------------------------------------===// % for self_ty in all_integer_types(word_bits): % bits = self_ty.bits % signed = self_ty.is_signed % (sign, ext) = ('s', 'sext') if signed else ('u', 'zext') % Self = self_ty.stdlib_name % BuiltinName = self_ty.builtin_name % OtherSelf = self_ty.get_opposite_signedness().stdlib_name % Article = 'An' if bits == 8 else 'A' % if self_ty.is_word: /// ${'An un' if sign == 'u' else 'A '}signed integer value type. /// /// On 32-bit platforms, `${Self}` is the same size as `${Self}32`, and /// on 64-bit platforms, `${Self}` is the same size as `${Self}64`. % else: /// ${Article} ${bits}-bit ${'un' if sign == 'u' else ''}signed integer value /// type. % end @_fixed_layout public struct ${Self} : ${'SignedInteger' if sign == 's' else 'UnsignedInteger'}, Comparable, Equatable { public // @testable var _value: Builtin.${BuiltinName} // FIXME: this declaration should be inferred. // Type checker refuses to use the default for // Int.Distance associated type /// Create an instance initialized to zero. @_transparent public init() { let maxWidthZero: IntMax = 0 self._value = Builtin.truncOrBitCast_Int${int_max_bits}_${BuiltinName}( maxWidthZero._value) } @_transparent public init(_ _v: Builtin.${BuiltinName}) { self._value = _v } @_transparent public init(_bits: Builtin.${BuiltinName}) { self._value = _bits } % if self_ty.is_word: @_transparent public // @testable init(_ _v: Builtin.Word) { % if BuiltinName == 'Int32': self._value = Builtin.truncOrBitCast_Word_Int32(_v) % elif BuiltinName == 'Int64': self._value = Builtin.zextOrBitCast_Word_Int64(_v) % end } @_transparent public // @testable var _builtinWordValue: Builtin.Word { % if BuiltinName == 'Int32': return Builtin.zextOrBitCast_Int32_Word(_value) % elif BuiltinName == 'Int64': return Builtin.truncOrBitCast_Int64_Word(_value) % end } % 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._value)) #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._value)) #endif } % end @_transparent public init(_builtinIntegerLiteral value: Builtin.Int${builtinIntLiteralBits}) { self = ${Self}(Builtin.s_to_${sign}_checked_trunc_Int${builtinIntLiteralBits}_${BuiltinName}(value).0) } /// Create an instance initialized to `value`. @_transparent public init(integerLiteral value: ${Self}) { self = value } % if bits > 8: /// 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}(_value)) #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}(_value)) #endif } % end % if bits > 8: /// Returns the current integer with the byte order swapped. public var byteSwapped: ${Self} { return ${Self}(Builtin.int_bswap_${BuiltinName}(_value)) } % end % max = maskBits((bits - 1) if signed else bits) @_transparent public static var max: ${Self} { return ${max} } @_transparent public static var min: ${Self} { return ${'-%s-1' % max if signed else '0'} } @_transparent public static var _sizeInBits: ${Self} { return ${bits} } public static var _sizeInBytes: ${Self} { return ${bits}/8 } } 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(truncatingBitPattern: self) ^ Int(truncatingBitPattern: self >> 32) % else: _Unimplemented() % end } } } extension ${Self} : CustomStringConvertible { /// A textual representation of `self`. public var description: String { % if signed: return _int64ToString(self.toIntMax()) % else: return _uint64ToString(self.toUIntMax()) % end } } // Operations that return an overflow bit in addition to a partial result, // helpful for checking for overflow when you want to handle it. extension ${Self} { % for Method, op in [('add', 'add'), ('subtract', 'sub'), ('multiply', 'mul')]: /// ${Method.capitalize()} `lhs` and `rhs`, returning a result and a /// `Bool` that is `true` iff the operation caused an arithmetic /// overflow. @_transparent public static func ${Method}WithOverflow(_ lhs: ${Self}, _ rhs: ${Self}) -> (${Self}, overflow: Bool) { let tmp = Builtin.${sign}${op}_with_overflow_${BuiltinName}(lhs._value, rhs._value, false._value) return (${Self}(tmp.0), Bool(tmp.1)) } % end % for Method, op in [('divide', 'div'), ('remainder', 'rem')]: /// Divide `lhs` and `rhs`, returning /// ${'a result' if op == 'div' else 'the remainder'} and a `Bool` /// that is `true` iff the operation caused an arithmetic overflow. @_transparent public static func ${Method}WithOverflow(_ lhs: ${Self}, _ rhs: ${Self}) -> (${Self}, overflow: Bool) { if rhs == 0 { return (0, true) } % if signed: if lhs == ${Self}.min && rhs == -1 { return (0, true) } % end // FIXME: currently doesn't detect overflow -- blocked by: // Need [su]{div,rem}_with_overflow IR let tmp = Builtin.${sign}${op}_${BuiltinName}(lhs._value, rhs._value) return (${Self}(tmp), false) } %end % (U, un) = ('','') if signed else ('U','un') /// Represent this number using Swift's widest native ${un}signed /// integer type. @_transparent public func to${U}IntMax() -> ${U}IntMax { return ${'self' if Self == U+'Int%s'%int_max_bits else U+'IntMax(self)'} } % if not signed: /// Explicitly convert to `IntMax`${', trapping on overflow (except in -Ounchecked builds)' if bits == int_max_bits else ''}. @_transparent public func toIntMax() -> IntMax { return IntMax(toUIntMax()) } % end } % if signed: extension ${Self} : SignedNumber {} % end %{ import gyb fixed_fixed_conversion_function = gyb.parse_template("fixed_fixed_conversion_function", """ % let src = value._value let result: (value: Builtin.${BuiltinName}, error: Builtin.Int1) % % if srcBits == bits and srcSign == sign: # Exact same size/signedness. result = (src, false._value) % % elif srcBits == bits: # Same size, switching signs. result = Builtin.${srcSign}_to_${sign}_checked_conversion_Int${srcBits}(src) % % elif srcBits > bits: # Larger input, check for truncation. result = Builtin.${srcSign}_to_${sign}_checked_trunc_Int${srcBits}_Int${bits}(src) % % elif srcSigned and not signed: # Smaller size input, signed going to unsigned. let (tmp, signError) = Builtin.s_to_u_checked_conversion_Int${srcBits}(src) result = (Builtin.${srcExt}_Int${srcBits}_Int${bits}(tmp), signError) % % else: # Smaller size input, unsigned to signed or unsigned to unsigned. result = (Builtin.${srcExt}_Int${srcBits}_Int${bits}(src), false._value) % end % % if not safelyConvertible: ${error_check} % end self._value = result.value """) }% % for src_ty in all_integer_types(word_bits): % srcBits = src_ty.bits % srcSigned = src_ty.is_signed % Src = src_ty.stdlib_name % (srcSign, srcExt) = ('s', 'sext') if srcSigned else ('u', 'zext') % safelyConvertible = (srcBits < bits and (srcSign == sign or signed)) or (srcBits == bits and srcSign == sign) extension ${Self} { @_transparent public init(_ value: ${Src}) { ${gyb.execute_template( fixed_fixed_conversion_function, error_check="Builtin.condfail(result.error)", **locals() ) } } % if safelyConvertible: @available(*, message: "Converting ${Src} to ${Self} will always succeed.") % end @_transparent public init?(exactly value: ${Src}) { ${gyb.execute_template( fixed_fixed_conversion_function, error_check="if Bool(result.error) == true { return nil }", **locals() ) } } % if should_define_truncating_bit_pattern_init(src_ty=src_ty, dst_ty=self_ty): /// 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._value % % if self_ty.bits == src_ty.bits: let dstNotWord = src % else: let dstNotWord = Builtin.trunc_Int${srcBits}_Int${bits}(src) % end % self._value = dstNotWord } % end } % end extension ${Self} { // Construction of integers from floating point numbers. % for src_type in all_floating_point_types(): % Src = src_type.stdlib_name % srcBits = src_type.bits % (lower, upper) = getFtoIBounds(floatBits=srcBits, intBits=int(bits), signed=signed) % if srcBits == 80: #if !os(Windows) && (arch(i386) || arch(x86_64)) % end /// Creates a new instance by rounding the given floating-point value toward /// zero. /// /// - Parameter other: A floating-point value. When `other` is rounded toward /// zero, the result must be within the range `${Self}.min...${Self}.max`. @_transparent public init(_ value: ${Src}) { _precondition(value.isFinite, "${Src} value cannot be converted to ${Self} because it is either infinite or NaN") _precondition(value > ${str(lower)}.0, "${Src} value cannot be converted to ${Self} because the result would be less than ${Self}.min") _precondition(value < ${str(upper)}.0, "${Src} value cannot be converted to ${Self} because the result would be greater than ${Self}.max") self._value = Builtin.fpto${sign}i_FPIEEE${srcBits}_${BuiltinName}(value._value) } /// Creates a ${Self} whose value is `value` /// if no rounding is necessary, nil otherwise. @inline(__always) public init?(exactly value: ${Src}) { self._value = Builtin.fpto${sign}i_FPIEEE${srcBits}_${BuiltinName}(value._value) if ${Src}(self) != value { return nil } } % if srcBits == 80: #endif % end % end /// 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: ${OtherSelf}) { self._value = bitPattern._value } } // Operations with potentially-static overflow checking // // FIXME: must use condfail in these operators, rather than // overflowChecked, pending so that we don't // foil static checking for numeric overflows. % for op, method in ('+','add'), ('*','mul'), ('-','sub'): @_transparent public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} { let (result, error) = Builtin.${sign}${method}_with_overflow_${BuiltinName}( lhs._value, rhs._value, true._value) // return overflowChecked((${Self}(result), Bool(error))) Builtin.condfail(error) return ${Self}(result) } % end % for op, inst in [('/', 'div'), ('%', 'rem')]: @_transparent public func ${op}(lhs: ${Self}, rhs: ${Self}) -> ${Self} { Builtin.condfail((rhs == 0)._value) % if signed: Builtin.condfail(((lhs == ${Self}.min) && (rhs == -1))._value) % end // FIXME: currently doesn't detect overflow -- blocked by: // Need [su]{div,rem}_with_overflow IR let tmp = Builtin.${sign}${inst}_${BuiltinName}(lhs._value, rhs._value) return ${Self}(tmp) } %end // Bitwise negate /// Returns the inverse of the bits set in the argument. /// /// - SeeAlso: `BitwiseOperations` @_transparent public prefix func ~ (rhs: ${Self}) -> ${Self} { let mask = ${Self}.subtractWithOverflow(0, 1).0 return ${Self}(Builtin.xor_${BuiltinName}(rhs._value, mask._value)) } % for op, name, comment in ( % ('==', 'eq', 'the two arguments have equal values'), % ('!=', 'ne', 'the two arguments have unequal values'), % ('<', sign + 'lt', 'the first argument is less than the second argument'), % ('<=', sign + 'le', 'the first argument is less than or equal to the second argument'), % ('>', sign + 'gt', 'the first argument is greater than the second argument'), % ('>=', sign + 'ge', 'the first argument is greater than or equal to the second argument'), % ): /// Returns a Boolean value that indicates whether /// ${comment}. /// /// - SeeAlso: `Equatable`, `Comparable` @_transparent public func ${op} (lhs: ${Self}, rhs: ${Self}) -> Bool { return Bool(Builtin.cmp_${name}_${BuiltinName}(lhs._value, rhs._value)) } % end % for op, name in (('<<','shl'), ('>>','ashr' if signed else 'lshr')): @_transparent public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} { % if signed: _precondition(U${Self}(rhs) < U${Self}._sizeInBits, "shift amount is larger than type size in bits") % else: _precondition(rhs < ${Self}._sizeInBits, "shift amount is larger than type size in bits") % end return ${Self}(Builtin.${name}_${BuiltinName}(lhs._value, rhs._value)) } % end % for op, name, comment in ( % ('&', 'and', 'intersection of bits set in'), % ('^', 'xor', 'bits that are set in exactly one of'), % ('|', 'or', 'union of bits set in'), % ): /// Returns the ${comment} the two arguments. /// /// - SeeAlso: `BitwiseOperations` @_transparent public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} { return ${Self}(Builtin.${name}_${BuiltinName}(lhs._value, rhs._value)) } /// Calculates the ${comment} the two arguments /// and stores the result in the first argument. /// /// - SeeAlso: `BitwiseOperations` @_transparent public func ${op}=(lhs: inout ${Self}, rhs: ${Self}) { lhs = lhs ${op} rhs } % end // Bitwise operations extension ${Self} : BitwiseOperations { /// The empty bitset of type `${Self}`. @_transparent public static var allZeros: ${Self} { return 0 } } // Compound assignments % for op in '+', '-', '*', '<<', '>>': @_transparent public func ${op}=(lhs: inout ${Self}, rhs: ${Self}) { lhs = lhs ${op} rhs } % 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} } // Prefix and postfix increment and decrement. @_transparent @available(*, unavailable, message: "it has been removed in Swift 3") @discardableResult public prefix func ++ (x: inout ${Self}) -> ${Self} { x = x + 1 return x } @_transparent @available(*, unavailable, message: "it has been removed in Swift 3") @discardableResult public postfix func ++ (x: inout ${Self}) -> ${Self} { let ret = x x = x + 1 return ret } @_transparent @available(*, unavailable, message: "it has been removed in Swift 3") @discardableResult public prefix func -- (x: inout ${Self}) -> ${Self} { x = x - 1 return x } @_transparent @available(*, unavailable, message: "it has been removed in Swift 3") @discardableResult public postfix func -- (x: inout ${Self}) -> ${Self} { let ret = x x = x - 1 return ret } % 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._value)) } % end % end % fixedBitWidths = [2**x for x in range(3, 8) if 2**x <= 2 * word_bits] % for bits in fixedBitWidths: @_transparent public func _leadingZeros(_ x: Builtin.Int${bits}) -> Builtin.Int${bits} { return Builtin.int_ctlz_Int${bits}(x, true._value) } % end //===--- End loop over all integer types ----------------------------------===// 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 } @available(*, unavailable, renamed: "Integer") public typealias IntegerType = Integer @available(*, unavailable, renamed: "SignedInteger") public typealias SignedIntegerType = SignedInteger @available(*, unavailable, renamed: "UnsignedInteger") public typealias UnsignedIntegerType = UnsignedInteger // ${'Local Variables'}: // eval: (read-only-mode 1) // End: