SPB Git

spb/os-vault Public

Self-custody, multi-chain crypto wallet for macOS. One recovery phrase, six chain families, zero API keys — nothing leaves your Mac.

Swift 96% Shell 3.4% Makefile 0.6%
29.8 KB · 786 lines swift
Raw Blame History
1import Accelerate.vecLib2import Foundation34public typealias UInt1X = FixedWidthInteger & BinaryInteger & UnsignedInteger & Codable56public struct UInt2X<Word: UInt1X>: Hashable, Codable {7    public typealias IntegerLiteralType = UInt648    public typealias Magnitude = UInt2X9    public typealias Words = [Word.Words.Element]10    public typealias Stride = Int11    // internally it is least significant word first to make Accelerate happy12    public var lo: Word = 013    public var hi: Word = 014    public init(hi: Word, lo: Word) { (self.hi, self.lo) = (hi, lo) }15    public init(_ source: UInt2X) { (hi, lo) = (source.hi, source.lo) }16}1718// Swift bug?19// auto-generated == incorrectly reports20// UInt2X(hi:nonzero, lo:0) == 0 is true21public extension UInt2X {22    static func == (_ lhs: UInt2X, _ rhs: UInt2X) -> Bool {23        lhs.hi == rhs.hi && lhs.lo == rhs.lo24    }25}2627extension UInt2X: ExpressibleByIntegerLiteral {28    public static var isSigned: Bool { false }29    public static var bitWidth: Int {30        Word.bitWidth * 231    }3233    public static var min: UInt2X { UInt2X(hi: Word.min, lo: Word.min) }34    public static var max: UInt2X { UInt2X(hi: Word.max, lo: Word.max) }35    public init(_ source: Word) {36        (hi, lo) = (0, source)37    }3839    public init?<T>(exactly source: T) where T: BinaryInteger {40        guard source.bitWidth <= UInt2X.bitWidth || source <= T(UInt2X.max) else {41            return nil42        }43        self.init(source)44    }4546    public init<T>(_ source: T) where T: BinaryInteger {47        hi = Word(source.magnitude >> Word.bitWidth)48        lo = Word(truncatingIfNeeded: source.magnitude)49    }5051    public init?<T>(exactly source: T) where T: BinaryFloatingPoint {52        print("\(#line)", source)53        guard source.sign != .minus else { return nil }54        guard source.exponent < UInt2X.bitWidth else { return nil }55        self = UInt2X(source.significandBitPattern | (1 << T.significandBitCount))56        self <<= Int(source.exponent) - T.significandBitCount57    }5859    public init<T>(_ source: T) where T: BinaryFloatingPoint {60        guard let result = UInt2X(exactly: source) else {61            fatalError("Not enough bits to represent a signed value")62        }63        self = result64    }6566    // alway succeeds67    public init<T: BinaryInteger>(truncatingIfNeeded source: T) {68        hi = Word(truncatingIfNeeded: source.magnitude >> Word.bitWidth)69        lo = Word(truncatingIfNeeded: source.magnitude)70    }7172    // alway succeeds73    public init<T: BinaryInteger>(clamping source: T) {74        self = UInt2X(exactly: source) ?? UInt2X.max75    }7677    public init(integerLiteral value: IntegerLiteralType) {78        self.init(value)79    }80}8182// Comparable83extension UInt2X: Comparable {84    public static func < (lhs: UInt2X, rhs: UInt2X) -> Bool {85        lhs.hi < rhs.hi ? true : lhs.hi == rhs.hi && lhs.lo < rhs.lo86    }87}8889// Accelerate support90// careful with the significance order.  Accerelate is least significant first.91#if os(macOS) || os(iOS)92    import Accelerate93#endif94public enum Int2XConfig {95    #if os(macOS) || os(iOS)96        public static var useAccelerate = true97    #else98        public static let useAccelerate = false99    #endif100}101102// numeric103extension UInt2X: Numeric {104    public var magnitude: UInt2X {105        self106    }107108    // unary operators109    public static prefix func ~ (_ value: UInt2X) -> UInt2X {110        UInt2X(hi: ~value.hi, lo: ~value.lo)111    }112113    public static prefix func + (_ value: UInt2X) -> UInt2X {114        value115    }116117    public static prefix func - (_ value: UInt2X) -> UInt2X {118        ~value &+ 1 // two's complement119    }120121    // additions122    public func addingReportingOverflow(_ other: UInt2X) -> (partialValue: UInt2X, overflow: Bool) {123        guard self != 0 else { return (other, false) }124        guard other != 0 else { return (self, false) }125        #if os(macOS)126            if Int2XConfig.useAccelerate {127                // print("line \(#line):Accelerated! \(UInt2X.self)(\(self)).addingReportingOverflow(\(other))")128                switch self {129                case is UInt128:130                    var a = unsafeBitCast((self, vU128()), to: vU256.self)131                    var b = unsafeBitCast((other, vU128()), to: vU256.self)132                    var ab = vU256()133                    vU256Add(&a, &b, &ab)134                    let (r, o) = unsafeBitCast(ab, to: (UInt2X, UInt2X).self)135                    return (r, o != 0)136                case is UInt256:137                    var a = unsafeBitCast((self, vU256()), to: vU512.self)138                    var b = unsafeBitCast((other, vU256()), to: vU512.self)139                    var ab = vU512()140                    vU512Add(&a, &b, &ab)141                    let (r, o) = unsafeBitCast(ab, to: (UInt2X, UInt2X).self)142                    return (r, o != 0)143                case is UInt512:144                    var a = unsafeBitCast((self, vU512()), to: vU1024.self)145                    var b = unsafeBitCast((other, vU512()), to: vU1024.self)146                    var ab = vU1024()147                    vU1024Add(&a, &b, &ab)148                    let (r, o) = unsafeBitCast(ab, to: (UInt2X, UInt2X).self)149                    return (r, o != 0)150                default:151                    break152                }153            }154        #endif155        var of = false156        let (lv, lf) = lo.addingReportingOverflow(other.lo)157        var (hv, uo) = hi.addingReportingOverflow(other.hi)158        if lf {159            (hv, of) = hv.addingReportingOverflow(1)160        }161        return (partialValue: UInt2X(hi: hv, lo: lv), overflow: uo || of)162    }163164    public func addingReportingOverflow(_ other: Word) -> (partialValue: UInt2X, overflow: Bool) {165        return addingReportingOverflow(UInt2X(hi: 0, lo: other))166    }167168    public static func &+ (_ lhs: UInt2X, _ rhs: UInt2X) -> UInt2X {169        lhs.addingReportingOverflow(rhs).partialValue170    }171172    public static func + (_ lhs: UInt2X, _ rhs: UInt2X) -> UInt2X {173        precondition(~lhs >= rhs, "\(lhs) + \(rhs): Addition overflow!")174        return lhs &+ rhs175    }176177    public static func + (_ lhs: UInt2X, _ rhs: Word) -> UInt2X {178        lhs + UInt2X(hi: 0, lo: rhs)179    }180181    public static func + (_ lhs: Word, _ rhs: UInt2X) -> UInt2X {182        UInt2X(hi: 0, lo: lhs) + rhs183    }184185    public static func += (lhs: inout UInt2X, rhs: UInt2X) {186        lhs = lhs + rhs187    }188189    public static func += (lhs: inout UInt2X, rhs: Word) {190        lhs = lhs + rhs191    }192193    // subtraction194    public func subtractingReportingOverflow(_ other: UInt2X) -> (partialValue: UInt2X, overflow: Bool) {195        guard self != other else { return (0, false) }196        guard self != 0 else { return (-other, false) }197        guard other != 0 else { return (+self, false) }198        #if os(macOS)199            if Int2XConfig.useAccelerate {200                // print("line \(#line):Accelerated! \(UInt2X.self)(\(self)).subtractingReportingOverflow(\(other))")201                switch self {202                case is UInt128:203                    var a = unsafeBitCast((self, vU128()), to: vU256.self)204                    var b = unsafeBitCast((other, vU128()), to: vU256.self)205                    var ab = vU256()206                    vU256Sub(&a, &b, &ab)207                    let (r, o) = unsafeBitCast(ab, to: (UInt2X, UInt2X).self)208                    return (r, o != 0)209                case is UInt256:210                    var a = unsafeBitCast((self, vU256()), to: vU512.self)211                    var b = unsafeBitCast((other, vU256()), to: vU512.self)212                    var ab = vU512()213                    vU512Sub(&a, &b, &ab)214                    let (r, o) = unsafeBitCast(ab, to: (UInt2X, UInt2X).self)215                    return (r, o != 0)216                case is UInt512:217                    var a = unsafeBitCast((self, vU512()), to: vU1024.self)218                    var b = unsafeBitCast((other, vU512()), to: vU1024.self)219                    var ab = vU1024()220                    vU1024Sub(&a, &b, &ab)221                    let (r, o) = unsafeBitCast(ab, to: (UInt2X, UInt2X).self)222                    return (r, o != 0)223                default:224                    break225                }226            }227        #endif228        return addingReportingOverflow(-other)229    }230231    public func subtractingReportingOverflow(_ other: Word) -> (partialValue: UInt2X, overflow: Bool) {232        return subtractingReportingOverflow(UInt2X(hi: 0, lo: other))233    }234235    public static func &- (_ lhs: UInt2X, _ rhs: UInt2X) -> UInt2X {236        lhs.subtractingReportingOverflow(rhs).partialValue237    }238239    public static func - (_ lhs: UInt2X, _ rhs: UInt2X) -> UInt2X {240        precondition(lhs >= rhs, "\(lhs) - \(rhs): Subtraction overflow!")241        return lhs &- rhs242    }243244    public static func - (_ lhs: UInt2X, _ rhs: Word) -> UInt2X {245        lhs - UInt2X(hi: 0, lo: rhs)246    }247248    public static func - (_ lhs: Word, _ rhs: UInt2X) -> UInt2X {249        UInt2X(hi: 0, lo: lhs) - rhs250    }251252    public static func -= (lhs: inout UInt2X, rhs: UInt2X) {253        lhs = lhs - rhs254    }255256    public static func -= (lhs: inout UInt2X, rhs: Word) {257        lhs = lhs - rhs258    }259260    // multiplication261    public func multipliedHalfWidth(by other: Word) -> (high: UInt2X, low: Magnitude) {262        guard self != 0 else { return (0, 0) }263        guard other != 0 else { return (0, 0) }264        let l = lo.multipliedFullWidth(by: other)265        let h = hi.multipliedFullWidth(by: other)266        let r0 = Word(l.low)267        let (r1, o1) = Word(h.low).addingReportingOverflow(Word(l.high))268        let r2 = Word(h.high) &+ (o1 ? 1 : 0) // will not overflow269        return (UInt2X(hi: 0, lo: r2), UInt2X(hi: r1, lo: r0))270    }271272    public func multipliedFullWidth(by other: UInt2X) -> (high: UInt2X, low: Magnitude) {273        guard self != 0 else { return (0, 0) }274        guard other != 0 else { return (0, 0) }275        #if os(macOS)276            if Int2XConfig.useAccelerate {277                // print("line \(#line):Accelerated! \(UInt2X.self)(\(self)).multipliedFullWidth(by:\(other))")278                switch self {279                case is UInt128:280                    var a = unsafeBitCast(self, to: vU128.self)281                    var b = unsafeBitCast(other, to: vU128.self)282                    var ab = vU256()283                    vU128FullMultiply(&a, &b, &ab)284                    let (l, h) = unsafeBitCast(ab, to: (UInt2X, UInt2X).self)285                    return (h, l)286                case is UInt256:287                    var a = unsafeBitCast(self, to: vU256.self)288                    var b = unsafeBitCast(other, to: vU256.self)289                    var ab = vU512()290                    vU256FullMultiply(&a, &b, &ab)291                    let (l, h) = unsafeBitCast(ab, to: (UInt2X, UInt2X).self)292                    return (h, l)293                case is UInt512:294                    var a = unsafeBitCast(self, to: vU512.self)295                    var b = unsafeBitCast(other, to: vU512.self)296                    var ab = vU1024()297                    vU512FullMultiply(&a, &b, &ab)298                    let (l, h) = unsafeBitCast(ab, to: (UInt2X, UInt2X).self)299                    return (h, l)300                default:301                    break302                }303            }304        #endif305        let l = multipliedHalfWidth(by: other.lo)306        let hs = multipliedHalfWidth(by: other.hi)307        let h = (high: UInt2X(hi: hs.high.lo, lo: hs.low.hi), low: UInt2X(hi: hs.low.lo, lo: 0))308        let (rl, ol) = h.low.addingReportingOverflow(l.low)309        let rh = h.high &+ l.high &+ (ol ? 1 : 0) // will not overflow310        return (rh, rl)311    }312313    public func multipliedReportingOverflow(by other: UInt2X) -> (partialValue: UInt2X, overflow: Bool) {314        guard self != 0 else { return (0, false) }315        guard other != 0 else { return (0, false) }316        let result = multipliedFullWidth(by: other)317        return (result.low, result.high > 0)318    }319320    public static func &* (lhs: UInt2X, rhs: UInt2X) -> UInt2X {321        lhs.multipliedReportingOverflow(by: rhs).partialValue322    }323324    public static func &* (lhs: UInt2X, rhs: Word) -> UInt2X {325        lhs.multipliedHalfWidth(by: rhs).low326    }327328    public static func &* (lhs: Word, rhs: UInt2X) -> UInt2X {329        rhs.multipliedHalfWidth(by: lhs).low330    }331332    public static func * (lhs: UInt2X, rhs: UInt2X) -> UInt2X {333        let result = lhs.multipliedReportingOverflow(by: rhs)334        precondition(!result.overflow, "Multiplication overflow!")335        return result.partialValue336    }337338    public static func * (lhs: UInt2X, rhs: Word) -> UInt2X {339        let result = lhs.multipliedHalfWidth(by: rhs)340        precondition(result.high == 0, "Multiplication overflow!")341        return result.low342    }343344    public static func * (lhs: Word, rhs: UInt2X) -> UInt2X {345        let result = rhs.multipliedHalfWidth(by: lhs)346        precondition(result.high == 0, "Multiplication overflow!")347        return result.low348    }349350    public static func *= (lhs: inout UInt2X, rhs: UInt2X) {351        lhs = lhs * rhs352    }353354    public static func *= (lhs: inout UInt2X, rhs: Word) {355        lhs = lhs * rhs356    }357}358359// bitshifts360public extension UInt2X {361    func rShifted(_ width: Int) -> UInt2X {362        if width < 0 { return lShifted(-width) }363        if width == 0 { return self }364        if width == Word.bitWidth { return UInt2X(hi: 0, lo: hi) }365        #if os(macOS)366            if Int2XConfig.useAccelerate {367                // print("line \(#line):Accelerated! \(UInt2X.self)(\(self)).rShifted(\(other))")368                switch self {369                case is UInt128:370                    var a = unsafeBitCast((self, vU128()), to: vU256.self)371                    var r = vU256()372                    vLR256Shift(&a, UInt32(width), &r)373                    return unsafeBitCast(r, to: (UInt2X, UInt2X).self).0374                case is UInt256:375                    var a = unsafeBitCast(self, to: vU256.self)376                    var r = vU256()377                    vLR256Shift(&a, UInt32(width), &r)378                    return unsafeBitCast(r, to: UInt2X.self)379                case is UInt512:380                    var a = unsafeBitCast(self, to: vU512.self)381                    var r = vU512()382                    vLR512Shift(&a, UInt32(width), &r)383                    return unsafeBitCast(r, to: UInt2X.self)384                case is UInt1024:385                    var a = unsafeBitCast(self, to: vU1024.self)386                    var r = vU1024()387                    vLR1024Shift(&a, UInt32(width), &r)388                    return unsafeBitCast(r, to: UInt2X.self)389                default:390                    break391                }392            }393        #endif394        if Word.bitWidth < width {395            return UInt2X(hi: 0, lo: hi >> (width - Word.bitWidth))396        } else {397            let mask = Word((1 << width) &- 1)398            let carry = (hi & mask) << (Word.bitWidth - width)399            return UInt2X(hi: hi >> width, lo: carry | lo >> width)400        }401    }402403    func lShifted(_ width: Int) -> UInt2X {404        if width < 0 { return rShifted(-width) }405        if width == 0 { return self }406        if width == Word.bitWidth { return UInt2X(hi: lo, lo: 0) }407        #if os(macOS)408            if Int2XConfig.useAccelerate {409                // print("line \(#line):Accelerated! \(UInt2X.self)(\(self)).lShifted(\(other))")410                switch self {411                case is UInt128:412                    var a = unsafeBitCast((self, vU128()), to: vU256.self)413                    var r = vU256()414                    vLL256Shift(&a, UInt32(width), &r)415                    return unsafeBitCast(r, to: (UInt2X, UInt2X).self).0416                case is UInt256:417                    var a = unsafeBitCast(self, to: vU256.self)418                    var r = vU256()419                    vLL256Shift(&a, UInt32(width), &r)420                    return unsafeBitCast(r, to: UInt2X.self)421                case is UInt512:422                    var a = unsafeBitCast(self, to: vU512.self)423                    var r = vU512()424                    vLL512Shift(&a, UInt32(width), &r)425                    return unsafeBitCast(r, to: UInt2X.self)426                case is UInt1024:427                    var a = unsafeBitCast(self, to: vU1024.self)428                    var r = vU1024()429                    vLL1024Shift(&a, UInt32(width), &r)430                    return unsafeBitCast(r, to: UInt2X.self)431                default:432                    break433                }434            }435        #endif436        if Word.bitWidth < width {437            return UInt2X(hi: lo << (width - Word.bitWidth), lo: 0)438        } else {439            let carry = lo >> (Word.bitWidth - width)440            return UInt2X(hi: hi << width | carry, lo: lo << width)441        }442    }443444    static func &>> (_ lhs: UInt2X, _ rhs: UInt2X) -> UInt2X {445        lhs.rShifted(Int(rhs.lo))446    }447448    static func &>>= (_ lhs: inout UInt2X, _ rhs: UInt2X) {449        return lhs = lhs &>> rhs450    }451452    static func &<< (_ lhs: UInt2X, _ rhs: UInt2X) -> UInt2X {453        lhs.lShifted(Int(rhs.lo))454    }455456    static func &<<= (_ lhs: inout UInt2X, _ rhs: UInt2X) {457        return lhs = lhs &<< rhs458    }459}460461// division, which is rather tough462public extension UInt2X {463    func quotientAndRemainder(dividingBy other: Word) -> (quotient: UInt2X, remainder: UInt2X) {464        precondition(other != 0, "division by zero!")465        let (qh, rh) = hi.quotientAndRemainder(dividingBy: other)466        let (ql, rl) = other.dividingFullWidth((high: rh, low: lo.magnitude))467        return (UInt2X(hi: qh, lo: ql), UInt2X(rl))468    }469470    func quotientAndRemainder(dividingBy other: UInt2X) -> (quotient: UInt2X, remainder: UInt2X) {471        precondition(other != 0, "division by zero!")472        guard other != self else { return (1, 0) }473        guard other < self else { return (0, self) }474        guard other.hi != 0 else {475            return quotientAndRemainder(dividingBy: other.lo)476        }477        #if os(macOS)478            if Int2XConfig.useAccelerate {479                // print("line \(#line):Accelerated! \(UInt2X.self)(\(self)).quotientAndRemainder(dividingBy:\(other))")480                switch self {481                case is UInt128:482                    var a = unsafeBitCast((self, vU128()), to: vU256.self)483                    var b = unsafeBitCast((other, vU128()), to: vU256.self)484                    var (q, r) = (vU256(), vU256())485                    vU256Divide(&a, &b, &q, &r)486                    let qq = unsafeBitCast(q, to: (UInt2X, UInt2X).self).0487                    let rr = unsafeBitCast(r, to: (UInt2X, UInt2X).self).0488                    return (qq, rr)489                case is UInt256:490                    var a = unsafeBitCast(self, to: vU256.self)491                    var b = unsafeBitCast(other, to: vU256.self)492                    var (q, r) = (vU256(), vU256())493                    vU256Divide(&a, &b, &q, &r)494                    let qq = unsafeBitCast(q, to: UInt2X.self)495                    let rr = unsafeBitCast(r, to: UInt2X.self)496                    return (qq, rr)497                case is UInt512:498                    var a = unsafeBitCast(self, to: vU512.self)499                    var b = unsafeBitCast(other, to: vU512.self)500                    var (q, r) = (vU512(), vU512())501                    vU512Divide(&a, &b, &q, &r)502                    let qq = unsafeBitCast(q, to: UInt2X.self)503                    let rr = unsafeBitCast(r, to: UInt2X.self)504                    return (qq, rr)505                case is UInt1024:506                    var a = unsafeBitCast(self, to: vU1024.self)507                    var b = unsafeBitCast(other, to: vU1024.self)508                    var (q, r) = (vU1024(), vU1024())509                    vU1024Divide(&a, &b, &q, &r)510                    let qq = unsafeBitCast(q, to: UInt2X.self)511                    let rr = unsafeBitCast(r, to: UInt2X.self)512                    return (qq, rr)513                default:514                    break515                }516            }517        #endif518        #if false519            if Word.bitWidth * 2 <= UInt64.bitWidth { // cheat when we can :-)520                let divided = (UInt64(hi) << Word.bitWidth) + UInt64(lo)521                let divider = (UInt64(other.hi) << Word.bitWidth) + UInt64(other.lo)522                let (q, r) = divided.quotientAndRemainder(dividingBy: divider)523                return (UInt2X(q), UInt2X(r))524            }525        #endif526        // slow but steady bitwise long division527        // print("line \(#line): \(UInt2X.self)(\(self)).quotientAndRemainder(dividingBy:\(other))")528        var (q, r) = (UInt2X(0), UInt2X(0))529        for i in (0 ..< UInt2X.bitWidth).reversed() {530            r <<= 1531            r |= (self >> i) & 1532            if other <= r {533                r -= other534                q |= (1 << i)535            }536        }537        return (q, r)538    }539540    static func / (_ lhs: UInt2X, rhs: UInt2X) -> UInt2X {541        lhs.quotientAndRemainder(dividingBy: rhs).quotient542    }543544    static func /= (_ lhs: inout UInt2X, rhs: UInt2X) {545        lhs = lhs / rhs546    }547548    static func % (_ lhs: UInt2X, rhs: UInt2X) -> UInt2X {549        lhs.quotientAndRemainder(dividingBy: rhs).remainder550    }551552    static func %= (_ lhs: inout UInt2X, rhs: UInt2X) {553        lhs = lhs % rhs554    }555556    func dividedReportingOverflow(by other: UInt2X) -> (partialValue: UInt2X, overflow: Bool) {557        return (self / other, false)558    }559560    func remainderReportingOverflow(dividingBy other: UInt2X) -> (partialValue: UInt2X, overflow: Bool) {561        return (self % other, false)562    }563564    func dividingFullWidth(_ dividend: (high: UInt2X, low: Magnitude)) -> (quotient: UInt2X, remainder: UInt2X) {565        precondition(self != 0, "division by zero!")566        guard dividend.high != 0 else { return dividend.low.quotientAndRemainder(dividingBy: self) }567        #if os(macOS)568            if Int2XConfig.useAccelerate {569                // print("line \(#line):Accelerated! \(UInt2X.self)(\(self)).dividingFullWidth(\(dividend))")570                switch self {571                case is UInt128:572                    var a = unsafeBitCast((dividend.low, dividend.high), to: vU256.self)573                    var b = unsafeBitCast((self, vU128()), to: vU256.self)574                    var (q, r) = (vU256(), vU256())575                    vU256Divide(&a, &b, &q, &r)576                    let qq = unsafeBitCast(q, to: (UInt2X, UInt2X).self).0577                    let rr = unsafeBitCast(r, to: (UInt2X, UInt2X).self).0578                    return (qq, rr)579                case is UInt256:580                    var a = unsafeBitCast((dividend.low, dividend.high), to: vU512.self)581                    var b = unsafeBitCast((self, vU256()), to: vU512.self)582                    var (q, r) = (vU512(), vU512())583                    vU512Divide(&a, &b, &q, &r)584                    let qq = unsafeBitCast(q, to: (UInt2X, UInt2X).self).0585                    let rr = unsafeBitCast(r, to: (UInt2X, UInt2X).self).0586                    return (qq, rr)587                case is UInt512:588                    var a = unsafeBitCast((dividend.low, dividend.high), to: vU1024.self)589                    var b = unsafeBitCast((self, vU512()), to: vU1024.self)590                    var (q, r) = (vU1024(), vU1024())591                    vU1024Divide(&a, &b, &q, &r)592                    let qq = unsafeBitCast(q, to: (UInt2X, UInt2X).self).0593                    let rr = unsafeBitCast(r, to: (UInt2X, UInt2X).self).0594                    return (qq, rr)595                default:596                    break597                }598            }599        #endif600        // slow but steady bitwise long division601        // print("line \(#line): \(UInt2X.self)(\(self)).dividingFullWidth(\(dividend))")602        var (q, r) = (UInt2X(0), dividend.high % self)603        for i in (0 ..< UInt2X.bitWidth).reversed() {604            r <<= 1605            r |= (dividend.low >> i) & 1606            if self <= r {607                r -= self608                q |= (1 << i)609            }610        }611        return (q, r)612    }613}614615// UInt2X -> String616extension UInt2X: CustomStringConvertible, CustomDebugStringConvertible {617    public func toString(radix: Int = 10, uppercase: Bool = false) -> String {618        precondition((2 ... 36) ~= radix, "radix must be within the range of 2-36.")619        if self == 0 { return "0" }620        if hi == 0 { return String(lo, radix: radix, uppercase: uppercase) }621        if radix == 16 || radix == 4 || radix == 2 { // time-saver622            let sl = String(lo, radix: radix, uppercase: uppercase)623            let dCount = Word.bitWidth / (radix == 16 ? 4 : radix == 4 ? 2 : 1)624            let zeros = [Character](repeating: "0", count: dCount - sl.count)625            return String(hi, radix: radix, uppercase: uppercase) + String(zeros) + sl626        }627        let digits = uppercase628            ? Array("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")629            : Array("0123456789abcdefghijklmnopqrstuvwxyz")630        #if false // slow but steady digit by digit conversion631            var result = [Character]()632            var qr = (quotient: self, remainder: UInt2X(0))633            repeat {634                qr = qr.quotient.quotientAndRemainder(dividingBy: Word(radix))635                result.append(digits[Int(qr.remainder.lo)])636            } while qr.quotient != UInt2X(0)637            return String(result.reversed())638        #else // faster n-digit-at-once conversion639            let base: UInt64 = [640                0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0xA8B8_B452_291F_E800, //  0 ~  3641                0x0000_0000_0000_0000, 0x6765_C793_FA10_0800, 0x41C2_1CB8_E100_0000, 0x3642_7987_5022_6200, //  4 ~  7642                0x8000_0000_0000_0000, 0xA8B8_B452_291F_E800, 0x8AC7_2304_89E8_0000, 0x4D28_CB56_C33F_A400, //  8 ~ 11643                0x1ECA_170C_0000_0000, 0x780C_7372_621B_D800, 0x1E39_A505_7D81_0000, 0x5B27_AC99_3DF9_7800, // 11 ~ 15644                0x0000_0000_0000_0000, 0x27B9_5E99_7E21_DA00, 0x5DA0_E1E5_3C5C_8000, 0xD2AE_3299_C1C4_B000, // 16 ~ 19645                0x16BC_C41E_9000_0000, 0x2D04_B7FD_D9C0_F000, 0x5658_597B_CAA2_4000, 0xA0E2_0737_3760_9000, // 20 ~ 23646                0x0C29_E980_0000_0000, 0x14AD_F4B7_3203_3500, 0x226E_D364_78BF_A000, 0x383D_9170_B85F_F800, // 24 ~ 27647                0x5A3C_23E3_9C00_0000, 0x8E65_1373_8812_2800, 0xDD41_BB36_D259_E000, 0x0AEE_5720_EE83_0680, // 28 ~ 31648                0x1000_0000_0000_0000, 0x1725_88AD_4F5F_0A00, 0x211E_44F7_D02C_1000, 0x2EE5_6725_F06E_5C00, // 32 ~ 35649                0x41C2_1CB8_E100_0000, // 36650            ][radix]651            let nlen = base.description.count - 1652            // print("base=",base)653            var qr = (quotient: self, remainder: UInt2X(0))654            var result = [UInt64]()655            repeat {656                qr = qr.quotient.quotientAndRemainder(dividingBy: UInt2X(base))657                result.append(UInt64(qr.remainder))658            } while qr.quotient != UInt2X(0)659            let firstDigit = result.removeLast()660            return String(firstDigit, radix: radix, uppercase: uppercase) + result.map {661                let s = String($0, radix: radix, uppercase: uppercase)662                return String([Character](repeating: "0", count: nlen - s.count)) + s663            }.reversed().joined()664        #endif665    }666667    public var description: String {668        toString()669    }670671    public var debugDescription: String {672        "0x" + toString(radix: 16)673    }674}675676public extension StringProtocol {677    init?<Word>(_ source: UInt2X<Word>, radix: Int = 10, uppercase: Bool = false) {678        self.init(source.toString(radix: radix, uppercase: uppercase))679    }680}681682// String <- UInt2X683extension UInt2X: ExpressibleByStringLiteral {684    public init(stringLiteral value: StringLiteralType) {685        self.init()686        if let result = UInt2X.fromString(value) {687            self = result688        }689    }690691    internal static func fromString(_ value: String) -> UInt2X? {692        let radix = UInt2X.radixFromString(value)693        let source = radix == 10 ? value : String(value.dropFirst(2))694        return UInt2X(source, radix: radix)695    }696697    internal static func radixFromString(_ string: String) -> Int {698        switch string.prefix(2) {699        case "0b": return 2700        case "0o": return 8701        case "0x": return 16702        default: return 10703        }704    }705}706707// Int -> UInt2X708public extension Int {709    init<Word>(_ source: UInt2X<Word>) {710        self.init(bitPattern: UInt(source.hi << Word.bitWidth + source.lo))711    }712}713714// Strideable715extension UInt2X: Strideable {716    public func distance(to other: UInt2X) -> Int {717        Int(other) - Int(self)718    }719720    public func advanced(by n: Int) -> UInt2X {721        self + UInt2X(n)722    }723}724725// BinaryInteger726extension UInt2X: BinaryInteger {727    public var bitWidth: Int {728        Word.bitWidth * 2729    }730731    public var words: Words {732        Array(lo.words) + Array(hi.words)733    }734735    public var trailingZeroBitCount: Int {736        hi == 0 ? lo.trailingZeroBitCount : hi.trailingZeroBitCount + Word.bitWidth737    }738739    public static func &= (lhs: inout UInt2X, rhs: UInt2X) {740        lhs = UInt2X(hi: lhs.hi & rhs.hi, lo: lhs.lo & rhs.lo)741    }742743    public static func |= (lhs: inout UInt2X, rhs: UInt2X) {744        lhs = UInt2X(hi: lhs.hi | rhs.hi, lo: lhs.lo | rhs.lo)745    }746747    public static func ^= (lhs: inout UInt2X<Word>, rhs: UInt2X<Word>) {748        lhs = UInt2X(hi: lhs.hi ^ rhs.hi, lo: lhs.lo ^ rhs.lo)749    }750751    public static func <<= <RHS>(lhs: inout UInt2X<Word>, rhs: RHS) where RHS: BinaryInteger {752        lhs = lhs.lShifted(Int(rhs))753    }754755    public static func >>= <RHS>(lhs: inout UInt2X, rhs: RHS) where RHS: BinaryInteger {756        lhs = lhs.rShifted(Int(rhs))757    }758}759760// FixedWidthInteger761extension UInt2X: FixedWidthInteger {762    public init(_truncatingBits _: UInt) {763        fatalError()764    }765766    public var nonzeroBitCount: Int {767        hi.nonzeroBitCount + lo.nonzeroBitCount768    }769770    public var leadingZeroBitCount: Int {771        hi == 0 ? lo.leadingZeroBitCount + Word.bitWidth : hi.leadingZeroBitCount772    }773774    public var byteSwapped: UInt2X {775        UInt2X(hi: lo.byteSwapped, lo: hi.byteSwapped)776    }777}778779// UnsignedInteger780extension UInt2X: UnsignedInteger {}781782public typealias UInt128 = UInt2X<UInt64>783public typealias UInt256 = UInt2X<UInt128>784public typealias UInt512 = UInt2X<UInt256>785public typealias UInt1024 = UInt2X<UInt512>786