//===--- FixedPoint.swift.gyb ---------------------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 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 // //===----------------------------------------------------------------------===// %{ from SwiftIntTypes import * # # 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 # FIXME: checked and unchecked conversions of Word types CastFromWord = 'zextOrBitCast_Word_Int64' if word_bits==64 else 'truncOrBitCast_Word_Int32' CastToWord = 'truncOrBitCast_Int64_Word' if word_bits==64 else 'zextOrBitCast_Int32_Word' def maskBits(n): """Return an n-bit mask in hex""" return hexify((1 << n) - 1) }% public typealias IntMax = Int${int_max_bits} public typealias UIntMax = UInt${int_max_bits} /// This protocol is an implementation detail of `IntegerType`; do /// not use it directly. /// /// Its requirements are inherited by `IntegerType` and thus must /// be satisfied by types conforming to that protocol. public protocol _IntegerType : _BuiltinIntegerLiteralConvertible, IntegerLiteralConvertible, Printable, Hashable, IntegerArithmeticType, BitwiseOperationsType, _Incrementable { } /// A set of common requirements for Swift's integer types. public protocol IntegerType : _IntegerType, RandomAccessIndexType { } /// This protocol is an implementation detail of `SignedIntegerType`; /// do not use it directly. /// /// Its requirements are inherited by `SignedIntegerType` and thus /// must be satisfied by types conforming to that protocol. public protocol _SignedIntegerType : _IntegerType, SignedNumberType { /// 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 SignedIntegerType : _SignedIntegerType, IntegerType { } /// This protocol is an implementation detail of `SignedIntegerType`; /// do not use it directly. /// /// Its requirements are inherited by `SignedIntegerType` and thus /// must be satisfied by types conforming to that protocol. public protocol _UnsignedIntegerType : _IntegerType { /// 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) } /// A set of common requirements for Swift's unsigned integer types. public protocol UnsignedIntegerType : _UnsignedIntegerType, IntegerType { } public func numericCast< T : _SignedIntegerType, U : _SignedIntegerType >(x: T) -> U { return U(x.toIntMax()) } public func numericCast< T : _UnsignedIntegerType, U : _UnsignedIntegerType >(x: T) -> U { return U(x.toUIntMax()) } public func numericCast< T : _SignedIntegerType, U : _UnsignedIntegerType >(x: T) -> U { return U(UIntMax(x.toIntMax())) } public func numericCast< T : _UnsignedIntegerType, U : _SignedIntegerType >(x: T) -> U { return U(IntMax(x.toUIntMax())) } % 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 public struct ${Self} : ${'SignedIntegerType' if sign == 's' else 'UnsignedIntegerType'} { public var value: Builtin.${BuiltinName} // FIXME: this declaration should be inferred. // Type checker refuses to use the default for // Int.Distance associated type /// A type that can represent the number of steps between pairs of /// values. public typealias Distance = Int /// Create an instance initialized to zero. @transparent public init() { var maxWidthZero: IntMax = 0 value = Builtin.truncOrBitCast_Int${int_max_bits}_${BuiltinName}( maxWidthZero.value) } @transparent public init(_ v: Builtin.${BuiltinName}) { value = v } /// Create an instance initialized to `value`. @transparent public init(_ value: ${Self}) { self = value } % if bits > 8: /// Creates an integer from its big-endian representation, changing the /// byte order if necessary. @transparent public init(bigEndian value: ${Self}) { #if arch(i386) || arch(x86_64) || arch(arm) || arch(arm64) self = ${Self}(Builtin.int_bswap_${BuiltinName}(value.value) ) #else _UnsupportedArchitectureError() #endif } /// Creates an integer from its little-endian representation, changing the /// byte order if necessary. @transparent public init(littleEndian value: ${Self}) { #if arch(i386) || arch(x86_64) || arch(arm) || arch(arm64) self = value #else _UnsupportedArchitectureError() #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 arch(i386) || arch(x86_64) || arch(arm) || arch(arm64) return ${Self}(Builtin.int_bswap_${BuiltinName}(value) ) #else _UnsupportedArchitectureError() #endif } /// Returns the little-endian representation of the integer, changing the /// byte order if necessary. public var littleEndian: ${Self} { #if arch(i386) || arch(x86_64) || arch(arm) || arch(arm64) return self #else _UnsupportedArchitectureError() #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} } } extension ${Self} : Hashable { public var hashValue: Int { % if bits < word_bits: return Int(Builtin.sextOrBitCast_${BuiltinName}_Word(self.value)) % elif self_ty.is_word: return Int(self.value) % elif bits == word_bits: return Int(Builtin.${CastToWord}(self.value)) % elif bits == word_bits * 2: return Int(truncatingBitPattern: self) ^ Int(truncatingBitPattern: self >> 32) % else: _Unimplemented() % end } } extension ${Self} : Printable { public var description: String { % if signed: return _int64ToString(self.toIntMax()) % else: return _uint64ToString(self.toUIntMax()) % end } } // When ${Self} is used as an index, there are always bounds---more // restrictive than the full range of ${Self}---against which we're // not able to check. Overflows are not useful indicators of // precondition violations in this context. Therefore, we use masked // arithmetic in this conformance, and we need to be be sure that // generic implementations of the arithmetic operators for // RandomAccessIndexType's are all shadowed by more-specific // implementations that *do* check for overflows. @transparent extension ${Self} : RandomAccessIndexType { // HACK: Disable indexing and slicing Ranges of IntegerType types // outside of a generic context. See the implementation of Range // for details of how this works. typealias _DisabledRangeIndex = ${Self} /// Returns the next consecutive value after `self`. /// /// Requires: the next value is representable. @transparent public func successor() -> ${Self} { return self &+ 1 } /// Returns the previous consecutive value before `self`. /// /// Requires: the previous value is representable. @transparent public func predecessor() -> ${Self} { return self &- 1 } /// Return the minimum number of applications of `successor` or /// `predecessor` required to reach `other` from `self`. /// /// Complexity: O(1). @transparent public func distanceTo(other: ${Self}) -> ${Self}.Distance { return numericCast((numericCast(other) as IntMax) &- numericCast(self)) } /// Return `self` offset by `n` steps. /// /// :returns: If `n > 0`, the result of applying `successor` to /// `self` `n` times. If `n < 0`, the result of applying /// `predecessor` to `self` `-n` times. Otherwise, `self`. /// /// Complexity: O(1) @transparent public func advancedBy(amount: ${Self}.Distance) -> ${Self} { return numericCast((numericCast(self) as IntMax) &+ numericCast(amount)) } } // 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) { var 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 var 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: @transparent extension ${Self} : SignedNumberType {} % end %# FIXME: checked conversions of Word types // construction from other integer types @transparent extension ${Self} { % for src_ty in all_integer_types(word_bits): % srcBits = src_ty.bits % srcSigned = src_ty.is_signed % Src = src_ty.stdlib_name % srcBuiltinName = src_ty.builtin_name % (srcSign, srcExt) = ('s', 'sext') if srcSigned else ('u', 'zext') % if Self != Src: public init(_ v: ${Src}) { % % if srcBuiltinName == 'Word': var srcNotWord = Builtin.${CastFromWord}(v.value) % else: var srcNotWord = v.value % end % % if srcBits == bits and srcSign == sign: var dstNotWord = srcNotWord % % elif srcBits == bits: var tmp = Builtin.${srcSign}_to_${sign}_checked_conversion_Int${srcBits}(srcNotWord) Builtin.condfail(tmp.1) var dstNotWord = tmp.0 % % elif srcBits > bits: var tmp = Builtin.${srcSign}_to_${sign}_checked_trunc_Int${srcBits}_Int${bits}(srcNotWord) Builtin.condfail(tmp.1) var dstNotWord = tmp.0 % % elif srcSigned and not signed: var tmp = Builtin.s_to_u_checked_conversion_Int${srcBits}(srcNotWord) Builtin.condfail(tmp.1) var dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(tmp.0) % % else: var dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(srcNotWord) % end % % if BuiltinName == 'Word': value = Builtin.${CastToWord}(dstNotWord) % else: value = dstNotWord % end } % end % 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}) { % % if srcBuiltinName == 'Word': let srcNotWord = Builtin.${CastFromWord}(truncatingBitPattern.value) % else: let srcNotWord = truncatingBitPattern.value % end % % if self_ty.bits == src_ty.bits: let dstNotWord = srcNotWord % else: let dstNotWord = Builtin.trunc_Int${srcBits}_Int${bits}(srcNotWord) % end % % if BuiltinName == 'Word': value = Builtin.${CastToWord}(dstNotWord) % else: value = dstNotWord % end } % 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}) { 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 var tmp = Builtin.${sign}${inst}_${BuiltinName}(lhs.value, rhs.value) return ${Self}(tmp) } %end // Bitwise negate @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 in ( % ('==','eq'), ('!=','ne'), % ('<',sign+'lt'), ('<=',sign+'le'), % ('>',sign+'gt'), ('>=',sign+'ge')): @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 in (('&','and'), ('^','xor'), ('|','or')): @transparent public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} { return ${Self}(Builtin.${name}_${BuiltinName}(lhs.value, rhs.value)) } % end // bitwise operations @transparent extension ${Self} : BitwiseOperationsType { public static var allZeros: ${Self} { return 0 } } // Compound assignments % for op in '+', '-', '*', '<<', '>>', '&', '|', '^': @transparent public func ${op}=(inout lhs: ${Self}, rhs: ${Self}) { lhs = lhs ${op} rhs } % end // Prefix and postfix increment and decrement. // We already have generic versions of these, but when compiling // -Onone we are unable to devirtualize the generic call, which // results in worse performance than we would like for these simple // operations (tracked by ). @transparent public prefix func ++ (inout x: ${Self}) -> ${Self} { x = x + 1 return x } @transparent public postfix func ++ (inout x: ${Self}) -> ${Self} { var ret = x x = x + 1 return ret } @transparent public prefix func -- (inout x: ${Self}) -> ${Self} { x = x - 1 return x } @transparent public postfix func -- (inout x: ${Self}) -> ${Self} { var ret = x x = x - 1 return ret } % end # for bits in allInts public typealias Word = Int public typealias UWord = UInt // ${'Local Variables'}: // eval: (read-only-mode 1) // End: