Arbitrary-precision arithmetic in pure Swift

Related tags

Math BigInt
Overview

BigInt

Swift 5 License Platform

Build Status Code Coverage jazzy Carthage compatible Version

Overview

This repository provides integer types of arbitrary width implemented in 100% pure Swift. The underlying representation is in base 2^64, using Array<UInt64>.

This module is handy when you need an integer type that's wider than UIntMax, but you don't want to add The GNU Multiple Precision Arithmetic Library as a dependency.

Two big integer types are included: BigUInt and BigInt, the latter being the signed variant. Both of these are Swift structs with copy-on-write value semantics, and they can be used much like any other integer type.

The library provides implementations for some of the most frequently useful functions on big integers, including

The implementations are intended to be reasonably efficient, but they are unlikely to be competitive with GMP at all, even when I happened to implement an algorithm with same asymptotic behavior as GMP. (I haven't performed a comparison benchmark, though.)

The library has 100% unit test coverage. Sadly this does not imply that there are no bugs in it.

API Documentation

Generated API docs are available at https://attaswift.github.io/BigInt/.

License

BigInt can be used, distributed and modified under the MIT license.

Requirements and Integration

BigInt 4.0.0 requires Swift 4.2 (The last version with support for Swift 3.x was BigInt 2.1.0. The last version with support for Swift 2 was BigInt 1.3.0.)

Swift Version last BigInt Version
3.x 2.1.0
4.0 3.1.0
4.2 4.0.0
5.x 5.2.1

BigInt deploys to macOS 10.10, iOS 9, watchOS 2 and tvOS 9. It has been tested on the latest OS releases only---however, as the module uses very few platform-provided APIs, there should be very few issues with earlier versions.

BigInt uses no APIs specific to Apple platforms, so it should be easy to port it to other operating systems.

Setup instructions:

  • Swift Package Manager: Although the Package Manager is still in its infancy, BigInt provides experimental support for it. Add this to the dependency section of your Package.swift manifest:

    .package(url: "https://github.com/attaswift/BigInt.git", from: "5.2.1")
  • CocoaPods: Put this in your Podfile:

    pod 'BigInt', '~> 5.2'
  • Carthage: Put this in your Cartfile:

    github "attaswift/BigInt" ~> 5.2
    

Implementation notes

BigUInt is a MutableCollectionType of its 64-bit digits, with the least significant digit at index 0. As a convenience, BigUInt allows you to subscript it with indexes at or above its count. The subscript operator returns 0 for out-of-bound gets and automatically extends the array on out-of-bound sets. This makes memory management simpler.

BigInt is just a tiny wrapper around a BigUInt absolute value and a sign bit, both of which are accessible as public read-write properties.

Why is there no generic BigInt<Digit> type?

The types provided by BigInt are not parametric—this is very much intentional, as Swift generics cost us dearly at runtime in this use case. In every approach I tried, making arbitrary-precision arithmetic operations work with a generic Digit type parameter resulted in code that was literally ten times slower. If you can make the algorithms generic without such a huge performance hit, please enlighten me!

This is an area that I plan to investigate more, as it would be useful to have generic implementations for arbitrary-width arithmetic operations. (Polynomial division and decimal bases are two examples.) The library already implements double-digit multiplication and division as extension methods on a protocol with an associated type requirement; this has not measurably affected performance. Unfortunately, the same is not true for BigUInt's methods.

Of course, as a last resort, we could just duplicate the code to create a separate generic variant that was slower but more flexible.

Calculation Samples

Obligatory Factorial Demo

It is easy to use BigInt to calculate the factorial function for any integer:

import BigInt

func factorial(_ n: Int) -> BigInt {
    return (1 ... n).map { BigInt($0) }.reduce(BigInt(1), *)
}

print(factorial(10))
==> 362880

print(factorial(100))
==> 93326215443944152681699238856266700490715968264381621468592963895217599993229915
    6089414639761565182862536979208272237582511852109168640000000000000000000000

print(factorial(1000))
==> 40238726007709377354370243392300398571937486421071463254379991042993851239862902
    05920442084869694048004799886101971960586316668729948085589013238296699445909974
    24504087073759918823627727188732519779505950995276120874975462497043601418278094
    64649629105639388743788648733711918104582578364784997701247663288983595573543251
    31853239584630755574091142624174743493475534286465766116677973966688202912073791
    43853719588249808126867838374559731746136085379534524221586593201928090878297308
    43139284440328123155861103697680135730421616874760967587134831202547858932076716
    91324484262361314125087802080002616831510273418279777047846358681701643650241536
    91398281264810213092761244896359928705114964975419909342221566832572080821333186
    11681155361583654698404670897560290095053761647584772842188967964624494516076535
    34081989013854424879849599533191017233555566021394503997362807501378376153071277
    61926849034352625200015888535147331611702103968175921510907788019393178114194545
    25722386554146106289218796022383897147608850627686296714667469756291123408243920
    81601537808898939645182632436716167621791689097799119037540312746222899880051954
    44414282012187361745992642956581746628302955570299024324153181617210465832036786
    90611726015878352075151628422554026517048330422614397428693306169089796848259012
    54583271682264580665267699586526822728070757813918581788896522081643483448259932
    66043367660176999612831860788386150279465955131156552036093988180612138558600301
    43569452722420634463179746059468257310379008402443243846565724501440282188525247
    09351906209290231364932734975655139587205596542287497740114133469627154228458623
    77387538230483865688976461927383814900140767310446640259899490222221765904339901
    88601856652648506179970235619389701786004081188972991831102117122984590164192106
    88843871218556461249607987229085192968193723886426148396573822911231250241866493
    53143970137428531926649875337218940694281434118520158014123344828015051399694290
    15348307764456909907315243327828826986460278986432113908350621709500259738986355
    42771967428222487575867657523442202075736305694988250879689281627538488633969099
    59826280956121450994871701244516461260379029309120889086942028510640182154399457
    15680594187274899809425474217358240106367740459574178516082923013535808184009699
    63725242305608559037006242712434169090041536901059339838357779394109700277534720
    00000000000000000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000000000000000000000000000
    00000

Well, I guess that's all right, but it's not very interesting. Let's try something more useful.

RSA Cryptography

The BigInt module provides all necessary parts to implement an (overly) simple RSA cryptography system.

Let's start with a simple function that generates a random n-bit prime. The module includes a function to generate random integers of a specific size, and also an isPrime method that performs the Miller–Rabin primality test. These are all we need:

func generatePrime(_ width: Int) -> BigUInt {
    while true {
        var random = BigUInt.randomInteger(withExactWidth: width)
        random |= BigUInt(1)
        if random.isPrime() {
            return random
        }
    }
}

let p = generatePrime(1024)
==> 13308187650642192396256419911012544845370493728424936791561478318443071617242872
    81980956747087187419914435169914161116601678883358611076800743580556055714173922
    08406194264346635072293912609713085260354070700055888678514690878149253177960273
    775659537560220378850112471985434373425534121373466492101182463962031

let q = generatePrime(1024)
==> 17072954422657145489547308812333368925007949054501204983863958355897172093173783
    10108226596943999553784252564650624766276133157586733504784616138305701168410157
    80784336308507083874651158029602582993233111593356512531869546706885170044355115
    669728424124141763799008880327106952436883614887277350838425336156327

Cool! Now that we have two large primes, we can produce an RSA public/private keypair out of them.

typealias Key = (modulus: BigUInt, exponent: BigUInt)

let n = p * q
==> 22721008120758282530010953362926306641542233757318103044313144976976529789946696
    15454966720907712515917481418981591379647635391260569349099666410127279690367978
    81184375533755888994370640857883754985364288413796100527262763202679037134021810
    57933883525572232242690805678883227791774442041516929419640051653934584376704034
    63953169772816907280591934423237977258358097846511079947337857778137177570668391
    57455417707100275487770399281417352829897118140972240757708561027087217205975220
    02207275447810167397968435583004676293892340103729490987263776871467057582629588
    916498579594964478080508868267360515953225283461208420137

let e: BigUInt = 65537
let phi = (p - 1) * (q - 1)
let d = e.inverse(phi)!     // d * e % phi == 1
==> 13964664343869014759736350480776837992604500903989703383202366291905558996277719
    77822086142456362972689566985925179681282432115598451765899180050962461295573831
    37069237934291884106584820998146965085531433195106686745474222222620986858696591
    69836532468835154412554521152103642453158895363417640676611704542784576974374954
    45789456921660619938185093118762690200980720312508614337759620606992462563490422
    76669559556568917533268479190948959560397579572761529852891246283539604545691244
    89999692877158676643042118662613875863504016129837099223040687512684532694527109
    80742873307409704484365002175294665608486688146261327793

let publicKey: Key = (n, e)
let privateKey: Key = (n, d)

In RSA, modular exponentiation is used to encrypt (and decrypt) messages.

func encrypt(_ message: BigUInt, key: Key) -> BigUInt {
    return message.power(key.exponent, modulus: key.modulus)
}

Let's try out our new keypair by converting a string into UTF-8, interpreting the resulting binary representation as a big integer, and encrypting it with the public key. BigUInt has an initializer that takes an NSData, so this is pretty easy to do:

let secret: BigUInt = BigUInt("Arbitrary precision arithmetic is fun!".dataUsingEncoding(NSUTF8StringEncoding)!)
==> 83323446846105976078466731524728681905293067701804838925389198929123912971229457
    68818568737

let cyphertext = encrypt(secret, key: publicKey)
==> 95186982543485985200666516508066093880038842892337880561554910904277290917831453
    54854954722744805432145474047391353716305176389470779020645959135298322520888633
    61674945129099575943384767330342554525120384485469428048962027149169876127890306
    77028183904699491962050888974524603226290836984166164759586952419343589385279641
    47999991283152843977988979846238236160274201261075188190509539751990119132013021
    74866638595734222867005089157198503204192264814750832072844208520394603054901706
    06024394731371973402595826456435944968439153664617188570808940022471990638468783
    49208193955207336172861151720299024935127021719852700882

Well, it looks encrypted all right, but can we get the original message back? In theory, encrypting the cyphertext with the private key returns the original message. Let's see:

let plaintext = encrypt(cyphertext, key: privateKey)
==> 83323446846105976078466731524728681905293067701804838925389198929123912971229457
    68818568737

let received = String(data: plaintext.serialize(), encoding: NSUTF8StringEncoding)
==> "Arbitrary precision arithmetic is fun!"

Yay! This is truly terrific, but please don't use this example code in an actual cryptography system. RSA has lots of subtle (and some not so subtle) complications that we ignored to keep this example short.

Calculating the Digits of π

Another fun activity to try with BigInts is to generate the digits of π. Let's try implementing Jeremy Gibbon's spigot algorithm. This is a rather slow algorithm as π-generators go, but it makes up for it with its grooviness factor: it's remarkably short, it only uses (big) integer arithmetic, and every iteration produces a single new digit in the base-10 representation of π. This naturally leads to an implementation as an infinite GeneratorType:

func digitsOfPi() -> AnyGenerator<Int> {
    var q: BigUInt = 1
    var r: BigUInt = 180
    var t: BigUInt = 60
    var i: UInt64 = 2 // Does not overflow until digit #826_566_842
    return AnyIterator {
        let u: UInt64 = 3 * (3 * i + 1) * (3 * i + 2)
        let y = (q.multiplied(byDigit: 27 * i - 12) + 5 * r) / (5 * t)
        (q, r, t) = (
            10 * q.multiplied(byDigit: i * (2 * i - 1)),
            10 * (q.multiplied(byDigit: 5 * i - 2) + r - y * t).multiplied(byDigit: u),
            t.multiplied(byDigit: u))
        i += 1
        return Int(y[0])
    }
}

Well, that was surprisingly easy. But does it work? Of course it does!

var digits = "π ≈ "
var count = 0
for digit in digitsOfPi() {
    assert(digit < 10)
    digits += String(digit)
    count += 1
    if count == 1 { digits += "." }
    if count == 1000 { break }
}

digits
==> π  3.14159265358979323846264338327950288419716939937510582097494459230781640628
    62089986280348253421170679821480865132823066470938446095505822317253594081284811
    17450284102701938521105559644622948954930381964428810975665933446128475648233786
    78316527120190914564856692346034861045432664821339360726024914127372458700660631
    55881748815209209628292540917153643678925903600113305305488204665213841469519415
    11609433057270365759591953092186117381932611793105118548074462379962749567351885
    75272489122793818301194912983367336244065664308602139494639522473719070217986094
    37027705392171762931767523846748184676694051320005681271452635608277857713427577
    89609173637178721468440901224953430146549585371050792279689258923542019956112129
    02196086403441815981362977477130996051870721134999999837297804995105973173281609
    63185950244594553469083026425223082533446850352619311881710100031378387528865875
    33208381420617177669147303598253490428755468731159562863882353787593751957781857
    780532171226806613001927876611195909216420198

Now go and have some fun with big integers on your own!

Comments
  • versioning scheme to use with spm

    versioning scheme to use with spm

    Would it be possible to comply to the semVer semantic scheme for versioning so that the swift package manager can be used? (https://github.com/apple/swift-package-manager/blob/master/Documentation/Reference.md#version) (http://semver.org)

    many thx!

    opened by ratranqu 11
  • Hi. I Made extension for BigInt to Data and reverse.

    Hi. I Made extension for BigInt to Data and reverse.

    extension BigInt {
        
        public func serialize() -> Data {
            var array = Array(BigUInt.init(self.magnitude).serialize())
            
            if array.count > 0 {
                if self.sign == BigInt.Sign.plus {
                    if array[0] >= 128 {
                        array.insert(0, at: 0)
                    }
                } else if self.sign == BigInt.Sign.minus {
                    if array[0] <= 127 {
                        array.insert(255, at: 0)
                    }
                }
            }
            
            return Data.init(bytes: array)
        }
        
        public init(_ data: Data) {
            var dataArray = Array(data)
            var sign: BigInt.Sign = BigInt.Sign.plus
            
            if dataArray.count > 0 {
                if dataArray[0] >= 128 {
                    sign = BigInt.Sign.minus
                    
                    if dataArray.count > 1 {
                        if dataArray[0] == 255, dataArray.count > 1 {
                            dataArray.remove(at: 0)
                        } else {
                            dataArray[0] = UInt8(256 - Int(dataArray[0]))
                        }
                    }
                }
            }
            
            let magnitude = BigUInt.init(Data.init(bytes: dataArray))
            
            self .init(sign: sign, magnitude: magnitude)
        }
    }
    
    opened by OleksiiShulzhenko 10
  • Computational overhead

    Computational overhead

    hello,

    Thank you for open source this Arbitrary-precision arithmetic. When I use this to test paillier algorithm computational overhead, this function

    func power(exponent: BigUInt, modulus: BigUInt) -> BigUInt{}

    , the Java modPower computational overhead about 45ms but this function about 2.7s, cause some distortion. The overhead test code at here: https://github.com/SummonY/Paillier_iOS

    Can you help to optimize this function?

    Thanks, Summon Yang

    opened by SummonY 9
  • Let Swift Package Manager support Linux, too

    Let Swift Package Manager support Linux, too

    With this PR you can swift build and swift test on Linux. Note SipHash needs fixes as https://github.com/attaswift/SipHash/pull/6 so for the time being its url is pointed to https://github.com/dankogai/SipHash .

    opened by dankogai 8
  • Removed SipHash dependency

    Removed SipHash dependency

    I removed the dependency on SipHash. According to my benchmarks performance seems to be the same.

    Benchmark without SipHash: Executed 11 tests, with 0 failures (0 unexpected) in 120.415 (120.421) seconds Test Suite 'All tests' started at 2018-09-08 14:02:11.044 Test Suite 'BigInt Benchmark.xctest' started at 2018-09-08 14:02:11.044 Test Suite 'ProfileTests' started at 2018-09-08 14:02:11.045 Test Case '-[BigInt_Benchmark.ProfileTests testBalancedFactorial]' started. /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:113: Test Case '-[BigInt_Benchmark.ProfileTests testBalancedFactorial]' measured [Time, seconds] average: 0.229, relative standard deviation: 3.722%, values: [0.227781, 0.214933, 0.214401, 0.228784, 0.238261, 0.239564, 0.235090, 0.224704, 0.236136, 0.225983], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testBalancedFactorial]' passed (5.644 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testDivision]' started. Performing 31 divisions with digit counts (3215 / (137...3215) Round 0 started Round 1 started Round 2 started Round 3 started Round 4 started Round 5 started Round 6 started Round 7 started Round 8 started Round 9 started /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:27: Test Case '-[BigInt_Benchmark.ProfileTests testDivision]' measured [Time, seconds] average: 0.424, relative standard deviation: 2.560%, values: [0.431835, 0.427855, 0.447590, 0.435150, 0.423544, 0.416147, 0.410971, 0.416255, 0.418640, 0.413905], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testDivision]' passed (5.253 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testDivisionOfFactorial]' started. /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:66: Test Case '-[BigInt_Benchmark.ProfileTests testDivisionOfFactorial]' measured [Time, seconds] average: 3.049, relative standard deviation: 1.462%, values: [3.022145, 2.999424, 2.993472, 3.022597, 3.027681, 3.056863, 3.056912, 3.077387, 3.151286, 3.081494], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testDivisionOfFactorial]' passed (31.168 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testFactorial]' started. /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:94: Test Case '-[BigInt_Benchmark.ProfileTests testFactorial]' measured [Time, seconds] average: 0.416, relative standard deviation: 1.002%, values: [0.424100, 0.418992, 0.411405, 0.417613, 0.418825, 0.411340, 0.410206, 0.412449, 0.415378, 0.415086], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testFactorial]' passed (7.462 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testFibonacciAddition]' started. /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:37: Test Case '-[BigInt_Benchmark.ProfileTests testFibonacciAddition]' measured [Time, seconds] average: 1.641, relative standard deviation: 0.633%, values: [1.651454, 1.644607, 1.657809, 1.651886, 1.641968, 1.626550, 1.642342, 1.639924, 1.624014, 1.633499], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testFibonacciAddition]' passed (16.669 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testGCD]' started. /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:205: Test Case '-[BigInt_Benchmark.ProfileTests testGCD]' measured [Time, seconds] average: 1.198, relative standard deviation: 0.420%, values: [1.203180, 1.206066, 1.202442, 1.196433, 1.194464, 1.200242, 1.189438, 1.199220, 1.195358, 1.191657], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testGCD]' passed (12.705 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testMersennePrimes]' started. /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:216: Test Case '-[BigInt_Benchmark.ProfileTests testMersennePrimes]' measured [Time, seconds] average: 1.759, relative standard deviation: 1.851%, values: [1.750311, 1.742634, 1.726778, 1.760925, 1.734730, 1.740537, 1.762530, 1.838110, 1.798488, 1.737544], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testMersennePrimes]' passed (17.849 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testModularExponentiation]' started. /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:182: Test Case '-[BigInt_Benchmark.ProfileTests testModularExponentiation]' measured [Time, seconds] average: 0.920, relative standard deviation: 0.612%, values: [0.932345, 0.913196, 0.918843, 0.920127, 0.918067, 0.921500, 0.918864, 0.915972, 0.928977, 0.916208], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testModularExponentiation]' passed (9.459 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testPrintingFactorial]' started. /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:75: Test Case '-[BigInt_Benchmark.ProfileTests testPrintingFactorial]' measured [Time, seconds] average: 0.792, relative standard deviation: 0.788%, values: [0.803952, 0.787616, 0.794060, 0.786527, 0.798550, 0.794586, 0.795813, 0.783751, 0.784988, 0.788474], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testPrintingFactorial]' passed (8.735 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testReadingFactorial]' started. 27749286793134184196846444043573827718796588128229077500965619901740421977829554305488090649945440026450089364907772533229141984707087772877435054661661246827209548469380787794206617080077463047701947019599063641510434901502364644948326090736582226744074149905262584673889503649107578130804056355481537688498198108887363212467177736870348551676170536902730461651075165872438889213764082863946832823386648426511600560180156350202267190113608287460564450749505473514023179580949094973330212308153890541674628045683215179240181755974997623803301083899529241336641670644374891172171933327740029118787006971707306688383260515986678592454570075272201683050782614539583123284749373502297310336275676891863964018788629538692888031873980198661136040765349891618084687723506025361434280261977070136897031152891366207754540786660685316085353383612759127748874273689877491435733305795787097120938742344426163749986577832713424594454439489894743555264488651676518662791729973675128739092013062265921516348913092797520830774578209743068173151542288906440933177157239608172400068320108817864823243803869231389641641477628579952708774343272709190912952821371768500203101501097607216452461242416229952024883321879046633183558468137733051746840804870172841619050983955844400385652248938501549856490267688371052105312193319994588107047926829780555723109093980431710059611399966439418005748892433432939292974781902638967697744380475955243729606479980516370496107439061639476364136302022458328999490139577696223922392583954138611412398441772312338075993976357157288241067694966927071014536565070099472601369141259793843992872269935780776964878612808108456582900921150885930235209883565492414245768534857895538991548203464949409124280911317493483041687009596799762951471326080758858975767517055590706237024253121793311299422478338932210489724999840985605780309266351951134803819139217360327980713999146355997843146748466534459786227929915990629807914594905851073803143933519150420780613488273801147495162025477356017392447266328114427811349640682723490236134065996579331876071355895322818117924646882253824777668066148598410616836193870617064140015705935300624802042764321883928645296205929975498009245936149646237716742887339042066568764579170861946783926626647201678589594776193412039731209837457558495135303078594626536534399994225891817566880857677917442758462935197749785843199462833936747578146925896258771659746980173461219455008934978770873874234535755618426604048955274716292980382952784380969407269088592271193407385914852088364762854062289735230934966274548353280839726137479476543093300656512986259377486486200867822535126875364611603817028305658609357179561950593202789728873994373527802120646700139306941327065484932140454496462884883111697017421534768697829836368300778849040246883186006899405381122977218241898298492476618353614693544609173365012528340307973477007229832170776286464531387949661767834912336175736755731345024924704343137199726047093516941814647993431750303605059249560279306006913148373436226882880221320468668648162189127276921922912100770098629557668400520661358270359601560202795018180652125515508145086175889528731550707273825867550166032044331967952968932523669783025102394199895955808972085284235255782010486518368489178642488304812740523608894895997787193894223638605187938466288122583883756689008433026813769214575203007470464934169440133491824009290325501539855066478983290406752700774432267307456216693013762577656651428943798284907407905176716807155312647655043870105452068083943484250790281536101213463833071226512608662908121371728163626226787037503084537850076111931914389011774384414650731191110300289305019719350454351768919819250965912117828432620511835970038410112708138445358383640253647635655694374474197832070865088852526020336820550144655485674950224257486941561223524334648761465270087567276126111947685633292944920119203376612312251741647078918680593291564381670826558638088230622898839377777684397190403163930839544594450220346949053192294493036326988939430627651207907153059712365272113462283349983316830134535343516206354379765326252548605784758044077915308113362319101807649982308048310310817191254162057823420089474471482920093351506344647949357852643696876729118049077216950382955041512193513012548911915391478693818317047697612396922905203525005106298595797017321243062267250191031223308636479907756518926915871220581388680340945682241653573142091848696538025698992955853006514017363212159351158593874703912815846917502609615675962348144818597181561583348545165199694814925070812450978331416091104428642812802842763408262114584743065316243779795521176882854951965214874542218843414334576773572538018805876434570689814201624980763388301240470698035507859978242085921888949403423222581741306409600281034600698725327523863797486997190125576413942167361717634463581295017296714311928882908237328839419066085644684709848420888037827729236462838295599921663155335791773243570040045191832807625715179839053607248536776953882423117796935960994166319202325817967720621774905289900397410904213096980572015343684916299260735941074964728126305605955791775380375790611453525688088571267120132314185792903225272849845900738291444822385544300647196161994572890218845058368619249127876140859743089242911254249453550540932185061047990167854039514178524006185259752287565613096600527197101902635021900219743103523931169564015818493080874700244774885680998043403560616551511724846831626333761967840871676473434641536278161676750025811587461625538707882595225158583111099061940804442339000615126297157414955842467633544875707032244878493945407524753900943534655265371728434800913305587451296837020702615614663189743348154159180768357605535235238165807054140481410070198723092611082534750127796297102113002272253852027151523119537884662996466143605114185264984512592724364595003936292383180489385241254156129452112241816135088482358038537562091968867654937903062272131460225427322803382009236538276376550252680276549921086159965028464019813410437311632659971474837396001146304721854411407847083681188222801012075854991602563036643418020952004470008384708096128568933900317086750751684563221584641316721048987343216751873176952279675049398742951113296827040487657021016930218107173174997915693368108021348080340456091238803342281030456377964042489224830536530606370365440268772118732145944991824508320654369516681439929125696358363414818991183152498477680891680995994824668006425237852616198163903856142664654761572931232700768402684971113576829448051334551485914715251972811644571800974642062040282416723835595889589210965645245941980114994489927526334499355701271709468049152681811238337229865826443373691650040021371599098321627840570110342604292903260373102042243048418586675947973527503596690685817541472643911543987876128325398232978787445928994937907131669438182660919813833840362758517944318091936414721579085191262402265712615317692051460482891705489423197272796113281725705830400085172428588615693232192493930543364569840813659881534827121290254283719960971367344057560263465335246887099280924769441329454360856007647619023086767266659925533532847605474576395106941278735305213881811333529974640490270885661685171955330364197412053208885566615099538795019332128148925824140184635549126073840146593795588858895373703391742856065357138332918832253774021417257702031892316706949324106790425068556824178398197253089629288904663276491746731611183214715814733513870611737790417580969851672395591244409956637032576062375704697407589972663175630672133918457151794233265277187297501670149804635542445777296304772204772996601929267282278963625237373416898219989722894679876144838350605616017651233181851385823145810448816308246477483633936599575897726394322129597606430100869374449686198131476985094153433043261306913683285840981263590503766704556821600422211474548501069126594623800679863453635544894999763989724043178654898504985933407179586299916116676489774422289893841470895437455728657997908872504190900813968733857888973882175293939870199473069302010198445104632574042125832512167366792284974210345202752969986511622866223310173825217783207923725603197951871692872911381824290675383324114455188660947751606354944418197479393766764033780717024346886688829177066621084402116949452633099688473394784859310305877311653235633067803622604898596465543039232738659881930765152349004793981135462384449343104366317941345664217136561761711086726096347652079040220865194671436728709148797864161597692369810246312845319312556949499874227118226530755743475681688394217098949571367272938328187143572527485828882947783740113356974927252635748546636108997374107583587987470353564331095787086340021655342540664526265175021103153593540953884638037498550665858118488404740099847650723571637120861990835250248423198636564531876108341515396777991700785407975595493294164920955341518031293304593570960344333379054589255779105528104495221870317743222927739681190427596464471180606956525117672275379958331663935872116394728787387747411618756167601187743886829394581531671044237968968088489548278289420934184403938006452978785133570323186679422308721193410129563717307762263991758626235217744022630595986638594354422511872783220467109289954034376702052951581441424399647473806711755248742426827143184852349085541055972969789877672661461086152110380353283526885984864113082777233010971487704610013886068941641140403296381566423483327700137540903576061160176124316402407874085696396211853662170332536988056150371245807581382760940592066492151049885357983018540299557653040742753166109874020630658916647622626186418760910337096674577599500840658479932630740929716626674719229218226348027027800582863839825877809696369606842475954898827407528248238460808565723050119680167400901922002790058873432690028249103167012062452167676518048603738148133054284072496974314026075953756362456628600623759195631701835850423211352722710403509989824221431516132082402428200561592767496787416177590462611787633529163473845956631866285424077042162854718152909814142994412666915104791880994108123093440387632949769283216253770726490720817955447444183143793879033842484484935217474859196743912070452418980014879358433062610193978511130621352299828331919999520244840290046711157690965266709134413998441992973691508781108873182031571118657927507571651173860161772164393676780981612709418450048415536124271684618777477491037779203990417644180855084965828737891394476879105603448193109329017819435349987513744671451602100129521107974630493072985720832202597222925627726412113277332206868290876077574691791589270504214767623839149456645872750988486406787974473504807009276097914549752373924789014589378916128946215899668791655203070963580632698320710925354589943203006413925333333875945173223759659653495323090942648409848530947494613169282302632632411207627140774248389874769636084078793235576598256986954283545331530995505290331232799427967638239446377209524665984606628682916209289836298911177707113339820271267215661011509986356853406779965024146560797217935109105395299065950248896401238689132857380369501272678849314577856288784467461329650884830974734447840837536147799419419458476182758345784910472533761718927544410686101422259705506859595524138240209234572941766049325848816583326229704934630213531848422624690091874975384777879472803067968229953505847027131681683010119516698391555541512217342256098753708657072242382395368704249293693287322876280025752240483263534929246985219636152748724155310706051973110582720145629065535250731739336079656512407224678417677118427851868079200281762436379952214008103806897225483138022343207391263321809492223122024821164817854621933081936189288457338743337301253269704151554683954434775156133277662439219976889389896090302271800629332852888741952202486819296565244677274402423504169951175265294075366661098781140129031852699740184935498785724100241352500468786878991995501293985637448354683330481986364783624340198849599476348025958992913231634632366471971915029149379847575232350106486025192744476287953849720448261993034336465071711956807977594818608535605165643715570804843854718428257167860899146418978839944260220330552225237262908316305686989305279984995374223971966632597110333210517478523490245180444295262792813463764342970256871855459911423834472418851395668169131999582351944822063994639156000835252531437016537500980569504441991011786320053699986951583147992097472863692863271273522793089511188471996070877257958743246336318497214302212220200975356758514268988080705584646250644156745193797154793494620962442515744438285758376409564394136095549289058326797005958837861147139740235477197155795485063910911562178983140609116861649375935301153454815021413492597207695405849588435695941347689616786993186221649334342486303420904206544392582663060799967145812890238531668398819341657067443337359556929417614649687435347082988523066582131927482502824504598977160391687856375271544010224068439710815073567050621049247332233991670285445731457656793060147724974654849610356998916285789051378457863885086091770535935385212412278226051442443333482624516504628237602844991834373925205778378706169174114078458048298051585448147610612743759527849806411847355159825265653900360566341593039033801834427567761454223381593486965164571577381916918773127659257686671170318207296971960033494948514882271821152031128978751052257850434666896627870758448997687982332325706076406762177811286370148469377152456483356771786439008856163277083766306047350214454545014298878855931267148149901150186882564220008135678842016477113440413545487739624882083732819408455947370260294240849312173352155983184659284680788411339803311423920749163744360903723622694682488923518894376611653741658015499924283499004571403400067767210091629649865967318309628010565296507047781933386689767357138859612749022934717941145772659655706264631101549208211939646937071483526656453700862106539062547656629361668341028925129139607857537081306297427300229647353256936917190571204324474168172149760735018126396581110594087689391455186263684219313805905856766177550379609393178352565210657494533646105807531450909594486858422242996320880431799796735662380094153792716479610541976273844751016761923547403431956926117697700529028343628817276123971312097534478147796352193942899365063456798294773686096170305404652286370090221922103838712207992759962336739784660136421369108817788818047880778661977227773562364188821418733437240897489636440673698021986883460982799148104972215679725166597175894073893317137524857871955861943452948451831849524626057775430753818404501004326056156841244051199671206771012170242118784619655435465750354578929580280267863334795834758291740751819792357200335285558125214206688983964969375928327001978237692564522914904803565356935413874613711080389665594603312454891597081610131935293327562015855001067562351408987063441944462896196935493397721736185997967601908269845039769465772886889798767295299038735507838748857467482063050197174522445616885306448923861536413283230371576597361628686136346007940606691810535541608990315300818671160038906411745681702633633674181934995546998608727205044511373338623662317642551605411327494554427310479564734598745154708657601154765351207554210388338554624240164388145382009754380041630802309165409771898534441014210077987361617059440097713288081224656417280327757477903971223481259936967364503939000292357316723144803960684033513003874264188161708883891847495645320000012417532575809372147470679438826398579945473903742089955519737788275519623610030070622603046338432796800122490080628370245586754056280502919970425079346155978885136594480888535908162594595862619583822084063705762988000034031720207065378352630349335316774894841004332921035415907286853720398182033634887797461510332721095139829183789341222424730428278055225041411405746600303218784871462889139850192585073233520548833958726062825771125303597711174719916949601890038724188316345908481341721974375689885168282777503120090261981593107795607314863235376629418709102087640826173658294155349091201482918037030278553820596114305515125163944813024526781314589512770456799300369449067774228372872471405121913978451069533273986345316719941687298837919044299889684948388248232905432790156533550793601456576531547010338625722053737620887291821533497605186842812546729807169298403586258979757996613878861324803023050006859878031919219528133052523093459093317586623777387262489370606407818515163357304293519559953326182137710940136270396917811578436158600340257423336863262956839964287281641456933183181224816223435381609451895140323609536092920094164002234476629188572705407245406766143161018386442493906919587943379893994595656812226198515224534735476311813897199377547591242882048503058779302347731443386565073558568872211018542391200380482945143182937400050882478373603232386418990486075697832100398823818732796235132985692678087410157236505153495944867198482127496998783401025521071910768638731575186871733986225877299388079239155261340543021485592491522213312591792982326847102242477921869302732449364236830999743730928811867884670015848676629236825730163385181418811249819243158084672355378156856814881026078321636775268655239554796863915829268805732654102625452940648521698043527688377061011148392397516619305898147967348623286908347144681841474109992167352307679924226498193123617806060685263022117128935845964871395355415444341472246567085426874810815939064964952783519538858732724669203635897009369936197379079592694986935538717036980937757369096126480767324290261428341280166775143542660580514463757884132764067204980583722653878117316743456090502007940341486769377695985941535283989527483006340958526547984018165148621334523136221934061623322655010265008149055300742419017869946511616515883952089029175298071752830968248554481275738581871899019540472572629278123216614449112568730626021891219775527800633721820762412704851529458233139339438109375099900891123033651956064430545533329163971555268183506772453396958389273736701350079131316036619435779800946245548843707014887662400845596396488326171509509563890328156723284301208334805393856066698744425678161948026032352639673491508061387631246207519178401914860316312281527107658165648797998675163184191893213973559670286629498390869848791790675569734231660151614715628891308331871127325633813627845523675157549524964746145335415589292721566539972041995686148308591204123878681326811223419303402783184206458887282272470438741512254233435507841624283074168162714428248429146182724459763323275249999545204640695858819248568994793561310697313839704828971227555505384263025612351456659642332025971885307455563511489549967155085312631415252114716288554092124598771986484001708838012916367259715126647015297856336750376684300557984256715963201142507354632682956127271589563818154043471152274096370303319764701418360727191379254025366682322705553502358455995449109554074815195901767490607244233037681828982324475089477512575996259401484064839294664604740212570414800947647453830704009339682666542927731301915363448968339479474365479935766369812779443705987967393670262212694662718805854215619629444081602608445510561807973568036128483691076915389151881328544883893686827609480403827016947855749696272155314336905530600215296180930736875463031654473917844608926764241005304954052902484896157270563973952797821123825787106943660615687352716629437780602623433177875621787317655495350610317390684294271370196083155412108463445322407936092324865117639690741821935799549306123892001601787684837044694025302882193132866270687305995267510970954442233068069464317318161985383907064622611802776083296418990028776837171629017169439235597105974782626210370822720678116551640544719842503101734637523825729546512480037569811576883621940466553939981666517968897466042523072624583115458687900063607508810339825867177889974401670709646926858896941422884845598413359676060305854687072047551148206199282876369325567575852434985963773698987331906114651550614214192667259586604303511026332360572450288360080929845041033830896177680124787774166257188146347052936659920659805417660684929300887291287123842725714450169329933849812143820048263781167004594283130482073718697501114929117182533720386343702224777527019810225992018093937301687857204262876539376205128393019513281796942576200047757133194809525564025993545484375864812668229291473413222086581850194256212419953321711261843667217366646545791411001883187355890698962547699684290814701773156348054847622361832991610501140475037468085786824227918231435051091225362478723989414380440650386613072100143960567754695367668649131245479057494148286008264774875491269548663927607023409287186693670388722462804814056739740466691757538872906679017495649998014154900080600090693591828122468041213961450965777136450397947084755331825384385530622293791446062761476989597185785992168824562865110898818510765301901214078222413069032824775835192851346602973961641941723318871373941863011211967132554944311824701386186947293835390167992678377189884404770272363540120675854286883115014521035969921650192664322030562827647484430838642110341324077161547515509165434327264285588077649736298754251913443756345206975759136429180249232476921487449555838425532982726239293823843944644495593402685800276478487467564609267064821316280335899646756732761703778284641329470252369037436703911452739428937342585282217321003887837558148982084843394221665962461875003641956257251331502325720192800281319035115966469092532428235790104736540355500214926920829524544714351543220736735941661602949196321527235850621882272579124993234082480863645379621592390581635880123646992721040800232139125965055658457526187395888785657814388937325407067120504661886577156873990770199618968466636425387109731509036157245477171567134918579055440547104328156060496303867174569562670948310397044176402471567912190694928776801580989661185643518682920803172360771328496202195564548249336215499268835916306946611267232537715680397247645702927708331556816701614055979566626767506570543668035263935910460882174270550852119800110961888874748310130861849557404471129410392868449852454558458198011534022895835576434527614970808894465743491271744144036215309764738468223765232380688565390618486181436142572510665395954026800152479647141889463414261856394766406830951429818280990712506073206317781796237249739475044986678189340886817555329795741662840325036125193252623884998527447183962002753399172274783507331791238916545684852302720556903390385640954105618411803879940722871239958506835859929471673298771612822661900840542439792172193779195037292624815606559213258537246711728863626893504121237901975981014632615850344189139098832837519891455330466705211060196693494145475698268804203160186836926244620296174946212430316028221213859317595985559450378170826599198001181648249782603845241025944003488851335292940746591344471194445297054498317285076281367330899265495848470762682812542838179323562981295095320951917780770287515577212153500838524925174477328493287659416232773157774629436597233832486158281672550323835242300566682445648365996074176261195736443124635354303805948371281584803465421599189747845138790867706486209670872551310937986633701723964798006051767164817974708671838359381806908173034695897084978311586492827574207749608953927591378908133136350323418986678707301074458593172570690441445672233918543181328124269780119355692454186076955779985801777851198686070765076857113735625240449516751036284882972343131250328923550193585123173830485948273708075072752632502226380598926784135445950753223305680314038786304335816687721999845689526520043743066912316697631320924465411765241959614527059124708551728382285680225925190303289593180640463937988699088244528757147147144285451465684373611555127636477832688521346804993187573133777449378906395097026181443784231540901563861002978775097579265778753564325585207580022932031412272726690626412854378305704051592706338764526286457263202767829580325066079344483637017998114838358300097579475414649147181267045829623153990503585177522471361081427973446681012965313923163380988137567137182509172303746316968705824016217030471537728981218227721618892173063258492212608509538568279541059846012095284391729495687754392846852120411883610762206341543669087076012968482153630784761153830258180025982332444033111436143506069435855791469791747107230239892678700927690298265273964447617423196395449702208375285252355245708851403467321001383457591794610649768126245531492187360404456876708793786006130403294218735055372845220070125499121847608637361325421391588304859327703009697446055296028066475467987344985753768163593648649436750536512054847534226825181029490634003995163157159160340750630765950834323345431524102789884381719379450523762320447201376826054894639846051784009472757694137282509728687633755403406083341087947669106719201995294819846710409783799274948621141862855014704176991716485882835483273541637777379763119707955159907264546818192150785704074271939244629515617649960122061838938544813638665445168738674456489327319945743394996346989487024390738907666288763671406353491641866801429889354767713143675491709161112939745322307197787399574914979519082193858330608054444756320392485722734600980568950401747488114209448540897860569468726528234827658904444105290555958845789039921967200816501622338107166807582367788332795172068267781587664523436833045313995507179455128290212786857785761149786408806990175406916132991607185486137932630332574118922908598727261539129713361544104857177116635060411450543436142346584065361633479865485171136131386341820404262944019442896928484731856072831823217615207156335275269857210944156883863173673185978365384051390629885803470176183734630376657440093977198735381311715165880144821766221627802791284724768716934655499056833036349074337556231147159617030155050736685974582612954155086245401786974784583972182091992137811823761266688967398925174504185972366221911074944393509744275623273808317488985484878679846520901176785065439615100781288065133680221522053024059645757320068644979438196895196303598437969418503631395382107414356257443862051090136824930215711456892208619100427483792259011693322244751540366549628821805111113004636066173610653991037055241711421988805445647814674686214745115445602917661008659987391691393282010359271914790756795863170131830598569800107091185543232439320434520197503920707764659233695832550424729894193447954145221166288373638944012752253646006340679228084832274927303919976199021706373557673698198983720265031877686703507811669258053661253210316968687499207822678226514432357159766662093711695345988855564497234666767403709532132514026940534680016514407947022725965930364782027903550856951220220731802757297328968496421500224647750632046326392994120543340913966473999608729184783399057807982503542216358398764817056924915460140643047027046318923430883508373858509321969747302968704673268285080090119413867655503182647160346742714755946170026490720666624481982540387429732257875652647026123008340543264560078637837570100844932926551261598012575648807761841959803365738746647825050766975099350611963012942202992959477653551516110417971294126422204198068863220953538357725531810052269520324945905616009520223698738647859879569360932478235009701241113062244057795595889797070921212714725234733868046257920007670363754888555089326809799613739497629246245327567226400084837134023970718268972459922069313448016574831633646081691582814056370307392220750304949012265353849923993721491919390099186066377533026822878966088964867543759781273860398043984354650301360868751283388965168554155673540153517885319238255371688410482588626043391932121376091407442137204504523113264467270873453354118543538338409469612346712693687850384694159659864735917441040090697675323540832887684584079452553926569596217269342400673739213997650352869323930220602983362655423344358311880685221786899432713673935641933956076160813312433007440114588578471697883173918224814533496293485649128177236335232770802185823922818542556985418486372593852567001524247159577046563387342767952458590943537593123497974894285397475406996549717424799451301389132437423839332863414878635882579842535518192480783167103614807312561227487815791438917347723451003871665133734818620760832455923148425241170585438044873549431347070398226169560017288316111410109909457321527007261495732620234494771487118487258003395140292081468160570763690762514963133153545240253281179679989474249131159121597991869459989991504284377188252505366953244973135167880684198635283896773562686366152447162858458736275238647547147753361741731258319578314160114087745778378666281663552970405230930675669716263501407985876855445151547108361550916212984034320083411255390345128923073043245061460820298266825713564800624893917092703758325601708895082832883681261486801539613879135765792999596489333355922138358325648769417959803943761548773026597247278350605213674014524563790039870625914679601585319955790174835221511827200790730974527706261949099705506367218960381339153335735560435173168550439140359572459659335299539198432040435296065666326510203682757108096955175520688122779761441700338090605443324264154288649764901560755804002702596740230142048010587859791472868723721899743384922559511836815471783416566831536380821227961001379484278610423763897375150435454490914605218203687337432851268042400476709052793144189525789866940517095936305372731180772484432308458388803267787131333508027808633413359353529147178048402757143267754097203885605725530030310316365058263403306978625219033655818500792318725800924856967842245568071584194217282967954588376827974813732537641519807273422024931628728999563029260285254139801706384709671722358134871772679086764712699064067151562150976445657854347685052975377677738509011401880120011167310347364140127096079339322360615081918523213358846043558738429392407942951436668422443306921495824585937580589071422457466553835085077669134479012555196832893235417887146689987367514939923461429966885948866335504057641764038939889495691944443730632584107854623260152591107024175717230975028206725430112867387359747258937453115720039012756633796484767245727558717165052677156225937613093035825010819644116487837570598872152425476732971045998810996243066652600238993360486133501934923340159832352960935702498164207034763893058714507442157861069514725644977578989999037708757533057518160596425834760767148213928667396369683889303804867443727013349264918418323297844617723082252447179995415785967925538316117845568664749317788431716677625570585330662168540027391496489400551846573316039211066149217382487160947773585888026724939098752095721615411980601623047107528562263278122740580896261046976892645059612427741914275273132356665388610528291278022686405708660916107756763769443613095366796881516986403057699411851399792895544028836399185918865178345054198216447160667761449643310693804659849585328819922179091837734886414474515697648790759024292826753904366379590002243900199602422657897148775492335764830709295242151904031424621538814109731720346851271572000664492045918909874966864860464089610272941771162135495519587346027535250591901224170404666171700802403087391248890168834483978489931967513586191435039457240846342487916300175177273019983601454026103581254474636084554417433321686803364780122841986763305492728459949174283772673611828627965286754708996940390870039442966843111330078343883116816295945814674071825664181380808668009332373800086769822412397587589514397949974163886190677843792541127601267026330473432360394797031282978744599363791560286540432528205288262783846672536865420219543810519349033907603345845239624571264329992456579387686169153990240848987841384211109074797210555316897310838626097672667308319943918806799450666786202237666184871542039330745826232671491741959491274847545070341643051146205495923973482856559802048539169436677271574411481939918133755237641367751148510104020297405683086633735342087683816468209743083198624628822143723351015343228278443051076858957246038194599682149538264358048845988785332070480358803602983639178898081411282962574154128753238340534416084095234324169710991840292395747721016008602692918452953190482447101287791759855758904345461155344042060188061042833141410877411901690828099039931831646733327237715449202207922547841300537950176493519556886251698132272237775490574089313490872935324687549233300991734589778938136850139135579311869617335310357842309778020393398311657509690763469786333565421487550831855347293904790273450555238325850438806352028007071933548598691615890400433679077125361807169685010040312250503148418131695204998006886919186567531710490010143662530354119594083644450463560485610884916850430626225783299686231183513053844518865458679843330174650369361448543391283891246123408155332992805868553318618954821701167349292359086846077865816426821475282429261102390231297876876886849344742594559599859951608547998127841238753998816780388024640484599627430468471864051008740593703050010781703031799892467182103373133196873538289926692184668618595688725482472563994516729640447282180542632992099319575600807122941430574093142364991119014475051908784101873514098278641875815220123190296814699290325602533514462503076934576463496838825911837739218876349478639621502257274870789767754092006437229955385304392704761816163585605440346920568379937026439595540532920226051292672207201727423475006131007585022359948401621985193145721358980816878778995650580581622946274745679607645001508670719844487340123193087597188109459194300674963578054874996672728837382490334832275578503559915540167977756265627934496016929454446746974666877037341025761509121152913222128985750044622241286897112914827199210954597325707374240476321640049780562457944509151971410963266076555873761558355651170856207030450492345345774694277386634936903096673801280620110097734351233948044980052772661942064531354667500649636051101477693616799269845758262886540284051780496076237367642325175263287338979656342827573955200825974463226452566846447167637010674514531869647010412644526452595530657417743537269143839802464903355897486438413061695199788207622833705524713319889757850541986371485559557530756321490873141310642302798056660355539354793021638355791225546384702116294946931417801527391359477320757161271159566385750012363500327096166717261286180637757431136209063853970476903444948346313136251318816611258727805074800383513415889300198070261636389107975118329468809804999864250934181462240942855093280356916631286936634884263578898509057088337623083501025656424795189785188229416754853796926874806273179200572307321375512683140387970826682407224285079593234261428113480413417397759625782144059868526001437262267011430833847465034759748617298366307031337779319564528835195805227800606184435833684617278437637864252921522708501594725619303234367418759556162707587210820829719037937348499997752352326180188227660052986417766272802244756190045520096465508887714260265112289380318798514908794724573359780097869170428052345172763909217957918723167804071174873705206840809523084093304956398015940101360633331644292380047628129489656061579710914243439345293640309675028740476161555625829077992348210223338574236904982004124298314851916703503481312288967358332698457885041316875275638327901426116067715804492912111254207284771493741073070325141392834269448789236954248803329739272384772829353978763158127787168608200501379437788374852409257357993438938627450124017216966423794362455448800379169121445101949796194087802730659646878486516555450612508495288010828160247330774726722890448977488550355631224213260795361917635621736580954801392985449376142378801637763364263132265000360639103549269067542109518847790955502827649816985635324664004390871881794572317110953859850849442250643064427606074721889437897186642820053017034809839653448379278351056868987552393770277396270482189973406413933328046140399818633071956507806941636338582671010752836827452631040129408399404763000022091146575434762633253661891035764232643529309269757990381807527806880179481031663093903824609231212242095360732873371400007481812701407386135777204430116559150094614799367484531352051112749520778576586799636355147854081405105537629899230074478589351956629484030284872398160436085949682968119553239685100754932908589775199781228662227828096828937147253451743244454266603327418342537430364081299884980576187554455220108005574328222244077814721724023261515892728340137639906335233551481959809023340048183987167386430400742954114735010495742442573407798413945917411592851543977178828993228296036119907719296276753055068347354850651010143754241965013872596116464779980433362145570376747547396972054762408009379168175494671435856737080177455675587718063923088710532841186118464304363655250704776860121982803356364767748066619436386366983188704954766731666096626010176095736000684869226685697134751504351385899165063289017541700747537540779099494993969485727402052868772721215969745524572903668143458958225181764900016368847250513033494631690914505432121733574201927732935379706082238793488031915580803534117441897408514520144478619829464032966202030649341071102743690174556827998426698099566294661762795854754954132725383920631183333654923323760493233857648298029976437038805462738222186438116068179115593423210812208478042753327852577518332484840869762829932758737776264317566502365032044326862658833754288274099087353420235760306717861034791332952155043817559177994582977880197960667286847584426311600454027920148819059181491803701482643562956015901685261551617386502535801039317428742360336799218772797740628397923728693249646960563581349782893120062065291660043190922860097444598820332445314238752394620801019598954315407198853949548560186519839588261356888779833482671693013379269480343731391664369504722595594191122035214115771950292089768587717452509183015716845034769768260053278014360350982438987583352710388419114843248174372885561699420707570187435921548327681102622318318342497755367083983039909086907639557827515038239394098217435895774750249731441681965806976792620634685544962382986779268896862965176331191821651076292935386659534041974089213747257091635589307143572729260837579869629788977919266793182738228518133082678336760607174855101985958980109601486230885562813130290477148597060112779988458851665426462430333457652937186104620030075713799658549344602953500931582741719283493649182119283067890101318140391535727303442958980380486618725341770334182087131391216149789962584867473460993408434316682433597522069041214928624855334082288159012361078757519214808803381100451043157911786492111358536024442223037056005257224831849914786162944395420486843995313638728010642303530095300437245195933506457988305573925813422780227862833440853601936034109344940341019109139437624887519033428969629148281989308426505202617277359256630587300151711907102469118267933176487858672483646744154758462811535560058898580539835303922514448897314329780576884912829841246521726275944484833962138529677998951977555500985153169511191524081605691405743955912973482238151658201871982841443758949648462028445060696781487373493334117964748563590756414262568814815856749077413152955483114695125494148538254804174344581662217983292950150655028140835820129519367645950340662984720120124366625018633540271618893534063459137930021733078580882817359898458015697004635594294477863705333117380279465078659397044757343179447710672920434851101595137673064460636595239222487995789618047271566675025563901888725299398605239622040228521359289247274451003357014588555297956947667332183850750596711555292702159118086842801070703401620832918850360484862091322649651067718815858387578050772796513288515276599719062469996087158072989025494121501424226556162527870349283080927930778524037442645392093884669322893703723252478470121077673650217250820824875178745043347003341353808793699349887419982321035788171493259948877369937251469908520361373226558788724287031454225139511089058452375202553843340312798220424052009257728433779442994193016456492876733414851199240169207271685728794993143808471070246555846028702749111225691726608979780158243048671964308877059045019919454761229395644085926994028103519064321317802828733189374452304468874081474521866732404313547376229416537837883106664723273662889345041595782771514521009500636930238701505225315494169778665870024978010568696591590439699529257795777115099052037716486589187192191695083313660394345176951369966381901097403400166139031941383778455618147677781832292143811117843142810062976007539674212418068619399518965303125341260843667498594407591571028414024751456839093072411001931129071755320741586518210521591525548749822849540162937428485992767549046825602725494923251731798821853299261857405854341015506916726983583363985197771246467120602075350099003976728553378909093316106339398991070226650403305762164670048258883403200312985748868672827064946506294407201100222226044615629283741355998388928091158015278126897964146207785422198614740874442790978530535268531600035768135828566484172778018761618504120242409680594493783258587111618686437655796686645077072925364254908387827316182336103394039859563761104527899452023726790703148267754701019324860597341136711676723105730343580817557929518081986094144720685934435047673845238805574105076048806047637895675982652052753890487173820001817224944846279378130570956233599408065969353126623306533455051632035475697691789426490224678656512023288764016037397010739681370451132209557937494162113089007287663279499556817166263084946493940100407272899680323458751021046797390636275274183492762721601674759377209762142229650887503746621158849197746650775699659564699540536115766323967112205693402129021218073966527775118621813619416061819539010250382011256249115144908626760726002111336973980750604947839454374856794374460606223239851576376038664698971166823974205651325123993960127794252589564377644129700489402115952552099193695035821192240967761034080988842977087877391393270450010728373869844162315074865345698082459973091958322582898525620162986863790568979669557655223451540381211361069118938753610099106452055712110343237257893902215052521696837358729477351215426507224843652506422164804163065173461738034956576340112943398424638195329298779498202707704643418019283171321666434162260582581896597902017769243529377984093323243623809321542719511563353948352091918776164190645257574574259939316971277716993818512553964948672346735132284439085109625372692036140358692856954547083116886416715874633130823476185136846076436558947055304496413534701580103102083731023487615025825486714995781203119914543573692133426026576058302876700641808292273694964048661435073842228442712435976605899748263201837501125035341935765064016800755849627596332201897784200058383048490325704826567106210338986069982644604183308153669850339680871586795831171078210205977748036028474687582144079906665609647354625434075615610420637401294508763364524952120398884770222389058366573512418977248869388832486429655283364614778667029274844437192261310312818638489715696773677929668212975797526233624662735570067760521155598078120872459247078730534879496798573697975705937969771654473279671471392808710609438057084565000011877372681357963622917467389011547238715071598943191993203544786254434938832399864045750665903467774925859122890756347412525881579532713180409647474091591063337940348573514337663319933530111157271495289724458582086006454508982965854218275156158000708214626407649303456023176557910019772390473250334859042737253035317821555021888089927119809560048424378539327921395150683024385338708320640393479672818178695286120403454358792081465294457228785465756159880893808420044197866541131183385527546609985252130195259587897376794977168290293794244133961529515649664270058675367596913714305155988466502215383304693740054385755756856053514390998994957371949364050909045876248761485787957750449664430093633187310664419727488462199501520684513184478889856797360197814146190642778917481152635079051489337588811831242477376199668858290854662391850946687483686892414164917854465618774295884112937449737090881605957944099045433475558619483236490311482799542082547087589886284457195928460178048891862068624295029250608348805521642443173959893092730814286510891146065794401735152168681836274500735032841783049506305005654824970261887634806360782443013400200547920278424706855262012760225945763845521201093352249760702989418285851341216371052410637029300876726151490154048518546264310467679034728542011462704796475034210095790561834845609643589732228243229972290231285556468251843318975155298118575465397311392669517780636127809514596293342403622945069078843077150592950327599577111864225037120687079139452335236070967484478982300607445940346727420101423082193986340344676183419510840700159551801963830255432226291655936843931068984849069425287751297142367644927111391271074610784729995776810970427498488373616868615884055541255432331344829491823468625093020609057798929378899359217835790975852022061160744904002962761448056823662426586619333088521686518846639268627432949898461453565447758860152542767637925617188601470335870071441631840627126208493054846662584189011458300396070876351936470373960658876341982025314282197943354899072492539726487490612022881146023901382083261242774837649876773970486855958116134765320755041463733557585101897979457798850527971123744126459613842861970806809361566706692609017844903242271847652877414460685975975483302195054773039428814376948382162024036182111100150506362854040943094475194593552843420347507869233599983450247792960959507686628059511011361625609884411506370335816188713813620961947305350714288240247846302321232557176967144247201968642201592334732138249602543887695230242691323609781968980737139561897524887404883673002967850370471168127413711467217840991791975441502261905122326947080786918090439855993933593221847646543525706390162231910673655602273837491833575832141073157128727381454705086661922860731202814554731979916399249794163643317940625303826192845048849388312943460252301480882715997822688311432104167469263589244292591109563742174918725593001050015724975119120515257121780135242053600591145676456548282459384105194462878017936766156581187811373168843538948208596418608636811611460027370043354319065767624599427807743284547124643080618166539048959202908999849483509828914291982007529694028025115501134174348437393430209571230214306577102512265898331950111952479561446486825718914158208998646809800583531094650167903256169289757424597401376786410672747471972496759756500785061366555375590990588644227194518872205645704746644018669008766036547789732027056575695438294007063434140979878984466796613149338780766383691516373726263311207117471889794542926772203574456352319874954737443418599510323380222605904749973917411459905376353807827007574198666335079491316996594354676158817541402939082652120676503702079374051596545481209113869614762046757289463972083380494589734306485126558037539805946714565758475827172042735386404936176396762531553476170815149555391244620106640981999558572101891231656645070150067595789879331829941622645563131332253330426688083726900127228544538204703502046733196397987778179516146553452502157655273661032535641766465409987166468712099983571787978361882491876773056693582661710421107262558909915839798031339729610365291003394272271597608623197602763460459852927214280331108164305524699891190357509149930953811560942316553499410441765761641259114560599869785116862935738231978512326607647611817203642872151938778879553576736440844330807329167260450261632897402224155344406140799849407938649301026427554258497237277217059197869596748101815220958900493228247078526051159282630500977834084846404775607613696531767742579811689495756335406334536665575343490318994586411182039731899128306212385194600517868504443592556417414519366620351895999555245499597161057104808859495718594049424838909741874260166271546034989377444732360214670385692713626116448279001549827258941897898482155411926408200053259598179413238637926447682739217179333859243587219184738195300627120643820696587434459299636140148569380854376267660398187287797369229258599549462170184052728523810651671490634176348749758242624859770597348520771405727813737706608500075614214464946957409354612304206534316726079092624912999560497114264658876349750490256760040673470098696098504351875146455607366473547120916356600565848203441012498758646701205542127695799351006597190200173254595749367428155070882982040490789027388656367836329720496012247578904780915689416697638369386019334523163418775566106955245492847347321780356164722462386497470135670714656372824947463755171306969413972240435559472589668028733347767456965871216104363839554724465675374608639576790590811015051736030768709621405674821515932508719566835364786704895359647852609022492282730515878312540704008994445547397351817699930391034690297800534754378200877610382697475464927532692800239651020810907610858618959235465352315258177267956533258597488961020781525838328624383371093451868553262484195166146384615661711415770666598213216182197695150419046121626199241845833624289460843772440795026442712468022562915537443124677778722436822604571841220203336850153082403966672522807502644127257220111443371843759365775262202306591705632131835631211156400867309012879383657217401350373465231383528737777039788116197686452672201310295870414677504665569124105853964705497469563258311786773032098754927620459450687494929570094704830022052490437411224344998834542741843611577567464265575333131231436228263513903631074414429466391792241360360975041010250147002177222600391443750628335629492095799169195893812109426925720111431395789403976644319706016143099490399935694863691816207673417217616142982433380400389837669619630297760315132169334494754758435126494565109837191490193925784521852899799068161489285602549752967189565065298904465519879729838441254115764235911499670536215773190971507225404424609753170351865770250909571916956768693149681397002849475107387189867909740770513150988566893144428449581517989209700104987080348229872572304431865035382581968004909966661360426017819713527519804073581362467676792295808430947003487152540804651741439590056840473587302489085255289541777466657730896857687116553963213967340834444970915840344312155947769950628632587839909053557006784157385370270982342148314758565944241607378578189808529180231011091037536734293681854829084641603519184480133629132940585449196907511050116972320184212475862707547873870959549509663944523182855356216294177684653356235875801105515475060746508194192683166213110653800769374162428643952699925774522291601586216154457014302747854067202675203909871109427828628478753890236645758256641931639425247135190516432621544433241937399481464361263872739927718252314079608340260618365215303899377307599027144825858490924896370566377528561796647276003248539020405578939525316738079576535013186294008238754315451647149157030782667303771882201225560999843466728150447825985564536654526096663125713240554955809152029635394702526689811131895171287862941021711057759552621309809745125245817563631578473959507871705217658573448353222992508864467238210292522654576408059259699408590677427399706633066071985873296236669134150570006036315775044699432606388353315880742314520522461986129864489655418615472479700699572931064336469113300260368307478068934960496604637331335995479888452609971175902147765704467555465868049204747816478242691794988514944093020348622150045642038198019811602920165293464748413626798609785982086465178076218124567490671227719882231734549476518765181749344599700145812865815268336496805405918019397831658038410727269269995384301303967517620519288783147876536741469640750253686793942214967305276245305359603496901838613679975445156634323206733086633263036870459399199150019757698814768243802646880559818745860356678733734916971558993851327392225109091587713778878847471898544269087115797334815950436533463796127459622065764886517323574195318764879442640697723206719042118132340638644215597133221387814497974158776285751032430983916304122181043760541927452939644612820859378608415564370853423235283020607716042524533009780492553952424038215269480580296129065581420373638866787201134606437354908788918557900879568551754074084369037638861068959557997434439000736260897858849805045877163087761800049011669124677227961582840873091439761645946897098850638939589236184768051962796999288755052103551486550948437231934443089588541056146463486500561528428721735889759098542226720007241327705909898819638690449213271927761508110460321622081428254004745374037046313440921380694263809483307815577749215076638337258206788036370047718876667521282624925408044511498269757887197143663451164035593158719141858298650939650381443151961591724537511780551160781243183573181286402065133663644365836752260889369895774044629161511380685274914549465317021640827058468481323012749667310893654445176515116510667994940763436777777094873452413688382554864605881881743895764635867765400913378212207821880124714520665666915087989178085227067888989559363424730730798476748379325907361068010891892832395669893224323309555418708366743987968998502502537873115006218434020050134071990868563848502717692024209903480425976678730456902431124118709614775620070410106877951899317531152418550535160874058831673756095514793696685021893537217086442623925171186395344555199938330282424493212396817923463971261184460538074146330917016796717563664402496823943705767030127525639032908391429416604339411860182058017815053621559740593960912088745644627763780134200411071334807237432812873856937123135000108628982757048858455025170340786350485799561930112996878485075103904826724136103045093252527396709245308754980021154040665519807735865185144314441211956193099605051170806350623205251345041057467961078827041912014930507702117864909797722741443592990640524341070573784798190756593518889305252905837619634467533684178238824312846870280397135717382116034477365782992939705156059698155413959903866255265815863688841487009342460382216796770617053304383779207489626992101525562009033558270640793358771589725294570530955467368644577608864720083418091344645433757673392627316224695194640151478496283753416244455531219280630694287686025694887095702097588456685355413016405367459438615892053563379138352488245820529526580518763789289934145776407407236720453776979688220125498836850208691615537132610835193742257713790541361108158620370954661930809843458988525596456214254103121648929354610609723647973035709311196899229902756270491712456183283274715731068471492203803563689826106466701043655668983546726663979630435553886062301608640829815674763043655294172628410024976661863117546220246551072950575699695940528447798586611574428351220731504655808263692310798417203328141780680831995501339781971753812837312988476225624076021338661459402077460058541211445577819127883621202058229917580134159003738163685229435578842715845299887016865654354460759517530880701828843123575213194739948886779143256055888699615277445336938892175093939798495051804680091014803926664211744455773563017561766607988792624294906991410862426347183288132666425355696065858376627845382493560093907789003403685643998566769250517762656906493337601851467590211306740430716877239116137933255490304131167136543120101339336619132540975642891870771031040791167092618208668818663164695102282878253081392903822442369093403507911972587171507368582093199120785085865314440542720237228571543317825748602327035122244627059725051103288135875800555118415712504780497234038026649066119840756630717486100854736836346308903830276091625353240823754142681119418441631604021160263712511295008149392144369549787597284429436006562935630323235416397338909184752383414529216996861579254200287726576311254100846753246417736909448334795558418333224451243475416127624969531464981104177892286345208993867679171516857805291352135052991783214117789547176929168072846292843745223172265227402866203384558204239486669616730371273562213926234938743890591137944683638362546080639745312678626547097097877400040663400135762460762293393267409215741114778599633182883577593361178044402867566711280264222979436931051406390520121817524971971758267870272982023008173250348630123537704736089636183988720232626072071202901917818045482363732698297489390317250696947232932984080958060733350041091921904700517297759068852429929220767926634225371302735191881356533192733653914681357509226095503370181219777923408016006392107453441421214133126354485420394404559124598172715940330873109485475226426596981266432106012098994568360614937999877596274271900801993309895620100083361322404566528146146278321283651094927005667142834604952948817017929298927256501865020278407704606589699799275986331717455445534498019705557791520038388827081244032821849866526701353509126851303999213764781724886279862665682565203523911447591497594292674587209754176080227522770924268655845076958312179879205300912206779768666939665141155101422139403594214593079557008727530949151062798582064991312661314997643748928454794851707299117849623288094161271615048078983806198265321255864654249423071337904880276715055179501771383545524190796860986626854398601500783132929434508409106829452451400494952746728564551241786968564350234384839304193329333380524763733091484657446837781770995964813803807972049558660784258140060074605827458203570612147451714863664161767925548545024721610838213462524326053946503676695160219464298427299250202461906429205202193088392483779564068232670455907174623749827191932845002305127269774376900307757760825767598753851528611345732617451477007208686348380969921987430484378900140258412334340621961160810680805625382814386218792435190889769950796716527303847852105825026665932679992845264564120199484281822057228541457743746615842490708816776429957807934724457002135239142929406265198864265947647470921029779948959272006098496246273973197986600146226881659059097787404687127778906323113010975987185907305113764673534739769595306688343798289294268771332680105461239656452215379933166643893336442091569236172828624695400722436444355292431625315965173195560322625543260178925767417636610912569357360181301269813849787032203310052087517811168276748990890087417836866921763151256433107802567316396697259261102287494536731403166437886974311893901724280460716308840974476435405638385060504676842283059671222568671715867786399986673972056077221636267516650095918703574853988186477387064596570278183305945759300406032702873499127003743733983577918535404252288481412008922143496883272273153999849611199865421587662708433469524304090020262431522362799459775009279664439538475373823885942896829625119192315691887399893420912714346171599666629261799441162405190893958914087397904086593340410357342440746802279178527625679492835499064811564484058203812728269538901577777461130890778544927362262010482723203491677928218983651577540575131947658277164916014998597392067107741201136916970570045375401451599933920334278671721409762409613266184387392353606423925862009303235909264702162429382392109594363090077713537045583500542500410702598074620510833401691149490103623954274833488990878933703090715329103684113104659621511255562758403060037493107419988981182333256911288529985269716680198396653964575021937767164000314962549521362100683387318191598335334640888757113023995947178512154509567914945122559630693375885793561926916532747543604955987626039454370016836010870371117598157585494549706190230125230523193949438946344733761612410913692714027503674000367797132191811427804868113139249057975734018572589061013260725656279709170293334144767515318082739230442926956151950989220363139848243921713975396793898612851525367146898469444588098808788256053971382029386160861031755990113928783816423692130550275197742152051366664889928189867692980122214282979205084814625170060426769449374771351027549595261035431080797931775528233251693137596643196939969378607207394636156137252169961807590093981892467349374149129321600824886383755533641173970470786025499069921524063139996110686776199214148442411203949057130944982049469583299796516120716733450465483312794313850257218028749204367065477085671025027755428584610232140458552598679253182936334645670614691640373183971603386604066221285722161677050462952853227804312890168442898390766521589453169677504120987889378238329022414292418734276284590370736336524777723927927722326422081628508292621626413619422112974356901573030805091463475061168869202527823550083129693081982779215167563206977633889147237669868124743308065731490113488422831368567487564177195484392976124901154046692655008159656357265773951544117785129143430019618543364659605043540765479969237048035376743763722470354063877072704839088308877910110737593137579970889173986631364575219384140077904088420561879756939052172165151121356929874047572087760776668814240595733867625724579654227536101558102009097589007388585869599160833912157382735394926375080426827221351794572569092090524563586918947190405259318813579909328401693319874056469649947318782858953743782036361855893914271764580155773131288909014707065186310124989580664086172064448698296181548410438244401995997989503180077240061207427777353411246006191051241421941556356987122508483274778128577355776962245649559620128664531621653871895660551895144279085345359446275821321605330799400093851746408904358663361036344942406850033248588537577046898480440483391669470600672554597019062137838165605219850545091046679400650041535659623075907913578728543456034415745128537274158066841596383483212794054747423556052027720751832947382570823147117814655245337769576970958990675130288237142578342693451671477102904412288743371525794322721858878073643242660530379125949877025865761675183162610776399012009703583355398983581835474235405529383762907866353757835602096969899147897256459402239463061649553050630448072761856783959693426993413670986126613323981971576525359449209366061115265083905350195447911292039265214278730634530106526067910371421487953015244630526095991319630774315566142860705936426169613515497027527750026689473720311001036048366563354983033198883850071379127195527476845179217350901654110473987749803343633103918613251340290397468649013562849514062764225625203206536918776296958695233019667256300181611708282574358212571776445606559982351615907929217253031936748497060899607559031406040421426513948560261376481652925832460661530095365906271577139627726108558478396852419596255155087332368527392814554592005567669852567447518736833051870508157332856477509878567443905734206656205897223235596649122611662837827922670928816483083686147056415285589210599464253068380372223060415387323299280560439350999756779403374871177589976217694289197168062103116899695399317803413042915544683156425670014588733775336852889104180978051856498212238508777016314667228994985919009773968143811022100378723008418738921853407759520413869140791817013483725656010260794663584859786539604775949999565626182466578897604174153852390865219854922652360763586825378362692892039894599180644626201198620369497472953965199113368685277258422430903983207041223343715340836907177513356917913044735653813822532792947442578747588063534370896862665050605024637978259440890113271273056701491154855491566848433836639655166460031670126542413291203430288176480194974021650317560383896503416103074736003638640228763464917576284560981601421160637663914824837683849221872805383782758212990031068554457666105217572330110226339501020130891333348705681680372823814346958342177150379536364307655495380941055759845816625824043256805244169735690318494357525011629636668545838733020011786540352729172535845298603290678710820422779574878226787652802345953896966292429508157385516891925978486065810075035158571398614535516138818415397850181325791684654259446240798510738681292623788686626546423685732201775981060621288868376297867086281618519579913485028265344768100907330394290270355474895580063950078103937267693008749635865388694603960582181319602921486169745895043589257201951783954979779937239032012670199375088713926321733440082948235899703311660600357365168413107170143541909679873214110997498340581914512492390688656334339196828554096775010133480113101236609943049298355007751333270112091594637337584337002064746300263307007944245139622288573901369474691369224495029786905389368445276246248988293178773351726123439809936517267493363903283737898829668879703508404790453297046559356377666827973760233584990402613417653493493744113523190826391399095151144475778471125821612344297060023114817300875796716837987353658507356123843510547383671338292063455136533091039297962164162471835203275666461062857470530406732794762876138220987020118059924119779418841725360075550726491276685499417256994710490741809431279655597017501433580502867708073338789911543314836003158955241921467318849531423211414285213269360620960105844143745899226908790547121542634538048438673202451773414034281572119582494498250494840075574502607020269667442477980304506466733725045038118054222881744174978042641093555491820083730864984394804834715369136919340943130838269616741847691419220614203396859044276584880968264204913556532061011227572728217663034603973067328618356856096954768675905375316731172202368408278310303241928002960496826172141173664801250649726524802752037526362702200191438833314306274184220217892261331770979949096177436694574225928606561946417510362624351930043550618367963849642913107520526385625667529043649347764802745308274050794164546997270654822980289156858547968148759243962638312406439685231264548604478676991749471634384839181612370096755706448273583794379135484894178235503024273654691630720023244045336099389210015129109976924220814115629494238605117444200265777807068877331276584493521580834229810419096504425298220258236519820147950257403750383283873221122318807543692538827539652547525221154982228713850131621867615285921816309704437441391077928290829798412153441003448856495075477788039238800919694704794728942824293557155176984220335275196894063208741782659956218998226180565257639584974320283006890553095069342292179404082834580544114931453215679266334046766316762813617827516227666336281339588797711380617689037824614158028889887982754969952051112386659597567931464207435514236009565326844296167065975063503994755638886255837932023152387639324320646130676668455429937866112260256139246248918403317524425792728510353592987014006469262873098738985442371873510900607425346644333313682892273964013391147646538657672608732911465603289597689719485973904894592569364860683501760847372277999740392572296365642776381910393367006831585099378828115743261985458415085163825765825338910843307834561155400112620682632067180536630174462722642531186734370366613604168128665882917056214850443809238774445086773827570294912693773906741888500969966182282562415990677103104367069943220104860474675799175210012834641815401524267351926974405436036436387242708644407178105204845435175254899246642832051329496406898725113924794664369142130501524965601314954243478983863760217431627709504162472324813632843411954296609319307507465377637489978323937964643517611351501458235237959944417233688016371833908898303833481205317522043192473230705459588898850721784798918584865659901380484580378036031978950638385066048622454500289276120096777999714784873750639268768901073473921398052807762103052288953135240455778836161374605677670464195576156310863676326243587869853685225914457249329518178496384844588814649706824424090035274846401209866152932664936461404174875548423607262436343482069073091409327028686843919687148198992761211087280172296182051964460550394547235281704638736463981911092867376474421990277176563409208878287766120175668417784323414739399910994194320136408719786071735322114920948279466188824618835341112029662090297169824733252399026977272072810042419102734373933489798071786921283555964372451229601117531729833314777093183779940585641314908080806264914886701585423572371172861211598820148045124691238679256681702889357339838964938675122537873413389306469322244604564191250196776548192098352871669927673048932064066999618897419991428787996417579727869822262857770495475196947480076506472501732784857291568691388202238762108021220917461607601467918984144441518283283145393813790822274995106713641340887176915900593440388019262399538843294656750356216827901575429679782251044060750732517454661797746570423540610309786713455669750535243057537394148761953055634747177961951564189095255222012850608868523796876450375543706023169387666730819564158585008653235561457026245612353854554881888329403873309705905919879483702616798552029440413240934940035134544534407175313713751198573173856765961787108117961999559999266211806358772312679712017552698421424915205770898996775400435135152607076773478582093840771389059167815256213348881426803208876353954920993325123083308530960073191214178124452283699534851664096426232956506140033007397574098633903300492012712450148953177176010259908156464737832229214108026255879594393764430173887110027445724666704281586128455364383989970639341321716162254088053668007356051906195736333139858542165075154473899709275000933252309369400950631275341684743974161058969233402355064072462543755151511400765377631791691963759029507033990042822112867605404643250826880565019919883705018799017723809748072891296129690246028936594132761197513483655982961435092430395906397270017595141939262483226386544210383822536325504646379488583718779210853601999488370900773211298763835089639977744083089619552861053224318791296087357542193282635926471571611566592851359668734634803041122182693678230319712938238451503682750294852309320078635835823908279367760000538056931666390452989561193989617941254822098717276309394943176438487773622775363219525284317742033175334625050190139120356935861833777017260223813344275912879119052880010276801914660246168232631110994535497553626180437543814818717542569544633504549514236089645686419626004710807150919449414271157637173739789085872953806762291557898802958947062719983731217398879648045129297759745350174263248257378702835531101601443596695308026990515761385987097594117335043775351223457073857762058196667792099305615306965229252300991318627355638982639268304286241085989806763660250546926129755095153250459595814990013435201793916954799960807042932889737209578694858465238943819216437175837867957570015428146663494618902329815232916873172959220656549444660710453978919758764342251265991155808748238279628321517206111588917431310154150702417335238747780785095309784413638880855307709152155579247223659656184601494591845026750073549457516254531285252602858640204281915254736975511770649703795141974536305677887742514804043068110943660582097024022344050118158029103979863452539721454674329719398781381868891774986047028750787314377416497996136024816682945461144221368930553923645848652389744797265617735721959022775944995102968451587124654239682666764540546048699551141725186831790700940023947096116221287219523217468082199173646907495932596848007486682363723391785105124777300158108915702046677765824395948986614137558479181684925221149492252684301955615042037649023180436982640539974727100501680197024352668006713129567364477878574298367968582800368403377501135769851313505929442619913361410643569352226387548492943628139940645000342191393322377840166034981086462440413571577829783444312521954723189401278633329299850878270212575984040737549476609443267370954477700426899964730543181191045751867107525727134019570693043767334559894052329777295127038306535328167635272165189670845965932842205325973217808336197586979335840566785141416714600376693618651542925577691840549331244398397387844053159131673241049993697364529691035914520393893573137190842443766370941403928860985888587259574901911732355356250366502706720365807684033474768944236786329948695922337593382566309868183444936035796220129911930463179994079802553524520485911888790131113021408212943781164604407400571808068943934240459012945580599405226264547172800023617340943123184942918704999197350974009032245561842503887552854463634031190606594392054247473795949262540889162080858329234580670295520098346101771382061307797603629922258378834968587519772266901691664063094115131610067878532873049024014612280053478910033863584328179836888814597533884233324852729090052394267828332470351747150320378593139616491564836776143841537124080828126016726506336751845079173048427671737988379180328789544446096452467125860391386110756036040819689548110776501979211446144585147840078878223306982459304027573425484952368873819355364390656875562107943588451031159886591944173378358617957782518340559163076208198233951682010296800852053441456148318950014475029275704738813401255211039078920741158509733806183985549856948039240175905863750517786707275453407559274293338521307269857965109744220381845025133418447575732915806095391203531575571458617353556555111508795378879175936714787508186947644701323388671316278861333816620278339460673448295017507713433919848579578937884716676452114272750672687887812313987807562157645755283552854879003626234310233341528096399104014660217847882419647732098904612911457862031521677228276101281991853215051424344306967334014022852510121641036468671770207192981084157882170456478859881189092598817658490110531074361750743417317053569864491993532074772580741357788592518282528656916187962755533304272474804581318904976949324734842823911320850308988994046060223840655970802451362664762183600913701042889550343512106580129790827570233122658978453080940142595166593455899604062964874549523200779282420000910529503043473250679486447864920204973910524256573320408133883199995723019528833139006854798284430774585599303535912543172856282811507224953472360214417524089688118249121831907707234524400166557162397526541293580916358191629849557789568389183018644769613803307829469818834437101783228013926248104372858710151574044854939791369968460045506998420759759434400732061186856337716585118025363759121746353850071118201158856131625242521156224530592237326653431475449077113975244806324373306432934136684204142105115215675979302956512412382940825544879628617468895002525426150405940661102648450579499039063489602615854533766400960469309742124165469111757665202555705884811712627310382006529328561990407488709322706160863197642330679017778915674842753015003531369947604448851360401765407736059544930544621491767279992597600238251225066031262657733495018204574510240361616323130007203200668890141283019993644262734005825168275381146438878198026053994865226040632292146813839405762724618258341159506533966612363778874803754284707536793464460417619542519704311005188198747729533965955569554817044401005936165017179763194554035531464697284730977750072626276583811774767117805954588400529912851123581545425116794418427463824033450630880510920405187564805069224622382909466836172188112337681546987396073114526314848330907069184887615612358657341303870227337777786086968442750910131272662342031892995777608433241910461425126831903087839870329017580594152347704614129737848710655774812026088854720003867609232937620058732033749042184607030937113039098653182293915482753082924822434072485867191912760219256565409558108310130893208764168482054183283974885264485832137217602836076600265599481107447926233028234020786535442543825679323290353199725416643991946694800701086322497879077814037832687713034414387649366565294548972892611681167454283677025330904906716632204964865098237190822442029087051737117875224681652206689209226618433180001498157355332591711885840852002629292046806604663649366629534989689619455715509311538798056188514960239153600078966578009389602450842430384400397581203651866022928783129985760444338669755856553555614052954997112801626346045331592530831465895091228533772447540031818373427730023148066908889927011313133980162893168325067100715370478871854118356368039899815628584027546941475320634046868858601135259969231047099139796320830420511616333672659153616219947840442074886188089552809802379979834086800818118276368377555843639241724444947679039449982500241069614287073911157717505529770565495630014689290782390518778260689983095235027982060925659009237075831832412806414698953954202056578042467378633520541381711955842807887044249559595587350061670908542078669668874313288771469979767794358165400765749041105770899432615970243445814933146314937586764840668491675904714008439550024581402472929366235750216899511605730199701683747076928558340316907246127589389315283432673344530032297638145918549006085579830870446064611117929559944404469099679542478937602166846445701257403936694200418340626238078514127300272135368000461578118226787689152656579445849775906397385120840890496237853147495806886286135143278283907098839274504747009556614380932350567513983365543759848760837800757470459211851699421413438099414251296560484688753493841866290579597061133057873112005157182752274030827406160076751798989843153270043725748245788345441771358679434421452069507085182979398681472126584687311669956134461985933869187899697110864362430317727633104226554136253558476452464025925087408233543186204751960514229455944085458891917427256740398267056591178912942817319355763582096768740411646221689642040976424554719418979878460250898937347730517169082907732458747325261519412085382286449742461003307950807742878643279859473566137455079703891011124814211241776049621209184523741461584639024868558218624187927187331829662634466475989106891565784689467467063433949064320172794552668893835736063389307775772435579988039981440599267205899332472383530887308913252158916912177914739357618284859004163584545867742511569349796437372262580157358212098888139508967802717004146753902871068376379174765815599166493296778579579130229814328644339518314470006838416799330810877955906668689217353415257185783390867947100777220460623316794316917078278690432699343374500325479712783042666551487010775602947621841943583820757780993714730113347954992575780777393987385267788735249673115303351398698025671484035407535110879528760088039201542107772217118002922082762640167155899345738098883755389599158061528487137143250639159204691143579421580374959063863675814731558467453197260571406871453366838461092545006514556030401143987055555376565630292357332612441045388977359341261204757211059614059466188746447011952805027893207615791463289799428201261237443470674459575499027894013954917909328345193758735429110768010488854996147323167555440815040996461964978541395905225138101969476876875254873632112760901333312704174568576746915772414108311561101591470448167890996982504698504145801320250111403899565164589747464682909448630800315197091619367780097738992824932286492129837640206080968058057357007214015801706912297372233161641338673721697869637727469551997081328516998519674156491201921132927321923761667595274596790921518772006949722061281155241286272855531195686993697993101713061378196133874735099104060687883036075577361325893757427509418822690333515797836730465929430784574059937907685210179348731799765271644509635352276724091182754637680234611191419530036957530608929848412244577428063640749678638812995923637582371255694233251169394001682473362809066904156691311076317421194276514282932522118402951875015011579392572144224494951692788877890802049945834364891206060303769735724849805152749668750485255391484058720508293938434242538161703629818025489619998445440538618595304253172959319333357784109403526497914482437196928977679506979443288861608729238997205114957687727093894641816835490865806274366362608815563895034429508551145796130701992660800739369182681204016630027335749763907924682435650365657526120058771434668754398388305454700423797960439390361859600473837054523111190167342010430409205961008048612693607608716148739971204926934541618848671432710495154964647558983016667959118702222151332507734274011973691166688019430319524027583680381866907698334083129311542288019426930911309911235030875811200236178871150322719677269489021981159788706330452196504175856790929900222715455963253167328564656520961656931761211034011174055144690972963223405143562590480889090575192739914594554157661788760463419440214297066049867858065662160272902085679035540175191846438118010614746511434058470767615138464976738468121288100635919544253037298883299930271691757437934529316852860781712836746055053904312578757430483316449201581315837481094013644780420163648100205989984026104330418358739346849557779881324727493823883763715346368125494758087703322359346804172937247411615673283287393066385117998719962145213822771544476887675014055861100989633452788279971511916798900152474901815481962864841830668067195720721176614403576296029216745993864976200468530989412402825484701854178012706536521865479841946093674365927310616638066285176985851911703104063654717758997825296472262044326084907810418366884525473819665296108207989871072079619682992482936709477081029179585327850695720797942708915206478597409196798474049666141661261342941462156533436256064566524996625998371292798386178869549923073727026440622257700624399249227183656367717673969355592953533807922623285049850153296767462584425687739570953830497658316745309951138435467809504777089845165064649007340506745065677234062420437570250017533432561381064840544307050265702639720541578123311492247766943351410152457972088214865790013629731761034572852347632981898089986766042768576244083374729309989872557970750547347774148996774004292171855541655552360682372054678198358982349367651888715477215633472769669104174658312405514291339539579698984881455324583888084882657170093004736459071961936132049935956998585603624134098681759833311152643064918460401079137316298022963676179195139728751051851191873960413666704923507082746840430770073195339708144763012763291319417189386330085576654618260946943789143230844010533246018062907030602568522119499024246441094506448688747585053657115996460110399013230104768601178129644973834206192508966771520111398398335463195277806876662134791573231744237277080560166434546926007254763511979169523287570189897628013561228445247297187431052985550145561683473885153425331313410153765290081798838181823080136575744922320408885793416642147976053456655871688968305807230427611264426639382183152747570194165177187834336660334706053907220728985827502686396510046559192546140005292888497151661671894806580997855109717382978744648778539695838492191973455613669437585696692404385584244730591491502753122381808221059404779747628013404524475602161411506502357162662788041822456276639163836610355349728937834601880588246499996432930385690453752219656031576645364487067478820709828768367822723773594872112204143173195895262415246473700259097064439548779279677340470527777928079195760035698656830463043990416356992582158452628757955486029809701914789634525446936428114518671090995969830984382851640509527257898534174304974383897163013401822931999542066106337026644270039394622208702534802824995267036428643085617282883497950316769688167706366486745137513510409538136870430004697650053495374475954373675172878550658134174230354839346773856817088897849324821247046445778251658993491424110203887149527480305954285682180650065050461596791621372300814991324854253862392752512831184252588618323761877792437272180616010654084731770538987419176796416234269013008648598646232080305735811669705193424776829850579675801237055971687417935010572381044940329515383988889272974882488190268154363272168424040397085698315325185199005771176874841076626304668956508442098071949938897519221545205111402644763504345555508223025841820130470863906975260096728618475670379944259020918202921751039237403673539099576268116607999431815464521007254916696618515083774902952710437439219174679413726564491255069500056597266100162897231566342590138938147037326363553631778079590042892783885042515355816733053680284320682756729800377830353244244370156289168568717200254961076236873870219035004971769415089345745790539282117873158909878312777710646108135107684727084631157232741066694137506534854230485431626654438881851292484162444148762069309297695504990093032222610478392402319369420646161257735329322202543568007074739283183700412301957576708825866870832290619184091306783457472324450839426302088595542910953890302253661890821288377307896074698418620873399562830786658266428778236609107989190807779824985143634774302808606907748942909440295346646596731755280048940986408880797068045283598750136638266485860670725146878148030917754098448035376977258009724604667325676328829209175405071396863882135965715510927655057909731555384668878274398864774122627842758037662059909006220994208670184552960990165661298024892984551820828545879007216487621057770004586997515609203971318991589649190938101888359865428923704563192028972331161881834558898074863556595007850386973656664457584826495100233053620380706237529583302754665032630683884835687288623505854045169923258249771280297249109808691068310327531205819222359417539113588421952919694643841995447148777426851627785955197791276855309654021418170276561498479954239301854919589875298183973298761541049549728661490622204972718388125494210604761899323126607847062006913768317279475908908655188863901256361391734081147428764411495025297641308546503301906724864412634213089544528283773137105361173037379284945865575238613811674173801010432600507885812076849485248271813925999904677730194482752130015678803179614099507603542847256969301645290192319816179449683667023868175742808114300567232900466810345478854130541086996418389024326968588708790452362111224992234807078074486532320614484936428428860451082446475429859318648721390416743013649131743364027087389855358777963080529241532266192281647196667447738545693135359506813827371306540431010687361753364149356527283209739073706757820681266741366935958312834849530979062900966933878429197518570894590852211713611749706795351137890645491015379416217189488131092875702758373986972877867448627847697115504108916995108512972116307835715647874698845402647974220390587408511127163761022764385482717785094202612923128694329740492159782153914712172514881229814432680641806187333860341112684171496529990050293927884233880508730803371988191551632282791793338427954600073596980181841692926276515236823546028349654505905142802177553620345513017960486117016070656539444853085194011999836247685474271526556809421792374450584521317802603063640171643329536003395632025022965587617934532258198884020863139470464114837808889585833795742489471544823721841567557894787568897907217598521403095502546875260245939387403394327804514611245022027810595599558924548044878510391669938946868320209154919302839048436952956433063454606722398531675851156941723035001203433145450952885730690857965954605200962747060298415417704147003069974336326707250668120255154457166233385608263866440077661345573367719795495708273197238777504211064735524793288366290809789029108397989055409719412932445227509193051720921453717338844435347827109423594032920079063792699076217419427552262682228171661595052676902785165209963367103363307601152454666958301926737744873571817000609064750557371031259819270106034034944927943932684287012776274494743252607377287098568460713738015051247260570430905516483721927040512068750487661189475796076936634459663956316832984896213950643284636190088246717876851407599258896600897394763019177768468038467828327755426343486010782899553731351375512508005119260516027532496285986686181589562122002903986665245155008041187253129360464425997327757466139935461868198514940142579464458690481436719598488708797355815870720258733784617880836140317275833280048912457365527998873254557361536591775640260457531224691875893392692869216206249409400794213511122839162297779139174337735880075996077206152100159261219877885224190489043975949281030771519680917572034896328119359529244031789889167056631522979665515284942901388655370531926037242125477751391896802852092434382542225242445007212148022615501003906695630424720410213699743806857954325626969729248420923232769086552427955159422608866860665118712881515425806335320798938048175160760565296520946868291428901487441120794821699430164297653937645616287250633907712527519566329077358530045811501298229086014169804820812624737562086480766345120576778172757156353012847287797234912528727813466064724128338317298790041875487570712324933838872956007586010038510577512211603732073089200381465370758576537466671126246373150082160994656627896232958891547542984285209730233833513968704958397043855366562280827010594573395183452952131855536278483492542991503777098801873548712921320500236554012183669001745134662026533300226824095976586262953601793046567067557524795634338465320950711322987827557132058493071508843276760064696679876744322835965181383159249228870390025885995966093857032711756334476024258008884796348450668858213135589108695183883733637240049104185381354350299978139694017484090483690007249342845851416589182854742485825284933122470736411873634891469359941604360164836147021139613365739255156825660375010016360236476306225696560057504258199349364247827491888132178352485527621448510569363523987895815778035830615149830119359075660157347224645422998375624441981702349992211176799964054025861232353331458433787602546363170486954883325992672893543013499167128376003800081465772157225639994916572672975014234546908200593427977097608471214764877855752446753487267039277342966301586943480278301949047964281098396853924789862965773739880902433115831432317404265033873366820779193056984675511776519547835370731480767525705551376182630199031645969686492255932758798748355572860639773400490399903015331496223642796869981669426178264737791877292957739868271208874483657065152551829521202392719473131076613860153297966541258528669557213674342651439284189980528725305288522788054745270476272526361708388353594274562475066392400597910349182582367153975260384541677431827801974413851498522810285099040934612237872233824943251346796048316566498726350959398153840277453878769252560867344629113100309020625974996099887184630129156540037630793411085954172073842239984172031611012368977687200001535795517141776519003720105485226772291574032515730993193630872433271787130205184350703738078348395449130433201834498801581244414950072742802097620400107463063196678600552691832473567157890319448643318222931508117337824119384502620616794986571137947258662315987943507148584672863848396695061188552964015661420226692137869716468240780976628917332527301285408370156534130486577196420108224241104026668124991359526288824751478427510432120815995323196812426430505974629984729644768814508089052184310068863384857915482658245911034294638739191130035545483455449860517880125675632751006929294693052396728029216102183609765592245338554326302437304382640467401404574693071014114997823067765759233576757985619248750086272660939952431830099551141870127819684904431205519232343196995880910953858610973473177594389589372428263633528207474641188999548295559036606386678629602737070260550269511020143309610500736799497946475790693703867127449434335328348011658903179922287967871821137851814858656966449154123956830237420016732342047853987708175927607897596949900879385833727838741345832040209608227844508781095890401955135991022325945201990654042810397326471183661135891170920617409530709198501201798578549422644800199152219820609216605474678365929115028578811879831560269777569183174948177305209055098751594176610305462327054805881680236943320103470567595611570844900972413453089016790281756610727579957090012078806922825465536757990989630726733676812387919463907653806208299231662701494196157445431780831945392540841769428448525025122812283786270708368001172633437190745416411251990315524985842506294763443354813861591279437885096479548239286827393301195736745165023431519442241808937591983372593604316506890665801722903604728031746457780183684375993702015580713844597711259371231818847744652697422571018378911562544271940532759974614795540084614766737465990747356981852692246365137422641430155752445341345238533620383307900298056400808323283634539440764307913258932460442815159115101479459970492051473268947287972920223400936476640606629681352997031875486532434639925647560805203402436549769718509830639404209225178878569744938698774241709462304567202649463614396626890676317673323708844217315398177089393076040541393076382464491052145822450166372014841253765005923258401938448061523052139989384854234357597690394203289185929714970514506310882382750876310884332833381926612098222568391569342750533158760837055496960698393621987383444372294228880222904558715673927389298894761643550466420673735699676985994123296379095420932207359543873207189890917975911976722466571287943812546629784229000931120555155435859034975118291530154041723942868178653309040750733514986851002123578928871142158040209490225356189250113287674542445297044106691727745109563597317324962652854057207575373619262276880084295448972192028990637690990580142994077924725659268131336655925182519116577938974808055995248110626372606158240559435358571134204524255194655098120729304064360919526243968314263897623778172787332820514341001559419455615640914113877757729991982051418203578203948928008561115303109595235195407544888919919375612293014731330310632850328716624238700328478101258562431683074726809058021714118539415895556507848045207435438327397750766306027671607160121303329788737227469299162602891999428413211809776816024569635592419862673755495360141280862684522501820084479872880895578100033030807375469784542334232548210875083471369607468720551003100726605485692872804035813565699662589498945536646162203749435273947076717609242029293902423830102821057455499531699370235478234901218127412191501943192994889883476324679522153560779238172544811799783256640781861870925447077622305608906628212355544238855382678614461312058707295429344632035651546739259310055162284227484307219705665567464765941834937722964824286952228123428515008003720310187327075370776979326775242381773379211020645823266067042904054012270167186151094992346193630385568353311269922407002525834264886955924980057457002643990307657705153225685956056523003995961627178359743370212098165933784707548035804271058921880962755928474591561111518697426294047562446045372308800181124460160507148509968633801719182016178031219287412979676284739104579199355065524398898385648742792743124723602714503268167753297336482300543219117042204769039232845485598555546837396374856099368211299861187076913726023362053785035096785286519340885897922434228185084655228927747941680397774598888934164424516157459662227536795769332662652200021039576070410864383484716183537210606911838867213808320392089281130326975997274316929385471558247149779662551347898010422909799930756130606622418950781940006723361233003051920981970758130320119360280220948640323983420821663468696837119252397614287700450966083446145771705826719125207500923346362756544213692189966211276088949272357349502538235676503256118134443288403090020991756477717314561493904535558183902021731113037064956054477875311795131123673027276283616852575867051727499921614517073067907189569366099676273553021296001237792864894799121478984293365377384447471273779884245283852258578686712108279372221759458748272034177588886869282637054292976737530487336639899157445357403626110907602544019634858616654773731620745479989184710574492331714745347537694688815113850067758558858097300914859431291340956970094107127704425003391596445688503886184560834802727043149776022781533056457270966980441089569077453038622575369328105485028153469937564707812812192503596909531362761811185201106368729124087749663899502428500702669263086764654673832027075641202561091728692402115949739265043105155021898249340392028711245290503956179308841934838287602892057735235343174390329481112303209771865480916364983973025699611359403400684343165127992294862211354532582862030251061787247316730341441628291816419097439153494514889081412277934757388505365973988976002038855600353005789202889693840889122186677462664057355608316870510350544573616917266217693482318344623820659020426306705061741152621860096167923746722788784913407217141060176836536671647681389586324878378761181215801104226748860282116576410636321784807132901980172525645765077770799814502710692126532052697669149065733966015502959999990772537008135166120064898465024985239118755253976461198325931756793271202399559819008008448484446050865022348205294247956899886203046305755175877496786604744998295071554807636163689712530238696142742020503806794321453191303698926612422593791411176611996220608887089948912481027027287587910605670203380693994747052779359094896271603229040419588731518297928652638414769376750178800527754433171212303197425255245839872979556463978102123384850797261397436752015143680067685492508918739255543187952945821660883715554554724765566503006861156597977588108874653224535415375821994653263675248071139945929929965019313233342424008937246332852482678479374180384830630918191730483622210301019720026864105303884188463129595242564689173396055833469655063371371633868801328929452456075514514528153766011300852416292140980524008348081608681431590336106296097491668580327145184841715578802771628239261040026463526245994079993067757939679968876409317671764263022937633322403768980958628286939835977936986237906801183535210458929080315113261014912133889785651323800994266375261444830436420227909696894315540982133356836614275363295708282281127134113805234793664764251375301039066958767724191794437723273972836634344710106755350238759483811630619941086555779672273937522841950734394015060044546698663016930915554779373930166410039144250850900931635990671246805780467854138260439414141641347201609615408485117776045006267200920208583560788527258720173450660871458082156958937654324917400767478739051337857474186837842413988640485406016514362067119636509318896631840254728704822810759564845550988607670772175953546783619411318847356674879726103943793667723274761692663864583980095486185933837046218697215349815830152568338761658810314264253775335224185914041034336932353620189704401769498283146768056498511418540836233767111879898571124811842603987161516517296406302617337131452525707559333617016746396213653395859009406602625595825067580734487322347435037839553425105631532876847238083146471274694120524573580683477711742109646656527753854919139013860606349188781199773434893765612407975638798155899016488168982649599964279896180602108966017049848626639317727823500823032709793130150081539629259088336882577265026043324219585793839173931703158812679857513323354282549497907479407100013644403946580564046338104941689617596168652026991703668343125276350293985676102141828382595692993240518899873498966760039321872823640495934027490633236822698981472598598205471274329304415985695736869847633995177194389338010949140566427491460913580526416925167410743299849478432922876601032468872475210812799283760559992452699616469742966987828006298589007827750968277363786772030367528368405914124825181090475276273929622233054897447304410968257231638347461077644938679419454372460315170594710487656964600277111493107171683819715531137754954612759180822788139667600749529367024359009662361397994265237589189780282619131505195357178431777190496501565569431000362229312359104319485003244823373620425725041084279540244880685973821141627662154181969553398881516918051172694843475891848095249922068322799308818272427526984885721354349443289904452716976304019025448706655651854516361795766088308309683383705604053109984501945141924507213571346441362333815224123635536760513188495966560693653881286943777449529540715798360417965228517274690041494440503923865821546522509823186303134935373796446109411020901232589911741612582086259437288721275023398756062412947427028358578032301675944171028079736221383804510059576141403894040749216620462935322331919449881875215147953035460592739156638336491577746585104659216175278893384276236575767210194365305085955952929714920054096976634210575722029908929960125954580841041718299320882972557458681947874352115946729028276882572643402719664542148733592599847204322497123984937255477608662268179679029683846597170848453620594881713381461447991732982281064623440888027366188276092409034491909229157470861042663567326032956697501677216881334399635968158348015799756551054039514640089485036042118038307917039466554090392427388487380049043548287552099573375728572273309002577363636725769516889660579772848841663338463313560511152876946036262075102096020169278399444708123796038668251408687866709661297194741841247171240725921507261641721020828154625834279280467186697711689416657843184868711293960181580077072080023064267316423096198146338947034842423027414967021318359586733151461686170077235147036646091775642718575261955002326658555041280075264698908475145926237410839564811571915844747762594272398978335716996036141917821411554272427737434683853778102094420131455342762895606816310484637215467973617665281487674426603470138191803517319768925056223167560917367457718565114030627256179688945068837022815457460846586612890175342860605707262691287857344007025144381824775237879904341655161955686238679049073849642373665527770873898283215225214274283278749172943432031190268470841755105441029663312898165652609200354922186409527030883380776949762029662527259469669372991818220693871847836789551868200402717161386189379156140539959137082596333866175631210775136817803644583546492523469235292005563674877965030960484637023342282776637443501356300707063023458988909787589420029439972400958693101148901429961135952488326739884814639766957676294852466938909997135151608734633068889206187002481850242110354374819086592139627715067054773214837003697267485129036350838736791927763356505979972507961159389561510597796788964811740511290699119594833735084375837515717690976679719777104054222146969585147278612257228102811732051640944373553290229675550475049975849033888901533098741934621861873165028334663512854536063915967534657021537101691267757134079657463768947753495157448648615978472830150463668107076052950423607177024921006231449945320095996032832927647605525672416011511129388639916964044542606259957249962140256589438161899634878606177984823358243418809812186474535290035580214710808728895510597017158398043903216917775765335851308227483098432123562215344980977743611040422859978750818154486632071571763853437422113073438391203373887694350059729641524872680546456997558475784343850593813367254631137712003614666870579573166068870749454041458649870349264569740911952337660975360452584801377010146362954816954486241416641869841560664242444878884115504997996517061536342827366916135797086173808374462276718275618588788619832147144108535628038989713655229150948984999426648977708949012649187801314062968246590212580386246393224830288428115822491040185224508189875251607857327653283681320588937381393354522891820397279773720071285206102441782479028701055395526557044741229064824412600550228311791123557678845719252713855592484228563185167569042857167028188918248273526119969647335346820376316045958122505792915340337162816453002092982965355607440899415973516830363274405771314468404288878437899548002871898628881211242457632300363707714770494786927958953128901991816682183540363843594473769909079315056039971567109610071966375104096586524219994768678651651702052186540823066353793808178648040697607687208548484508935667785364586003019671396902843196042155494292380005866467864409250132284538368089524602133992756322555823159354468917843695756232054706402586270980885523583329362047196613931653885515440180983992987038802561200638289349206965102875714555385788587651384253634436365142237013824343772269458773802571659374548157001722843066579774558982532270535075058195971785537872620996812412179665441838990473126495903820409758058161685430504720202905106175562801206140624581463790245582378498423640162928481982946433402429399371611343711282296025522136944621572149488697575611150323592181522245190685363496050809485873296573448566426629117096656400047416323022638986368541977133063263686306829185632335728930065475353446508933505156421573118940656036194535624064231261628901454876324035907325374675960693277552757032318294045763376828466522142764429515251623640396017350663403300532251461442618326693215830695791558115044224330208006942652275723450117819886662484187288881007137441001678971575805647382644767640690338317788586947404121650107792746814031727584354122416058131458440281498301822023379082102127274354859734974578406335728869104412901709720233348017699864854901204074610463126014999894579277378652659687036343013570648453469297016888514144225683658814893008253177876787216872816921718895003351441840939285014551559118874297067086122302896013814601091989703599473643022319744533006143095876149930803023430581560395501247817108377149524164354500138571057009678471725773613479680471756809152428986669950211180155513613223955267400360520969166998935591075476044678672254668922498251619722080619781043101466439106836264463821175850368876811055277918463419971163125351548110995758659117963675121580688646633905974267034230368859714860956869501735484935892423435628119663834609861404603669293370116263234934228152479712608198838710906977703869942691807517386007963177722278218630355797809288369661636020430649704078550347363118303518456321650478625699753254072632034780906569824313829576581924285591111129410087982520527162716782559125084905878945653294630968762673918390674133534295597310624956656424002069396231999078910327731548222833389709222604174053318647359468971048001154518603057012246350245708209744160176812345668086430514473071288693530464111329660462999717559531872374161125322364236078913998397310653015062448475892402296819716036921161929997178080875353052861836220151307621736854735746195764259490219885929890449077552117004881313732621791832926075069840895630002897873981842396622798757346764890663182181325042569369013263128272029213447653327318561206380582604751353676120728851882749665153390387131429970960560738945851391484508921007233952722793696848237396272849263889854603635014285226961341280707557836914835576143055150926235063105323170811331352591560084223347630982300249444167458981385521959962978006589116218413138401560410619379191638266173929547332059920505452540688170304788812357710661549308021113453407303477956913570589357972441085532731316097750093509471117136983434240484524264391197972881894595720225255254943247702549575663554375552431585628849267907790792536010030496685512912636495359514484723175737328133360236802891924133417938482837505738825910346704332194068066644997798308417133333384732620763714438266995267704346807909858243283866286606794968464697854345326153848838517610653059184387344151013292756518720516123678358952739466354673880515920685448535172852432821784214764731524784483643638014860992994093390145285932501578298740974517236580746017087571213904641276673262242243870788741369320428995875922246461355100621801708998294133703107846724756644672066000549194649963139039960029594210652942957299494155307092146360929071650936965682999238440696737923871448182847428181323906294552433017102280385978824539412317644568975105457409566122347784847327656290113943582780315929818778857920224329417838832827728657882063935870805572314411470806633953203902505821120891433492661594755973975908931880974284824727284549195568427235140516463733520131237018913916716436725363841582677942211523633392697856612515060725875432786866843915648594412279308495972680288047864837973505109404436892113393691256248577948717931048514803654941639569805402850720024037487312799996681996592080815789927353124955287817811914753463559021929119824532931959625064712756520398729197375409724469339909486805794939846016404951443333100640233740561507891529004346070863222769964550717902537211754922345911548137790407690735200145062246329007850674118292459888335918799353600788505779122185238715525657865264420408674983049608343081470768890032179693181773660350225689272906665829708759271362874937052610689605517972094288602505552539968191089168686370420414206701601860858483351326416021321485483905711286367141187171828352038213534582699445098195612710390052149136020897669249885337571615439109581032126882998335326333158068861514403114625152805814370084587443111590852852638958304052511448770900046802023142386391291228674197110175432740919234096773455390791813010524414752589587840408924783246806601591854341007166840176831153971698331834402282719400071329472367659909350332356398417973358011794156178016310022669141131310710183959867972640052277210119063644035826102950483186499395384637921425884796038358122656674112592575040691537948456876343516110903177000938634767039166349780543098294947778694094742657926366806016007637207446097987283025124924875312445504972284074487334395743661327982591517815370923096679771301577859796676439834179026655798737433504129950258541085326490730869656571427774899514131369687034896668085653251183695667919565636501708657414750440436721265520923954261594372058291559148582931847548845018501068558893305709016934193429413836368134138486367616566346352664151178119901786698459990056748437492876367908799076956607804162905466002860433744034452315202010222569589145065671164185299497211803847750293350657765049521201071662003981371179864195250281894773142531603951511136390632877325230063646684283025250209973346345391196918830539837834658212780952596886949850117612173746227811976798352423749895824011235899269515786306655652399585372966912682705819981579278694676947843250972786034076615345065016941913842720842858267400695870503848178092679373607712295227146570324716374447744577425984136074077862824978716727653997186850635736488388787790243152954348713441316665691745288777699773647512143229006409055474211294504773512364701208446027336307011391793714931808851119553540868266667791657511862223571881981710715417423931174336394501451600542330069131213921970124157620098219851051816769355378124312058849558378516914838569943731047410424679909466958907585824020836184931640110577390684060610837808343666889792375155160538018099611144947564671078091781766097570657025196524247046325162332666346334540799270789522412054321959277879341714932080394379435361727546493990522538312801192050455187396155747441907722815480821850528892878566812062649464224035784309318194604171522869625936628270601552806672509923287220805889671393784952716259934028483719994079495672975323143622735512403398077806789564270282453681562311533919491193438564019690769704509791570842218644350513633254272141074836321519022004545398599328674882028560679710350140955826250707065474021700559860149633167867581198368935750999112207224450226742756986751166035231460718430541975285266970570671994775933846731323068194563442613992320410316780310928043158742491110810630166313070504710337745051810984071442953782353716528824033379082469621220955689278036282697260073029426413557169888767329714123163082391461665149780617203342813755300137594071813031205462668093090959905960064820974114924714521570673403259748283699586969240842435628551272262980748987549422999377394103886552812593184110634707108279374152579057763144739611452283083152034043808759202951288797702258538213395363758234120407525565726697083444642419551718167956207984725861999500864411939036028144642021237436630194086670278161925829986567695931836005390671569929715270921872832289525102864866753752296587232722994068583258181933194931860903904616032335709865270274364963275121003997388743217510959231198481905519138580434327264338209281222882232347570467768887500569238398677457236157675750191470851112516919480682965205365329432202007354454970662907553295282151412843112289113835197165629544411350384690888774694511109800641749989095389736274505477216256315278058004265378155900942697828654053435305267952093717535456841240485548524033391093542133528221258258908147625188845892002306581984458787507303137994322120638871047787726836787133882978998353254493694740798146619765248046750128857060034225651445189694777046821667978876942609178593510198299582258506033949425757782995959732547830011997439614874363915899841787994573180117969506813304549600654602510009311784083482618563463005914209246372736684089776223390932251288006973839377289169056706854102910211811576782011470552705954981074090683499290102564109363746866593732051978611306222916676278293576902759425057730282632196480295249484021203649018440658836713741950620060326669588554699769258271884864670292995509161318190511039818217463286367660029435250934402551064936485501960345089504885444232065148804715993442015403523089440963285577845467990492018911675487194769864795190296346106116446179558330871397659082488245192031080783564363933978113166886362992943666200963023481197008661153990184589573784930202913064230153613560677529916814545909561097041398442334455591887786857874086427541106010089670473674068901645113826276090913714697813296265580165292971247358496550993397203019195035515212211749363852358020519277038529717113496786296829128725123103305222711904504105398920543930633059564403537867106101407229226320476788305150258992971134851302521643526032411521351598567391039952931813225254474056769649542227626869502633526326184840545852955351425095803202284516990490635178449580125085515917666471996517821561232823458031392617566864891222582741703011392196111063523888049447886981578986106587815505606987600861569528629281970132364768167090599013835456553903689628512915608228188437456554566940940402513624576548159075246041029663489311977315888216811430791515101470386836650660824874997285294196028957266567489469581586975829291637138469738946864254322085323215788295791742823882462329008457469290876892376781905382207765622608108622949947045352643988933441596967828823803606940329199722282265829510343234427485822294775224873932988979655103389186850431894076982701967022760709983623476503753706195262783207080876077019189393226348368998822682445072477320547711726439500991267451387625452680425906595915671693698898390103893982364078090550440624615803030645520675624861352668727086974694802697350615476320147420719242109524845877245006886177188765321143670991468044111171364210422176138480575532746236335876482366083788755882068600747058153198768321517383226444826220512424368118340652348513619620621070852977477238292538310843811948011378105029518033781367925471623382296385441897228516721649028097297477931095706258231147062687946111365849857437400548856970410853030394018325422311052144305837716269657775129488255474621263128033836996737222906113109942723217429846875203509261614759410859782118856377232429386976552400311918080883001782131871310718627358400804413720907429775086568981972913917716295202450168184102061094052081398611535743396044302932688866931578418503932304778063805316682635852247785397767538381108320515858940523772706684228374783471756419442331657126922582300478308862726417750603755910059980902218196734854231904407729149744875101984682675812481969969815238650078852035503281015469623621478635892629053452025352727127618101262968994795838608645397384123722190410575488349541962799603761033288845194580019734157725023602836908595839799552265861203896126940842565686190128607729534009586283306560582601060086745466225026993254926414303748541094010370136174788731943208896428762987590042209423431710325666044801028586101092556759203949398350730535844183796904537517421785882053191481033725343922515512981036672513494007835616461334200129069035430873647611729190347836531029749431755262137013615104996577018733127512845904568932080332173042383923226539279531188062609139775457230475836945927054331427672096734844290734113605303793955750035080852807659427148141122734249498152644088707203060038432243501889561344260287056528292180610546291950549167738164573081326578636813289657567693444704448532755317445423143647668497524033506641685776540580026936950479095131611120870883402286590543973339436444250196707322349845712566637450677455605232608818756816921788139569482966651341043304121493575972651687445880780110804159174774030016967667363877718009945246811993751287403298306415291041101933901821402273599245020111103254736818636735544989408451613845825932230933540961525247599332157949535781468091438177388299775441211023843591276815706910081871983146497107852882266436561398831048838531440908796607017807647581260974667754642228861946877694472948115119197875497944557953501586837533230947714796166309116233568646795817007859769129445681169995877757137316485635174341070564268602672182349501631626192904949080641345418350272921583368186201856184851821580664001243146278233281915690169074238690357971068106626559603787415820575306383098161710823681572364558215588198103781498384223282612870848194171617742369585653488598756921727297022173547785934757792955329466997806206631748326364376960186920944239032586020110074758700591892813165023034456846596445663319083092684237573238916870821113689647369829006110515468545405028299092707181346661497071145161872138119027804692176276743909836996415271099018561258829011045705135846657483274179181024857675693866433737924577530543052698199909681236834927962430655381653748776283131591929440242437351666760208111509635004629324730367694298085015852388924352987768951198410930973136368778781491782324426835097631159662854664155918167120247128993172055050415388024683598304253511217345013768212331989460701530059344578875464098642002235616487868210647644667501778798905909454370624381614987968479698336657107683875216087804853246725980330811811312931771198957647978877799314515560220771661452548717499552881763989735128030177373137888187711199557747347686658798178125105002862738848830645759555012595187396765944442179906928136428813415581726157828665708401709334475406358939732583564102193763329538497151902244906790623809912333029583892193962145040079816630274522761890077588159995085581116633691429586525955271568491045259311145513915490131257768958279240638570892315798863814055696396678790638963081259337979782026692895897267944371975169726343365571040982965112884435367135041303207720619945237827575471496728237605025362460725682423990801387508316188815353393931914755294488941143839985068814670351901991377554060391490701509954981137382355412992761303576388099949878087971858078373569337037023253178733899813416055484625696613888249745817886728042967457141136940128924376915839191118560682720446296811820321320919063607385196050141559949305935386117004320767786205818522305349928616614395179760830758320481109684039754727223847642563581378511288665395659944758878081167255457295857068090862498690693619686593253487753055289979793032984262663401781431506652661910160667175567843205216153686888733367903849010167325916812307503343185850562124654398873822025453689503045548455998730756937025098867041918072219371966608393778464663241366220632923633258115178447044247605364488649827316835768406655820889448144205990447944241332230710636545840609748224030957568929790797936175197657919610711641532568332418391247812863062038117283736362593906199091253413753573487417409141860853565154185921921956477720275038595305692685213862498136925503474599725336309587678347808097370644091819116511542089830281398875842891290458226249302126046184537142717015848618413895992815032338879406524465989170603165661129493415955575228992191314683580365650125134437074866302228102961880441302541502806758129312799463435199942755249098398249368404056702456645806305136439024978324299707629432106449492855083224016915686043612679495317999633303014875169672516522693119062594868398482263093012601006613683347162918024345596375691127399367502888139630148506330829464292974851902639547544615383507157937877900136208027427915101586154107157038899044380883537877562149137127717224123596121767402292089188628901733430567000484584530832054622174286054047956914904750399275900261151406076477327280649133765188861646007125647358839749180405996839355761984820591681151074203325098798235095832261821018163884082230564104496681728209452314798869603566343068588078723435509285016663542644591792609858682997328875895844575993373481150743605069071543204375228466691322201902054206176247608906390521401270183648821526660739073416766529620861297326058026540423473799861864490926269104813942251542310125490453959198643151183013616319653446414844312693055774093316707855741519021079342840968323313708280413959997124584039938563377347666007041075796683079904936137626509973697088947914237417270774743090991449800044686341728204794142839471053597294559689201261593158836959007118976317264371565162178860542146903295980821128889911719177792237154988690480983154107004373032522547713371055673496091904202345738003241525483658141646518235233531473865689790337299732594279115020193253049529048031532637154049190581641865341104768972227642377456397628833113838606697342339539236528287036326987039301480476171526131854712568949412749782664116884828629847985007300075230892677899394184516236651975241168165459963970259627341360871273460721401407097763830524176559396764582448539240551304862764479724660085470776581582749932742462006532159897146234456685489669112532566752263644514999345932195929836446519573776780614010101566335386774377782877517435997686186955058626106494226283241558303034289198525765313922914812830193840748152813104794345084635732167354856472337110387392777970191909286964014662776192659052960334743918290891939387027124733527359026328736466385546353293702628863709411156149467369548558479022988800787177084029091490941289201132404484377278165674988928120089580787315938601240725431476328395664955629670416757308048900595780686752005838394038674303303560405586420484602616245241544546213888813918211203247858588890540137040610725156820884378873111250371714388896300552741167514150725178168837367217282973842404071214811788108850679035142690604934014161881458853970844673392090893380107661955518268072985504074604762706518334551288959419576897018650916557529420832600227298148573238552973180348926836581239735103864097010536890453621627733616375182239257469913430434044142295225056046940364038691463876167843025478840991725043892553754247132934754006580184496379122988843942708065808289633779270221794086315213904643362697568645030452327238096203083013931146837407300944905545420773031038490674873047968910056995395119357551869081892551519319175749349766225588805823462993808167964859281670770051409458333130217908024478082950557837863674364973642598407448608132039410436679255120802490049346816893205495828914327568297097550876767515497560183941180585651433748687095939279532118657667868189306868586369447160141871678802288564204054222398355239839974952337132266438144610906970120214786779360835603382780143632378290478971874290087114054006672664260585584075766819209714756306278487522784491901707456580710214583714341362545105648110332426575295007399106377387609778558866408926638684215384726598373971600279708141536428445153214596609134847023829387196516611271725420562058230707547837354713625400244905978056737333280615500787245348456320523964956744870312579807411688470568099570894694027870234284070804126298452114906944214779413490168909067523087811562342029576730464855269149786566198976801134449045016692885540565002406119630973265534829991556816757569643155701065917313914698210926179786230270432059662362696258459060788454686161402859077644954589350047761197542307426349767560951211741624606456495260370280850973514730082601611434528498341126525696488386478468148144579884543855549795297245489701809436288072066527338867956058449650013942900534528391385210046597735777879672243501268989958529884120798133261268607594691792573051153947836364585519576629968426113070114567805146663071479805076680593313599656535073614283733267764029510454351912283092352947647567571954332094740850569477938202183438344190536812907526295952169894609119757811017654496363414593869552101867572526305504361781399278386658038865082618289406071564123679184817222302459399240534447552507583763735148716632055713606753370135208284599188359433637517873535300569314817116399641161527650370590172304095387086674237648563364906620605062047885893463395928408005365810251764290238637587648917569093593708117469644711859402910387269749541775341351203209504201614425411791081791679904449240012795406826334951828045131311262656633856472308661330606338638003950020485875446265825984893881794518855901607241294071457458631530259389640784005463285133051494800787708638787569358107536344085011311685471944948839507928446799541450757003230596739022491207327003117720158297925814979010599772781349309188814641237462247756240068676046392126762526300064280767626480679525290683198017474076249402917696851304520719781161416742550630701970024804044694634805065381177259340016901745916384365218174236796130489761686576274416248688603288744294547271364386815128357121165196087629958194306254101307100047011451863450773743740269854128443549344513197281437490388876465703976236475981113351685338087125043723662722805881203587298000027619806016303078298157757739515429455936757608415600427598395600460977799370425100277663804895215175746787140165983104715627658496157852066731242068274784388169445414214182493083283595009593866473090659381423888454531712148368075866896543047333200342356980472342920418098128683615758165876598606666027839274252960629338359855855202145893320360529062348601853049829399897409548739520221657990798412535997787044943064199234999826407762572427210789463058125382643530386442027999340693207084067009883732284611325100250921441405712736178989935436788503094485928808323562327176052517766519351795664772971729078219378159182595371369344272936319343541017710327835615784782334412886650840042295067793635457390571047079223196019021890390191559854203556861408744035995847860175373583488476547831326418942890018392247730573112071003658647471576203053833965576747360718947836413418409390664271091040989231325851942092939709736459436850250066684326701735399201894399189993788753256328188376477547539152287136695863508780884269017327225504196990004155392505267428464509295718363530690280158804933674824919660166137205023361563476088492095019050310120979324120330358126648915011530877131048794452699426582414632687359102376113808358612219811285458838796150963667476976564978987579307034003320600545269842266858771552537989617247486858598647415349163411660726985387084603133820620829539703576554146365534451871481168052821066895754081595310200695437399572100348371829791064974884786087764005121036368123808348412416449015143085828196231588738227230073203411871434884077478964054037686239530572798811953100603136521494411997770941790570206906152030841706339261926935490644464152981498090574436687339119197218242413634071425743475338638685708943204044797369073297739900386969808282516468374615579254197814278687367644558205281784296455538985253846381576234186654219805990576293922162630128770802278137912727122739200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:86: Test Case '-[BigInt_Benchmark.ProfileTests testReadingFactorial]' measured [Time, seconds] average: 0.138, relative standard deviation: 2.808%, values: [0.149650, 0.137840, 0.135714, 0.137798, 0.139362, 0.136535, 0.137619, 0.136449, 0.135943, 0.137102], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testReadingFactorial]' passed (2.899 seconds). Test Case '-[BigInt_Benchmark.ProfileTests testSquareRoot]' started. /Users/tim/Developer/Xcode Projects/BigInt/tests/BigIntTests/ProfileTests.swift:165: Test Case '-[BigInt_Benchmark.ProfileTests testSquareRoot]' measured [Time, seconds] average: 0.229, relative standard deviation: 3.071%, values: [0.235449, 0.238305, 0.241843, 0.230759, 0.222361, 0.224314, 0.222579, 0.223777, 0.223153, 0.223580], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[BigInt_Benchmark.ProfileTests testSquareRoot]' passed (2.573 seconds). Test Suite 'ProfileTests' passed at 2018-09-08 14:04:11.464. Executed 11 tests, with 0 failures (0 unexpected) in 120.415 (120.419) seconds Test Suite 'BigInt Benchmark.xctest' passed at 2018-09-08 14:04:11.465. Executed 11 tests, with 0 failures (0 unexpected) in 120.415 (120.420) seconds Test Suite 'All tests' passed at 2018-09-08 14:04:11.465. Executed 11 tests, with 0 failures (0 unexpected) in 120.415 (120.421) seconds Program ended with exit code: 0
    opened by tgymnich 7
  • Add support for Swift 3.2 (Xcode 9)

    Add support for Swift 3.2 (Xcode 9)

    I know that it's a bit early now, but being able to compile with Xcode 9 (and Swift 3.2) would be really cool (since code completion and the editor in general is SO much nicer in the new Xcode).

    opened by serieuxchat 7
  • BigInt 3.0.3 crash in xcode 9 swift 4

    BigInt 3.0.3 crash in xcode 9 swift 4

    include by carthage in cartfile: github "attaswift/BigInt" ~> 3.0

    yld: Library not loaded: @rpath/SipHash.framework/SipHash Referenced from: /Users//Library/Developer/CoreSimulator/Devices/0A76CB65-0F98-4808-99A4-2C0B940D4C4F/data/Containers/Bundle/Application/153658BC-FB63-4CCA-B9F0-1E7AAE8ED4D5//Frameworks/BigInt.framework/BigInt Reason: image not found (lldb)

    opened by AdeSupriyadi 6
  • Library evolution support

    Library evolution support

    When importing BigInt on my project (using it for a RSA implementation in CryptoSwift), I'm getting this warning:

    Module 'BigInt' was not compiled with library evolution support; using it means binary compatibility for 'CryptoSwift' can't be guaranteed

    See https://swift.org/blog/library-evolution/ for details about how to fix it.

    opened by NathanFallet 5
  • In debug mode, taking too much time to calculate exponential comparable to Android native BigInteger.

    In debug mode, taking too much time to calculate exponential comparable to Android native BigInteger.

    Below exponential calculation (2048 bits) is taking around 5s whereas same calculation using Android native BigInteger is taking around 100ms.

            let N = BigUInt("AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", radix: 16)!
            let g = BigUInt(2)
            let a = BigUInt("601e4cdbc9ceadbd116fff9331c689b03d9770f5d4da80f8e0fe826f01104e9bb52d68a7bc38519d77d0463f4bc67cf9d13588e03324c7c79a6931dfc3d5b4b3b4014ec08820be1af9f9a056350ccaada53f063568671bd717217be2f90e948d037e00ea348f1bb4f99ca16ca4f11a889529afe80229127b10e85001c6654fbdb805f1122dc1b10679334228ab86ab65a3192f0368ca21f45e966e65adab6bf752844828b25923ad98da909c1b2ffae21625ce6095f0d15601475edd44a7a6979a48339f0265fabe7cb864a56e583c35f838eaa00e676658df7e091a5a3cf346f4df3ce65ed5633b7bb3ea7c2dec982a4ec9c7c6ad9eb3da33cf635ed6094c24", radix: 16)!
            let start = Date()
            let A = g.power(a, modulus: N)
            print("Elapsed time: \(Date().timeIntervalSince(start))")
    
    opened by gmtek 5
  • Any thoughts for improving the

    Any thoughts for improving the "power(_ exponent: BigUInt, modulus: BigUInt)" function?

    Hello,

    I have an issue right now with the power-modulus function. The problem is that an RSA 3072 key generation takes a couple of seconds while the modPow operation takes 10x more.

    From the comparisons done with the Android version of BigInteger this takes way much time for a modPow calculation. Is this a limitation of Swift or can it be improved and will be in the future?

    Thank you, D

    opened by dragosiancu0504 4
  • Build Causes Swift Compiler Crash on Latest Swift Trunk

    Build Causes Swift Compiler Crash on Latest Swift Trunk

    I am developing machine learning models on Ubuntu 18.04 using the Swift for Tensorflow v0.11 toolchain.

    $ which swift
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift
    $ swift --version
    Swift version 5.3-dev (LLVM db8896f3f345af2, Swift 61684f62a6132c0)
    Target: x86_64-unknown-linux-gnu
    
    $ swift build
    swift-frontend: /swift-base/swift/lib/AST/GenericSignature.cpp:251: static swift::CanGenericSignature swift::CanGenericSignature::getCanonical(TypeArrayView<swift::GenericTypeParamType>, ArrayRef<swift::Requirement>, bool): Assertion `isCanonicalAnchor(secondType)' failed.
    Stack dump:
    0.	Program arguments: /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend -frontend -c /home/xander/dev/BigInt/Sources/Addition.swift /home/xander/dev/BigInt/Sources/BigInt.swift /home/xander/dev/BigInt/Sources/BigUInt.swift /home/xander/dev/BigInt/Sources/Bitwise Ops.swift /home/xander/dev/BigInt/Sources/Codable.swift /home/xander/dev/BigInt/Sources/Comparable.swift -primary-file /home/xander/dev/BigInt/Sources/Data Conversion.swift -primary-file /home/xander/dev/BigInt/Sources/Division.swift -primary-file /home/xander/dev/BigInt/Sources/Exponentiation.swift -primary-file /home/xander/dev/BigInt/Sources/Floating Point Conversion.swift -primary-file /home/xander/dev/BigInt/Sources/GCD.swift -primary-file /home/xander/dev/BigInt/Sources/Hashable.swift /home/xander/dev/BigInt/Sources/Integer Conversion.swift /home/xander/dev/BigInt/Sources/Multiplication.swift /home/xander/dev/BigInt/Sources/Prime Test.swift /home/xander/dev/BigInt/Sources/Random.swift /home/xander/dev/BigInt/Sources/Shifts.swift /home/xander/dev/BigInt/Sources/Square Root.swift /home/xander/dev/BigInt/Sources/Strideable.swift /home/xander/dev/BigInt/Sources/String Conversion.swift /home/xander/dev/BigInt/Sources/Subtraction.swift /home/xander/dev/BigInt/Sources/Words and Bits.swift -supplementary-output-file-map /tmp/supplementaryOutputs-9577c2 -target x86_64-unknown-linux-gnu -disable-objc-interop -I /home/xander/dev/BigInt/.build/x86_64-unknown-linux-gnu/debug -color-diagnostics -enable-testing -g -module-cache-path /home/xander/dev/BigInt/.build/x86_64-unknown-linux-gnu/debug/ModuleCache -swift-version 5 -Onone -D SWIFT_PACKAGE -D DEBUG -enable-anonymous-context-mangled-names -parse-as-library -module-name BigInt -o /home/xander/dev/BigInt/.build/x86_64-unknown-linux-gnu/debug/BigInt.build/Data Conversion.swift.o -o /home/xander/dev/BigInt/.build/x86_64-unknown-linux-gnu/debug/BigInt.build/Division.swift.o -o /home/xander/dev/BigInt/.build/x86_64-unknown-linux-gnu/debug/BigInt.build/Exponentiation.swift.o -o /home/xander/dev/BigInt/.build/x86_64-unknown-linux-gnu/debug/BigInt.build/Floating Point Conversion.swift.o -o /home/xander/dev/BigInt/.build/x86_64-unknown-linux-gnu/debug/BigInt.build/GCD.swift.o -o /home/xander/dev/BigInt/.build/x86_64-unknown-linux-gnu/debug/BigInt.build/Hashable.swift.o -index-store-path /home/xander/dev/BigInt/.build/x86_64-unknown-linux-gnu/debug/index/store -index-system-modules
    1.	Swift version 5.3-dev (LLVM db8896f3f345af2, Swift 61684f62a6132c0)
    2.	While evaluating request TypeCheckSourceFileRequest(source_file "/home/xander/dev/BigInt/Sources/Division.swift")
    3.	While type-checking extension of FixedWidthInteger (at /home/xander/dev/BigInt/Sources/Division.swift:11:1)
    4.	While type-checking declaration 0x8acfa30 (at /home/xander/dev/BigInt/Sources/Division.swift:12:13)
    5.	While evaluating request PatternBindingEntryRequest((unknown decl), 0)
    6.	While evaluating request PatternTypeRequest((pattern @ 0x8acf618))
    7.	While canonicalizing generic signature <τ_0_0 where τ_0_0 : FixedWidthInteger, τ_0_0 == τ_0_0.Magnitude, τ_0_0.Magnitude == τ_0_0.Magnitude.Magnitude.Magnitude> in requirement #2
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x5214dc4]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x52129be]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x521509c]
    /lib/x86_64-linux-gnu/libpthread.so.0(+0x128a0)[0x7f6d86e128a0]
    /lib/x86_64-linux-gnu/libc.so.6(gsignal+0xc7)[0x7f6d856b4f47]
    /lib/x86_64-linux-gnu/libc.so.6(abort+0x141)[0x7f6d856b68b1]
    /lib/x86_64-linux-gnu/libc.so.6(+0x3042a)[0x7f6d856a642a]
    /lib/x86_64-linux-gnu/libc.so.6(+0x304a2)[0x7f6d856a64a2]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x193f72e]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x193e98d]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x193e87c]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x193fb27]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x18805a5]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x1418ecf]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x13a2636]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x13f4788]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x13a8cb7]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x13a87b6]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x13a1f61]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x13a1f34]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x1400212]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x137a793]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x137a4af]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x136cc71]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x14d180f]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x14d0871]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x14d3fab]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x14d0871]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x14d07a1]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x142b995]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x142cc70]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x142c9a7]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x142c8b1]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x142b6de]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x142b6b4]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x63d3c9]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x63d296]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x4fd485]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x490dd8]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x7f6d85697b97]
    /home/xander/swift-tensorflow-RELEASE-0.11-cuda10.2-cudnn7-ubuntu18.04/usr/bin/swift-frontend[0x49098a]
    

    This occurs on all the tags I tried: v5.1.0,v5.2.0, v5.0.0, and v4.0.0.

    Note that I do not have this issue on the previous version of Swift for Tensorflow, v0.10. This issue is new to v0.11.

    Note also that I do not have this issue when building on macOS 10.15.6 with Swift for Tensorflow v0.11 when linking against the Xcode 12 beta macOS SDK.

    Note also that this does not occur with the official Swift v5.3 development snapshot for Ubuntu 18.04:

    $ which swift
    /home/xander/swift-5.3-DEVELOPMENT-SNAPSHOT-2020-08-31-a-ubuntu18.04/usr/bin/swift
    $ swift --version
    Swift version 5.3-dev (LLVM 3fa9679add, Swift d24649a4d6)
    Target: x86_64-unknown-linux-gnu
    

    It appears to be specific to Ubuntu 18.04 + Swift for Tensorflow v0.11. Issue I filed against the Swift for Tensorflow project: tensorflow/swift#522.

    opened by xanderdunn 4
  • .quotientAndRemainder() is missing fraction precision data.

    .quotientAndRemainder() is missing fraction precision data.

    Example: BigUInt(1).quotientAndRemainder(dividingBy: BigUInt(1000000000000000000))

    returns: quotient: 0 remainder: 1

    However there is no way of telling the fraction digits of the result (1*10^-18)

    opened by Chevel 0
  • [Violet] Node tests

    [Violet] Node tests

    First batch of tests from Violet - Python VM written in Swift (connected to #98 Using tests from “Violet - Python VM written in Swift”).

    Test failures

    Binary operations

    Let's use the following test as an example (I chose this one at random, there are other tests that are failing, maybe for different reasons):

    self.xorTest(lhs: "-1", rhs: "18446744073709551615", expecting: "-18446744073709551616")
    

    attaswift/BigInt says it equals to 0.

    Other engines

    • WolframAlpha - BitXor[-1, 18446744073709551615] -> -18446744073709551616 link
    • Python 3.7.4
      Python 3.7.4 (default, Jul 20 2021, 13:20:24)
      [Clang 12.0.0 (clang-1200.0.32.2)] on darwin
      Type "help", "copyright", "credits" or "license" for more information.
      >>> -1 ^ 18446744073709551615
      -18446744073709551616
      
    • Node - we generated our test with Node, soooo…

    Why?

    • -1 in two complement is represented as all 1 with the desired width.
    • 18446744073709551615 is equal to 2^64 − 1 which is 1111111111111111111111111111111111111111111111111111111111111111 (basically 1 repeated 63 times)

    So, obviously if both -1 and 18446744073709551615 are all 1 then xor will be 0, just like attaswift/BigInt returns.

    Well… not exactly.

    18446744073709551615 is positive, so its binary representation has to have 0 prefix in two complement (otherwise it would mean negative number).

    With this:

    lhs:    11111111111111111111111111111111111111111111111111111111111111111
    rhs:    01111111111111111111111111111111111111111111111111111111111111111
    result: 10000000000000000000000000000000000000000000000000000000000000000
    

    Shift right

    Let's use the following test as an example (I chose this one at random, there are other tests that are failing, maybe for different reasons):

    self.shiftRightTest(value: "-1932735284", count: 5, expecting: "-60397978")
    

    This is an interesting case (look at the last number: 7 vs 8):

    | Engine | Result | | -------------------------------------------------------------------------- | ---------------------- | | attaswift/BigInt | -60397977 | | Wolfram Alpha | -60397977 | | Node v17.5.0 | -60397978 | | Python 3.7.4 | -60397978 | | Swift 5.3.2* |-60397978 | | Violet | -60397978 |

    (*) This is in Int range, so you can just -1932735284 >> 5 to test it.

    Anyway… Wolfram and attaswift give -60397977, but Node, Python, Swift and Violet give -60397978.

    Long story short, both answers are correct, it depends on how you round.

    Doing this by hand: 1000 1100 1100 1100 1100 1100 1100 1100 >> 5 = 100 0110 0110 0110 0110 0110 0110 rem 0 1100

    With sign extension to Int32: 1111_1100_0110_0110_0110_0110_0110_0110, which is (according to Swift repl):

     13> Int32(bitPattern: 0b1111_1100_0110_0110_0110_0110_0110_0110)
    $R11: Int32 = -60397978
    

    I think that attaswift uses sign + magnitude representation. If it was 2 complement then everything would be trivial, but it is not, so sometimes you need an adjustment: Swift uses what would be 'GMP_DIV_FLOOR' mode in 'GMP'. Which means that if we are negative and any of the removed bits is '1' then we have to round down.

    Wolfram does not round down (which is “more” mathematically correct!).

    opened by LiarPrincess 1
  • Using tests from “Violet - Python VM written in Swift”

    Using tests from “Violet - Python VM written in Swift”

    Hi,

    As I mentioned in #97 Using ManagedBufferPointer instead of Array as a storage I also implemented my own version of BigInt for Violet - Python VM written in Swift.

    The question is: can I merge some of our tests to this repo?

    The main idea behind this would be to test our tests. If attaswift/BigInt fails some case then it may mean that the test is wrong, in which case we have to fix our code in Violet.

    Violet test suite is quite big (but by no means it is exhausting the test-space). We went with property based testing with means that we test millions of inputs to check if the general rule holds (for example: a+b=c -> c-a=b etc.). This takes time, but pays for itself by finding weird overflows in bit operations (we store “sign + magnitude”, so bit operations are a bit difficult to implement).

    You can preview our tests at Violet -> BigIntTests. Though I would advise reading our documentation before, because our design is quite different than yours.

    opened by LiarPrincess 2
  • Using `ManagedBufferPointer` instead of `Array` as a storage

    Using `ManagedBufferPointer` instead of `Array` as a storage

    Hi,

    Recently I had to write my own BigInt implementation for Violet - Python VM written in Swift.

    Internally I decided to use ManagedBufferPointer instead of Swift Array. The whole design in one sentence would be: union (via tagged pointer) of Int32 (called Smi, after V8) and a heap allocation (magnitude + sign representation) with ARC for garbage collection. The detailed explanation is available in our documentation.

    Naturally I'm quite curious why most of the BigInt libraries (including this one) use Array. The current implementation gives you (2014 rMBP with Intel x64):

    print("BigUInt.size:", MemoryLayout<BigUInt>.size) // 32
    print("BigUInt.stride:", MemoryLayout<BigUInt>.stride) // 32
    print("BigInt.size:", MemoryLayout<BigInt>.size) // 33
    print("BigInt.stride:", MemoryLayout<BigInt>.stride) // 40
    

    Going with ManagedBufferPointer would give us much smaller numbers:

    // Basically our own version of `Swift.Array` specialized for storing `Words`.
    // Mainly deals with COW.
    struct BigIntStorage {
      struct Header {
        var count: Int
      }
    
      typealias Word = UInt
      typealias Buffer = ManagedBufferPointer<Header, Word>
    }
    
    struct BigUInt2 {
      typealias Word = BigIntStorage.Word
    
      enum Kind {
        case inline(Word, Word)
        case slice(from: Int, to: Int)
        case array
      }
    
      var kind: Kind
      var storage: BigIntStorage // <- This line changed!
    }
    
    struct BigInt2 {
      enum Sign {
        case plus
        case minus
      }
    
      typealias Magnitude = BigUInt2
      typealias Word = BigUInt.Word
    
      public var magnitude: BigUInt2
      public var sign: Sign
    }
    
    print("BigUInt2.size:", MemoryLayout<BigUInt2>.size) // 17
    print("BigUInt2.stride:", MemoryLayout<BigUInt2>.stride) // 24
    print("BigInt2.size:", MemoryLayout<BigInt2>.size) // 18
    print("BigInt2.stride:", MemoryLayout<BigInt2>.stride) // 24
    

    I believe that this approach would have following advantages:

    • better usage of CPU cache - in the current design BigInt has size 33 and stride 40. With ManagedBufferPointer we have size 18 and stride 24. This does not matter for a BigInt as a type, but it may matter in real-life scenarios, for example when it has to be stored in a struct on an Array. (Just a reminder: intel cpus have 64 bytes cache line and M1 128 bytes, though I do not own the M1 device to check this).

    • BigIntStorage is specialized for storing Word which means that it can do some things in a more efficient way than Swift.Array.

    • potential further optimizations - I believe that you could bring the stride to 16, but then: inline value would be a single Word (instead of 2 Words) and the slice from/to would have to be Int32 (instead of Int) + some minor rearrangement of how things are stored internally. It may not be worth it though.

    The downside is that you would have to implement your own heap storage based on ManagedBufferPointer, but this is not that difficult.

    opened by LiarPrincess 3
  • BigInt 5.3.0 not present on CocoaPods

    BigInt 5.3.0 not present on CocoaPods

    Hello,

    I've wanted to update BigInt from version 5.2.0 to 5.3.0, yet the CocoaPodsSpecs is not present.

    • https://cocoapods.org/pods/BigInt
    • https://github.com/CocoaPods/Specs/tree/master/Specs/6/5/b/BigInt

    Is CocoaPods still supported ? Can I do anything to help ?

    opened by AlonsoFloo 6
  • Data Conversion - support for `[UInt8]`

    Data Conversion - support for `[UInt8]`

    For now, we can initialize with Data, so from a [UInt8] using Data(bytes). Could we implement a more optimized way to use [UInt8] directly without a conversion to Data? (To improve performances)

    opened by NathanFallet 0
Releases(v5.3.0)
  • v5.3.0(Sep 6, 2021)

    This release contains the following changes:

    • Make access level for isZero the same for signed and unsigned types (#93)

    • NFC: Add protocol conformance to Comparable for BigInt for consistency (#88)

    Source code(tar.gz)
    Source code(zip)
  • v5.2.1(Nov 15, 2020)

  • v5.2.0(Aug 26, 2020)

  • v5.1.0(Aug 26, 2020)

  • v5.0.0(Aug 25, 2019)

  • v4.0.0(Apr 5, 2019)

    This release contains the following changes:

    • Swift 5.0 compatibility for Linux and macOS
    • Remove SipHash dependency

    There were no functional changes.

    Source code(tar.gz)
    Source code(zip)
  • v3.1.0(Jun 8, 2018)

    This release contains the following changes:

    • Swift 4.1 compatibility for Linux and macOS
    • Fix warnings for Swift 4.1

    There were no functional changes.

    Source code(tar.gz)
    Source code(zip)
  • v3.0.2(Dec 25, 2017)

    3.0.2 (2017-12-25)

    This release contains the following packaging fix:

    • Fixed product definitions in Package.swift not to create a duplicate library. (Issue #37)

    There were no functional changes.

    Source code(tar.gz)
    Source code(zip)
  • v3.0.1(Oct 10, 2017)

    This release contains the following bug fixes:

    • Issue #27 — changing scope of kind and storage to be fileprivate
    • Making subscript method of BigUInt public
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0(Sep 7, 2017)

    This is a major release upgrading BigInt to the new integer protocols introduced in Swift 4 as part of SE-0104, Protocol-oriented integers.

    • Adopting the new protocols involved major, breaking changes throughout the API. These aren't individually listed here.
    • The BigUInt struct now provides inline storage for big integers that fit inside two words. This optimization speeds up conversions from built-in fixed-width integer types, amongst other frequent operations.
    • BigInt and BigUInt implements the new Codable protocol. In both cases, values are encoded in an unkeyed container starting with a string indicating the sign ("+" or "-"), followed by a sequence of 64-bit unsigned integers representing component words, from least to most significant.
    • New method: BigInt.modulo, contributed by @FabioTacke.
    • BigUInt does not implement Collection in this release. The collection of words is available in the standard read-only words property. Direct public access to collection methods have been removed; if you have been manipulating big integers using collection methods, you need to rewrite your code. If you have a usecase that isn't covered by the public API, please submit a PR adding the missing functionality. (Public read-write access to the underlying storage inside BigUInt will not be restored, though.)

    BigInt is now part of the Attaswift project. The bundle identifiers in the supplied Xcode project have been updated accordingly.

    Note that the URL for the package's Git repository has changed; please update your references.

    Source code(tar.gz)
    Source code(zip)
  • v2.1.2(Feb 3, 2017)

    This release contains the following bugfix:

    • Issue #12: The iOS target in the supplied Xcode project file no longer copies extraneous files as resources into the framework bundle. The set of such files included generate-docs.sh, which led to App Store rejections for apps that build BigInt using the project file. (Thanks to @arrrnas and @wuftymerguftyguff)

    No source-level changes were made.

    Source code(tar.gz)
    Source code(zip)
  • v2.1.1(Nov 23, 2016)

  • v2.1.0(Nov 16, 2016)

    This release contains the following changes:

    • BigInt now uses the SipHash hashing algorithm instead of implementing its own hashing.
    • The SipHash package has been added as a required dependency. I suggest you use a dependency manager.
    • Minimum deployment targets have been bumped to iOS 9.0 and macOS 10.0 to match those of SipHash.
    • BigInt now requires Swift 3.0.1, included in Xcode 8.1.
    • The Xcode project file has been regenerated from scratch, with new names for targets and schemes.
    • The bundle identifiers of frameworks generated from the Xcode project file have been changed to hu.lorentey.BigInt.<platform>.
    Source code(tar.gz)
    Source code(zip)
  • v2.0.1(Nov 8, 2016)

    This release contains the following bugfixes:

    • The Swift version number is now correctly set in all targets (PR #7 by @mAu888).
    • BigInt now builds on Linux (PR #5 by @ratranqu).
    • Building BigInt with the Swift Package Manager bundled with Swift 3.0.1 works correctly.

    Additionally, Foundation imports that weren't actually needed were removed from sources.

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Sep 20, 2016)

    This release updates the project for Swift 3.0, including adapting the API to the new naming conventions.

    Further changes:

    • The behavior of BigUInt.gcd when one of the arguments is zero has been fixed; the result in this case is now equal to the other argument.
    • BigInt now conforms to Strideable, IntegerArithmetic, SignedNumber and AbsoluteValuable.
    • BigUInt now conforms to Strideable, IntegerArithmetic and BitwiseOperations.
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Mar 23, 2016)

  • v1.2.3(Jan 12, 2016)

  • v1.2.2(Jan 8, 2016)

  • v1.2.1(Jan 7, 2016)

  • v1.2.0(Jan 6, 2016)

    With this release, BigInt supports watchOS and tvOS in addition to OS X and iOS. Deployment targets are as follows:

    • OS X 10.9
    • iOS 8
    • watchOS 2
    • tvOS 9

    BigInt 1.2.0 also features support for both Carthage and CocoaPods deployments.

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jan 6, 2016)

    BigInt now contains enough functionality to pretend it's a respectable big integer lib. Some of the new additions since 1.0.0:

    • Conversion to/from NSData
    • Vanilla exponentiation
    • Algorithm to find the multiplicative inverse of an integer in modulo arithmetic
    • An implementation of the Miller-Rabin primality test
    • Support for generating random big integers
    • Better support for playgrounds in Xcode
    • Documentation for all public API
    • Fun new calculation samples
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jan 4, 2016)

    This is the first release of the BigInt module, providing arbitrary precision integer arithmetic operations in pure Swift.

    Two big integer types are included: BigUInt and BigInt, the latter being the signed variant. Both of these are Swift structs with copy-on-write value semantics, and they can be used much like any other integer type.

    The library provides implementations for some of the most frequently useful functions on big integers, including

    • All functionality from Comparable and Hashable
    • The full set of arithmetic operators: +, -, *, /, %, +=, -=, *=, /=, %=
      • Addition and subtraction have variants that allow for shifting the digits of the second operand on the fly.
      • Unsigned subtraction will trap when the result would be negative. (There are variants that return an overflow flag.)
      • Multiplication uses brute force for numbers up to 1024 digits, then switches to Karatsuba's recursive method. (This limit is configurable, see BigUInt.directMultiplicationLimit.) A fused multiply-add method is also available.
      • Division uses Knuth's Algorithm D, with its 3/2 digits wide quotient approximation. It will trap when the divisor is zero. BigUInt.divmod returns the quotient and remainder at once; this is faster than calculating them separately.
    • Bitwise operators: ~, |, &, ^, |=, &=, ^=, plus the following read-only properties:
      • width: the minimum number of bits required to store the integer,
      • trailingZeroes: the number of trailing zero bits in the binary representation,
      • leadingZeroes: the number of leading zero bits (when the last digit isn't full),
    • Shift operators: >>, <<, >>=, <<=
      • Left shifts need to allocate memory to extend the digit array, so it's probably not a good idea to left shift a BigUInt by 2^50 bits.
    • Radix conversion between Strings and big integers up to base 36 (using repeated divisions).
      • Big integers use this to implement StringLiteralConvertible (in base 10).
    • sqrt(n): The square root of an integer (using Newton's method)
    • BigUInt.gcd(n, m): The greatest common divisor of two integers (Stein's algorithm)
    • BigUInt.powmod(base, exponent, modulus): Modular exponentiation (right-to-left binary method):

    The implementations are intended to be reasonably efficient, but they are unlikely to be competitive with GMP at all, even when I happened to implement an algorithm with same asymptotic behavior as GMP. (I haven't performed a comparison benchmark, though.)

    The library has 100% unit test coverage.

    Source code(tar.gz)
    Source code(zip)
Owner
A collection of useful Swift packages
null
A collection of functions for statistical calculation written in Swift.

σ (sigma) - statistics library written in Swift This library is a collection of functions that perform statistical calculations in Swift. It can be us

Evgenii Neumerzhitckii 658 Jan 5, 2023
Multi-dimensional Swift math

Upsurge Upsurge implements multi-dimensional data structures and operations. It brings numpy-like operations to Swift. Upsurge no longer supports DSP

Alejandro Isaza 180 Dec 20, 2022
Swift Matrix Library

Swift Matrix and Machine Learning Library Note: tensorflow/swift and apple/swift-numerics/issues/6 have or will have more complete support for NumPy-l

Scott Sievert 591 Sep 5, 2022
Overload +-*/ operator for Swift, make it easier to use (and not so strict)

Easy-Cal-Swift Overview This file is an overloading of +-*/ operator for Swift, to make it easier to use (and not so strict) It can make your life wit

Wei Wang 272 Jun 29, 2022
Numpy-like library in swift. (Multi-dimensional Array, ndarray, matrix and vector library)

Matft Matft is Numpy-like library in Swift. Function name and usage is similar to Numpy. Matft Feature & Usage Declaration MfArray MfType Subscription

null 80 Dec 21, 2022
Swift Custom Operators for Mathematical Notation

Euler Euler uses custom operators in the "Math Symbols" character set to implement functions using traditional mathematical notation. Please keep in m

Mattt 1.1k Jan 4, 2023
SwiftMath is a Swift framework providing some useful math constructs and functions

SwiftMath is a Swift framework providing some useful math constructs and functions, like complex numbers, vectors, matrices, quaternions, and polynomials.

Matteo Battaglio 175 Dec 2, 2022
VectorMath is a Swift library for Mac and iOS that implements common 2D and 3D vector and matrix functions

Purpose VectorMath is a Swift library for Mac and iOS that implements common 2D and 3D vector and matrix functions, useful for games or vector-based g

Nick Lockwood 341 Dec 31, 2022
A cross-platform Swift library for evaluating mathematical expressions at runtime

Introduction What? Why? How? Usage Installation Integration Symbols Variables Operators Functions Arrays Performance Caching Optimization Standard Lib

Nick Lockwood 738 Jan 7, 2023
Numeric facilities for Swift

NumericAnnex NumericAnnex supplements the numeric facilities provided in the Swift standard library. Features The exponentiation operator ** and the c

Xiaodi Wu 69 Nov 3, 2022
Math expression parser built with Point•Free's swift-parsing package

swift-math-parser Basic math expression parser built with Point•Free's swift-parsing package. NOTE: currently, this uses a fork of that fixes a parsin

Brad Howes 36 Dec 14, 2022
Swift Matrix Library

Swift Matrix and Machine Learning Library Note: tensorflow/swift and apple/swift-numerics/issues/6 have or will have more complete support for NumPy-l

Scott Sievert 591 Sep 5, 2022
MRFoundation - A library to complement the Swift Standard Library

MRFoundation MRFoundation is a library to complement the Swift Standard Library.

Roman Mogutnov 2 Feb 12, 2022
Arbitrary precision fraction in Swift.

Fraction Arbitrary precision fraction in Swift. Usage Fraction can be converted from BinaryInteger, BinaryFloatingPoint or String. It supports nearly

Vaida 0 Dec 10, 2021
A set of protocols for Arithmetic, Statistics and Logical operations

Arithmosophi - Arithmosoϕ Arithmosophi is a set of missing protocols that simplify arithmetic and statistics on generic objects or functions. As Equat

Eric Marchand 66 Jul 9, 2022
AsyncTimer is a precision asynchronous timer. You can also use it as a countdown timer

AsyncTimer ?? Features Can work as a countdown timer Can work as a periodic Timer Can work as a scheduled timer Working with user events (like: scroll

Adrian Bobrowski 26 Jan 1, 2023
Swift type modelling the success/failure of arbitrary operations.

Result This is a Swift µframework providing Result<Value, Error>. Result<Value, Error> values are either successful (wrapping Value) or failed (wrappi

Antitypical 2.5k Dec 26, 2022
Swift type modelling the success/failure of arbitrary operations.

Result This is a Swift µframework providing Result<Value, Error>. Result<Value, Error> values are either successful (wrapping Value) or failed (wrappi

Antitypical 2.5k Dec 26, 2022
Automatically generate GraphQL queries and decode results into Swift objects, and also interact with arbitrary GitHub API endpoints

GitHub API and GraphQL Client This package provides a generic GitHub API client (GithubApiClient) as well as Codable-like GitHub GraphQL querying and

Mike Lewis 4 Aug 6, 2022
A customisable view for entering arbitrary length pins, codes or passwords in iOS. Supports iOS 12 one time codes.

CBPinEntryView CBPinEntryView is a view written in Swift to allow easy and slick entry of pins, codes or passwords. It allows backspacing, dismissal o

Chris Byatt 183 Dec 5, 2022