Files
swift-mirror/stdlib/core/FixedPoint.gyb
Anna Zaks b8c4019c2a Make Int's init() 128-bit-Int-proof.
Following Jordan suggestion to r8446, replace the current version of Int's
init() to make it 128 bit-proof.

Swift SVN r8531
2013-09-20 23:24:28 +00:00

222 lines
6.1 KiB
Swift

@# -*- mode: swift -*-
@# Ignore the following admonition; it applies to the resulting .swift file only
//// Automatically Generated From FixedPoint.gyb. Do Not Edit Directly ////
//// To regenerate: ////
//// ../../tools/gyb FixedPoint.gyb -o FixedPoint.swift ////
func overflowCheck<T: RandomAccessIndex>(arg: T, overflow: Bool) -> T {
alwaysTrap(overflow == false)
return arg
}
@{
#
# 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)
# Bit counts for all int types
allBits = [8, 16, 32, 64]
# Number of bits in the biggest int type
maxBits = max(allBits)
# Number of bits in an Int
intBits = 64
assert(intBits in allBits)
def maskBits(n):
"""Return an n-bit mask in hex"""
return hexify((1 << n) - 1)
def all_ints():
for bits in allBits:
for signed in False, True:
yield bits,signed
def int_name(bits, signed):
return ('' if signed else 'U') + 'Int' + str(bits)
}@
@for (bits, signed) in all_ints():
@ sign = 's' if signed else 'u'
@ Self = int_name(bits, signed)
@ ArrayBound = 'ArrayBound, ' if bits > 8 and bits < 128 else ''
struct ${Self} : BuiltinIntegerLiteralConvertible, IntegerLiteralConvertible,
${ArrayBound}ReplPrintable {
var value : Builtin.Int${bits}
init() {
var maxWidthZero : Int${str(maxBits)} = 0
value = ${'maxWidthZero.value' if bits == maxBits else ('Builtin.trunc_Int%d_Int%d(maxWidthZero.value)' % (maxBits, bits) )}
}
init [transparent] (v : Builtin.Int${bits}) {
value = v
}
static func [transparent] _convertFromBuiltinIntegerLiteral(val : Builtin.Int${maxBits}) -> ${Self} {
return ${Self}(${'val' if bits == maxBits else ('Builtin.trunc_Int%d_Int%d(val)' % (maxBits, bits) )})
}
typealias IntegerLiteralType = ${Self}
static func [transparent] convertFromIntegerLiteral(value : ${Self}) -> ${Self} {
return value
}
@if ArrayBound:
func _getBuiltinArrayBoundValue() -> Builtin.Int${bits} {
return value
}
typealias ArrayBoundType = ${Self}
func getArrayBoundValue() -> ${Self} {
return self
}
@else:
@end
func replPrint() {
print(${
'self' if bits == 64
else (('String' if bits > 64 else 'Int64' if signed else 'UInt64') + '(self)')})
}
@max = maskBits((bits - 1) if signed else bits)
// FIXME: these should be static vars when supported
static func max() -> ${Self} { return ${max} }
static func min() -> ${Self} { return ${'-%s-1' % max if signed else '0'} }
}
extension ${Self} : RandomAccessIndex, Hashable {
func __equal__(rhs: ${Self}) -> Bool {
return _getBool(Builtin.cmp_eq_Int${bits}(value, rhs.value))
}
func __less__(rhs: ${Self}) -> Bool {
return _getBool(Builtin.cmp_${sign}lt_Int${bits}(value, rhs.value))
}
func succ() -> ${Self} {
return self + 1
}
func pred() -> ${Self} {
return self - 1
}
func hashValue() -> Int {
@{
if bits <= intBits:
hashValue = 'Int(self)'
else:
# count of ints needed to represent this type
ints = (bits + intBits - 1) / intBits
# accumulate the high word
i = ints - 1
hashValue = 'Int(self >> %s)' % (i * intBits)
# accumulate middle words; these require shift + mask
while i > 1:
i = i-1
hashValue += ' ^ Int((self >> %d) & %s)' % (
intBits * i, maskBits(intBits))
# accumulate the low word; requires only a mask
hashValue += ' ^ Int(self & %s)' % maskBits(intBits)
}@
return ${hashValue}
}
typealias DistanceType = ${Self}
static func sub(lhs: ${Self}, rhs: ${Self}) -> (DistanceType, Bool) {
var tmp = Builtin.int_${sign}sub_with_overflow_Int${bits}(lhs.value, rhs.value)
return (${Self}(tmp.0), _getBool(tmp.1))
}
static func add(lhs: ${Self}, rhs: DistanceType) -> (${Self}, Bool) {
var tmp = Builtin.int_${sign}add_with_overflow_Int${bits}(lhs.value, rhs.value)
return (${Self}(tmp.0), _getBool(tmp.1))
}
static func mul(lhs: ${Self}, rhs: ${Self}) -> (${Self}, Bool) {
var tmp = Builtin.int_${sign}mul_with_overflow_Int${bits}(lhs.value, rhs.value)
return (${Self}(tmp.0), _getBool(tmp.1))
}
}
@if signed:
extension ${Self} : SignedNumber {
static func negate(rhs: ${Self}) -> (${Self}, Bool) { return ${Self}.sub(0, rhs) }
func isNegative() -> Bool { return self < 0 }
}
@end
// construction from other integer types
extension ${Self} {
@for (src_bits, src_signed) in all_ints():
@ That = int_name(src_bits, src_signed)
@ if Self != That:
init(v: ${That}) {
@if bits == src_bits:
value = v.value
@else:
value = Builtin.${
('trunc' if src_bits > bits
else 'sext' if src_signed
else 'zext')
}_Int${src_bits}_Int${bits}(v.value)
@end
}
@ end
@end
}
// Unary plus
func [prefix, transparent] +(rhs: ${Self}) -> ${Self} { return rhs }
// Operations with masking and non-masking versions
@for op,method in ('+','add'), ('*','mul'), ('-','sub'):
func [transparent] &${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
return ${Self}.${method}(lhs, rhs).0
}
func [transparent] ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
return overflowCheck(${Self}.${method}(lhs, rhs))
}
@end
// Bitwise negate
func [prefix, transparent] ~(rhs: ${Self}) -> ${Self} {
return rhs ^ ${maskBits(bits)}
}
@for op, name in (
@ ('/',sign+'div'), ('%',sign+'rem'),
@ ('<<','shl'), ('>>','ashr' if signed else 'lshr'),
@ ('&','and'), ('^','xor'), ('|','or')):
func [transparent] ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
return ${Self}(Builtin.${name}_Int${bits}(lhs.value, rhs.value))
}
@end
// Compound assignments
@for op in '+', '-', '*', '/', '%', '<<', '>>', '&', '|', '^':
func [assignment, transparent] ${op}=(lhs: [byref] ${Self}, rhs: ${Self}) {
lhs = lhs ${op} rhs
}
@end
@end # for bits in all_ints
// FIXME: rdar://14897572
// hack to make non-x86 architectures build at a reasonable speed
struct Hack14897572 { }
extension UInt32 {
init(_: Hack14897572) {
value = UInt32(0).value
}
}