diff --git a/Tests/FibonacciKitTests/Fibonacci+CoreInt.swift b/Tests/FibonacciKitTests/Fibonacci+CoreInt.swift deleted file mode 100644 index b0976bb5..00000000 --- a/Tests/FibonacciKitTests/Fibonacci+CoreInt.swift +++ /dev/null @@ -1,148 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Ultimathnum open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import CoreKit -import FibonacciKit -import TestKit - -//*============================================================================* -// MARK: * Fibonacci x Core Int -//*============================================================================* - -extension FibonacciTests { - - //=------------------------------------------------------------------------= - // MARK: Metadata - //=------------------------------------------------------------------------= - - private static let coreIntList: [any SystemsInteger.Type] = [ - IX .self, - I8 .self, - I16.self, - I32.self, - I64.self, - UX .self, - U8 .self, - U16.self, - U32.self, - U64.self, - ] - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testCoreInt() { - func whereIs(_ type: T.Type) where T: SystemsInteger { - Case.checkInstancesNearZeroIndex(Test()) - } - - for type in Self.coreIntList { - whereIs(type) - } - } - - func testCoreIntLimit() { - if let (item) = Test().some(try? Fibonacci(10)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: 10, - element: 00000000000000000055, - next: 00000000000000000089 - ) - } - - if let (item) = Test().some(try? Fibonacci(12)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: 12, - element: 00000000000000000144, - next: 00000000000000000233 - ) - } - - if let (item) = Test().some(try? Fibonacci(22)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: 22, - element: 00000000000000017711, - next: 00000000000000028657 - ) - } - - if let (item) = Test().some(try? Fibonacci(23)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: 23, - element: 00000000000000028657, - next: 00000000000000046368 - ) - } - - if let (item) = Test().some(try? Fibonacci(45)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: 45, - element: 00000000001134903170, - next: 00000000001836311903 - ) - } - - if let (item) = Test().some(try? Fibonacci(46)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: 46, - element: 00000000001836311903, - next: 00000000002971215073 - ) - } - - if let (item) = Test().some(try? Fibonacci(91)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: 91, - element: 04660046610375530309, - next: 07540113804746346429 - ) - } - - if let (item) = Test().some(try? Fibonacci(92)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: 92, - element: 07540113804746346429, - next: 12200160415121876738 - ) - } - } -} diff --git a/Tests/FibonacciKitTests/Fibonacci+DoubleInt.swift b/Tests/FibonacciKitTests/Fibonacci+DoubleInt.swift deleted file mode 100644 index fcd1a9d9..00000000 --- a/Tests/FibonacciKitTests/Fibonacci+DoubleInt.swift +++ /dev/null @@ -1,225 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Ultimathnum open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import CoreKit -import DoubleIntKit -import FibonacciKit -import TestKit - -//*============================================================================* -// MARK: * Fibonacci x Double Int -//*============================================================================* - -extension FibonacciTests { - - //=------------------------------------------------------------------------= - // MARK: Metadata - //=------------------------------------------------------------------------= - - private static let doubleIntList: [any SystemsInteger.Type] = [ - DoubleInt.self, DoubleInt>.self, - DoubleInt.self, DoubleInt>.self, - DoubleInt.self, DoubleInt>.self, - DoubleInt.self, DoubleInt>.self, - ] - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDoubleInt() { - func whereIs(_ type: T.Type) where T: SystemsInteger { - Case.checkInstancesNearZeroIndex(Test()) - } - - for type in Self.doubleIntList { - whereIs(type) - } - } - - /// - Note: `I8x01` and `U8x01` divide-and-conquer a lot. - func testDoubleIntLimit8x01() { - typealias I8x01 = I8 - typealias U8x01 = U8 - - if let (item) = Test().some(try? Fibonacci(I8x01("10")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: I8x01("10")!, - element: I8x01("55")!, - next: I8x01("89")! - ) - } - - if let (item) = Test().some(try? Fibonacci(U8x01("12")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: U8x01("12")!, - element: U8x01("144")!, - next: U8x01("233")! - ) - } - } - - /// - Note: `I8x02` and `U8x02` divide-and-conquer a lot. - func testDoubleIntLimit8x02() { - typealias I8x02 = DoubleInt - typealias U8x02 = DoubleInt - - if let (item) = Test().some(try? Fibonacci(I8x02("22")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: I8x02("22")!, - element: I8x02("17711")!, - next: I8x02("28657")! - ) - } - - if let (item) = Test().some(try? Fibonacci(U8x02("23")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: U8x02("23")!, - element: U8x02("28657")!, - next: U8x02("46368")! - ) - } - } - - /// - Note: `I8x04` and `U8x04` divide-and-conquer a lot. - func testDoubleIntLimit8x04() { - typealias I8x04 = DoubleInt> - typealias U8x04 = DoubleInt> - - if let (item) = Test().some(try? Fibonacci(I8x04("45")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: I8x04("45")!, - element: I8x04("1134903170")!, - next: I8x04("1836311903")! - ) - } - - if let (item) = Test().some(try? Fibonacci(U8x04("46")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: U8x04("46")!, - element: U8x04("1836311903")!, - next: U8x04("2971215073")! - ) - } - } - - /// - Note: `I8x08` and `U8x08` divide-and-conquer a lot. - func testDoubleIntLimit8x08() { - typealias I8x08 = DoubleInt>> - typealias U8x08 = DoubleInt>> - - if let (item) = Test().some(try? Fibonacci(I8x08("91")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: I8x08("91")!, - element: I8x08("04660046610375530309")!, - next: I8x08("07540113804746346429")! - ) - } - - if let (item) = Test().some(try? Fibonacci(U8x08("92")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: U8x08("92")!, - element: U8x08("07540113804746346429")!, - next: U8x08("12200160415121876738")! - ) - } - } - - /// - Note: `I8x16` and `U8x16` divide-and-conquer a lot. - func testDoubleIntLimit8x16() { - typealias I8x16 = DoubleInt>>> - typealias U8x16 = DoubleInt>>> - - if let (item) = Test().some(try? Fibonacci(I8x16("183")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: I8x16("183")!, - element: I8x16("078569350599398894027251472817058687522")!, - next: I8x16("127127879743834334146972278486287885163")! - ) - } - - if let (item) = Test().some(try? Fibonacci(U8x16("185")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: U8x16("185")!, - element: U8x16("205697230343233228174223751303346572685")!, - next: U8x16("332825110087067562321196029789634457848")! - ) - } - } - - /// - Note: `I8x32` and `U8x32` divide-and-conquer a lot. - func testDoubleIntLimit8x32() throws { - typealias I8x32 = DoubleInt>>>> - typealias U8x32 = DoubleInt>>>> - - if let (item) = Test().some(try? Fibonacci(I8x32("367")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: I8x32("367")!, - element: I8x32("22334640661774067356412331900038009953045351020683823507202893507476314037053")!, - next: I8x32("36138207717265885328441519836863123286695915870773021050058862406562749608741")! - ) - } - - if let (item) = Test().some(try? Fibonacci(U8x32("369")!)) { - Case(item).checkIsLastIndex() - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - Case(item).same( - index: U8x32("369")!, - element: U8x32("58472848379039952684853851736901133239741266891456844557261755914039063645794")!, - next: U8x32("94611056096305838013295371573764256526437182762229865607320618320601813254535")! - ) - } - } -} diff --git a/Tests/FibonacciKitTests/Fibonacci+InfiniInt.swift b/Tests/FibonacciKitTests/Fibonacci+InfiniInt.swift deleted file mode 100644 index 17e05628..00000000 --- a/Tests/FibonacciKitTests/Fibonacci+InfiniInt.swift +++ /dev/null @@ -1,284 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Ultimathnum open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import CoreKit -import FibonacciKit -import InfiniIntKit -import TestKit - -//*============================================================================* -// MARK: * Fibonacci x Infini Int -//*============================================================================* - -extension FibonacciTests { - - //=------------------------------------------------------------------------= - // MARK: Metadata - //=------------------------------------------------------------------------= - - private static let infiniIntList: [any BinaryInteger.Type] = [ - InfiniInt.self, InfiniInt.self, - InfiniInt.self, InfiniInt.self, - InfiniInt.self, InfiniInt.self, - InfiniInt.self, InfiniInt.self, - InfiniInt.self, InfiniInt.self, - ] - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInfiniInt() { - func whereIs(_ type: T.Type) where T: BinaryInteger { - Case.checkInstancesNearZeroIndex(Test()) - } - - for type in Self.infiniIntList { - whereIs(type) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Prime 3131 - //=------------------------------------------------------------------------= - - /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+28751 - func testInfiniIntIXLPrime3131() { - guard let item = Test().success(try Fibonacci(28751)) else { return } - #if !DEBUG - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - #endif - Case(item).element(IXL(""" - 0000000179539422936879670273043077421513074187637090531654188941\ - 5741714251061429371751580439620520390780557350979774794868208366\ - 4166176620878272615316694300157066431179767088884468131326626406\ - 6006793087609312815351213411657546695669274095062698689154398219\ - 4273493634687995463092807527082580641615117429769927175041405435\ - 0295797490359697968749112307931392970248348413038891015623785621\ - 6088847611043512273516649762447035351619033256347137730401912564\ - 3331923459443385236632710033100206681972486278892253338953989812\ - 3946916355990491141327157042882267874194134287364062276578746447\ - 9906202330820336469762881009578044941150880449686894920299840694\ - 1491825760720059082900953382857229547427350359177762089685919844\ - 7618397959101638970146048426296929999043034632587960523515344559\ - 3760366379638998785266019668146381119294252066632685499014459540\ - 3228626661986220007077177536233318464572108992736543438403328805\ - 5574464598751322289974611560904876079017322893499933000150292780\ - 9314181521891997450492395408326917003309389028222204533522299269\ - 9642000490804899546448343060640047086553849375374919580904272499\ - 2861624797203649272053099350900207574531796666472086817602155859\ - 1726945528270185394184089768658379449840625960802021947544967032\ - 4466186751708025198780714921940794569731981222458468445510099036\ - 0443553766379370268117503080771639388168258715530538192587730633\ - 8011648767649780378020253215618980934849061793639902195268270484\ - 2839829671374952066915706595211206930317379946812934908158184018\ - 6632013950586228393873546910724730610623601482513609286385660089\ - 5583205661787583142839574359287019169878432307244569229200612045\ - 5315250627992995880563363584077006573129537285154494784466671567\ - 6932915680429008994407050765199142140297716924995768736291428740\ - 5659885583080498298853597502387982203742256599364832940936912262\ - 7306295914308130060217932216792472674883590412715203292872224381\ - 9052280939272105914017040234667970649280968676984639911487164048\ - 6950512688416085851306225825060523983737858111232273015386133906\ - 3067106584779968201933848186941851209943130293249538453239817040\ - 3166446141432467835847673289873984793187889019124685049346194236\ - 9012603600383131016803724007081968761885862426032848180961930077\ - 9950227963208023000595795424035960037191281549377793907086267841\ - 5354352203190660234784252410121708238590550542287009655613245108\ - 4416679066018355796949509138190703862193823826940976741589457419\ - 9842183809073744133600807601681164860417876735323999739439826648\ - 6396093302983871451192612904135076545912778407507119999762905951\ - 0904335217479313753450789666808129764725813866718422907715543747\ - 5344763133751758328696596023139757344616559598352109613358123372\ - 5336145288103713015016170797186814486644452292159678982593774509\ - 0858972188466104850594765553599721902079446786014336284406080746\ - 6047070155943090400227067832916854600535823815502930111708409043\ - 2646551842931647415209855009938485127601076223545576051292990210\ - 2073345189649748973785384281664653132841926472290823737428037653\ - 6301390966801847207486995822378225832339748068221848846740932398\ - 3959466133500499766954176307273566790793220329043374920481301689\ - 7354443162803012925024323638559444813297758478704463046749525448\ - 3994253427313816352373748756985250548695717403420035283611811551\ - 8903829328845718140654077721662950782418573463754497643481431064\ - 3444759787070706038677485548256120377130269594213530852587880736\ - 3063990392833728301764457275979490777842591550350013392734278293\ - 0393930894524284143461403246004295880475120230584716506627288175\ - 5954208405305936426750512693561765614064070467267484067260606449\ - 3160788244304650910047777206727593713757409794734146439721983067\ - 7409870968970884026847313052795953418080569240543747685844136978\ - 5225197858237765766397728263719405697355726278399445515930357298\ - 8820946469896191657334557780499195433494664378529806387436512888\ - 9384612665032347753991477348768850268462782942582242628537367484\ - 9666383666195546877373280285951667514644359014593205613661066790\ - 2637643008076793963393319103431361492547474087057096618104945092\ - 9068797079145859217618763638460930039892230437159663346142492177\ - 3487965404583123116632813844515253796490318415246151607418608028\ - 3165345513066792765071386479447739995779779804703780812619628392\ - 0818316702529642078660025202341533889455931013711373344622660581\ - 7998569624624648319474551095608887152210196761483059300431511310\ - 8382114269844714319724855109740243228740858105309781623648408010\ - 7923960983889953454879306942395750194186332543209679586920699011\ - 6488027814044240538940310045469339495606646708566622415099015800\ - 4029612595363304441617897449047010514432607944518064803360908350\ - 3221111187440030745261296906933672534423314714794484547420193048\ - 0822412634857367963841998731477632114802046883490061951648320782\ - 1113969713026065616413746693504606279025231159734952205068924264\ - 5445300445311422184567380131890416551079481518026600240603387378\ - 1342039627717709671407636367938362954081810163995396023446847021\ - 4631560420750186123322823291039949303888078407967268763717208095\ - 2543903864295730492482781564450746654358853202741987848049019427\ - 6997291932933637411541980129747240034390408819886320767106029202\ - 2157076256100758673195322200389179370252504774367560355559349336\ - 1421680232486838517875664644500753346409203626845922264415603503\ - 6600023866782527437887467155147365535405191710659008737894371890\ - 2544238762746656220809565535557780409118203706433673604351735361\ - 1800390642391766176484428020897344653285440131973888356373655223\ - 9957549790982938642228964935099790778423157577696154898603995912\ - 2480143799026707122818026432168253584012508348126651287673108845\ - 5775153316563617041325708734461855814522735925258064105229767393\ - 9788941361715571270608197036912192258301294845630182802656964927\ - 4745384928401986455586018549294785940736001683767865500630792096\ - 5443200185649550920854638482906746241812642506927742506108188194\ - 9878469667918098704628894843753687311207089697195422433354870257\ - 2096820521441917774150069112449092359767362686064167992531585299\ - 6612569833761373691337107507656423822097124691089029473989643597\ - 4231470719178170567974934919172609491675022209246170315053321249 - """)) - } - - /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+28751 - func testInfiniIntUXLPrime3131() { - guard let item = Test().success(try Fibonacci(28751)) else { return } - #if !DEBUG - Case(item).checkMathInvariants() - Case(item).checkTextInvariants() - Case(item).checkSequencePairIsCoprime() - #endif - Case(item).element(UXL(""" - 0000000179539422936879670273043077421513074187637090531654188941\ - 5741714251061429371751580439620520390780557350979774794868208366\ - 4166176620878272615316694300157066431179767088884468131326626406\ - 6006793087609312815351213411657546695669274095062698689154398219\ - 4273493634687995463092807527082580641615117429769927175041405435\ - 0295797490359697968749112307931392970248348413038891015623785621\ - 6088847611043512273516649762447035351619033256347137730401912564\ - 3331923459443385236632710033100206681972486278892253338953989812\ - 3946916355990491141327157042882267874194134287364062276578746447\ - 9906202330820336469762881009578044941150880449686894920299840694\ - 1491825760720059082900953382857229547427350359177762089685919844\ - 7618397959101638970146048426296929999043034632587960523515344559\ - 3760366379638998785266019668146381119294252066632685499014459540\ - 3228626661986220007077177536233318464572108992736543438403328805\ - 5574464598751322289974611560904876079017322893499933000150292780\ - 9314181521891997450492395408326917003309389028222204533522299269\ - 9642000490804899546448343060640047086553849375374919580904272499\ - 2861624797203649272053099350900207574531796666472086817602155859\ - 1726945528270185394184089768658379449840625960802021947544967032\ - 4466186751708025198780714921940794569731981222458468445510099036\ - 0443553766379370268117503080771639388168258715530538192587730633\ - 8011648767649780378020253215618980934849061793639902195268270484\ - 2839829671374952066915706595211206930317379946812934908158184018\ - 6632013950586228393873546910724730610623601482513609286385660089\ - 5583205661787583142839574359287019169878432307244569229200612045\ - 5315250627992995880563363584077006573129537285154494784466671567\ - 6932915680429008994407050765199142140297716924995768736291428740\ - 5659885583080498298853597502387982203742256599364832940936912262\ - 7306295914308130060217932216792472674883590412715203292872224381\ - 9052280939272105914017040234667970649280968676984639911487164048\ - 6950512688416085851306225825060523983737858111232273015386133906\ - 3067106584779968201933848186941851209943130293249538453239817040\ - 3166446141432467835847673289873984793187889019124685049346194236\ - 9012603600383131016803724007081968761885862426032848180961930077\ - 9950227963208023000595795424035960037191281549377793907086267841\ - 5354352203190660234784252410121708238590550542287009655613245108\ - 4416679066018355796949509138190703862193823826940976741589457419\ - 9842183809073744133600807601681164860417876735323999739439826648\ - 6396093302983871451192612904135076545912778407507119999762905951\ - 0904335217479313753450789666808129764725813866718422907715543747\ - 5344763133751758328696596023139757344616559598352109613358123372\ - 5336145288103713015016170797186814486644452292159678982593774509\ - 0858972188466104850594765553599721902079446786014336284406080746\ - 6047070155943090400227067832916854600535823815502930111708409043\ - 2646551842931647415209855009938485127601076223545576051292990210\ - 2073345189649748973785384281664653132841926472290823737428037653\ - 6301390966801847207486995822378225832339748068221848846740932398\ - 3959466133500499766954176307273566790793220329043374920481301689\ - 7354443162803012925024323638559444813297758478704463046749525448\ - 3994253427313816352373748756985250548695717403420035283611811551\ - 8903829328845718140654077721662950782418573463754497643481431064\ - 3444759787070706038677485548256120377130269594213530852587880736\ - 3063990392833728301764457275979490777842591550350013392734278293\ - 0393930894524284143461403246004295880475120230584716506627288175\ - 5954208405305936426750512693561765614064070467267484067260606449\ - 3160788244304650910047777206727593713757409794734146439721983067\ - 7409870968970884026847313052795953418080569240543747685844136978\ - 5225197858237765766397728263719405697355726278399445515930357298\ - 8820946469896191657334557780499195433494664378529806387436512888\ - 9384612665032347753991477348768850268462782942582242628537367484\ - 9666383666195546877373280285951667514644359014593205613661066790\ - 2637643008076793963393319103431361492547474087057096618104945092\ - 9068797079145859217618763638460930039892230437159663346142492177\ - 3487965404583123116632813844515253796490318415246151607418608028\ - 3165345513066792765071386479447739995779779804703780812619628392\ - 0818316702529642078660025202341533889455931013711373344622660581\ - 7998569624624648319474551095608887152210196761483059300431511310\ - 8382114269844714319724855109740243228740858105309781623648408010\ - 7923960983889953454879306942395750194186332543209679586920699011\ - 6488027814044240538940310045469339495606646708566622415099015800\ - 4029612595363304441617897449047010514432607944518064803360908350\ - 3221111187440030745261296906933672534423314714794484547420193048\ - 0822412634857367963841998731477632114802046883490061951648320782\ - 1113969713026065616413746693504606279025231159734952205068924264\ - 5445300445311422184567380131890416551079481518026600240603387378\ - 1342039627717709671407636367938362954081810163995396023446847021\ - 4631560420750186123322823291039949303888078407967268763717208095\ - 2543903864295730492482781564450746654358853202741987848049019427\ - 6997291932933637411541980129747240034390408819886320767106029202\ - 2157076256100758673195322200389179370252504774367560355559349336\ - 1421680232486838517875664644500753346409203626845922264415603503\ - 6600023866782527437887467155147365535405191710659008737894371890\ - 2544238762746656220809565535557780409118203706433673604351735361\ - 1800390642391766176484428020897344653285440131973888356373655223\ - 9957549790982938642228964935099790778423157577696154898603995912\ - 2480143799026707122818026432168253584012508348126651287673108845\ - 5775153316563617041325708734461855814522735925258064105229767393\ - 9788941361715571270608197036912192258301294845630182802656964927\ - 4745384928401986455586018549294785940736001683767865500630792096\ - 5443200185649550920854638482906746241812642506927742506108188194\ - 9878469667918098704628894843753687311207089697195422433354870257\ - 2096820521441917774150069112449092359767362686064167992531585299\ - 6612569833761373691337107507656423822097124691089029473989643597\ - 4231470719178170567974934919172609491675022209246170315053321249 - """)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x 1 000 000 - //=------------------------------------------------------------------------= - - func testInfiniInt1e6() throws { - #if DEBUG - throw XCTSkip("req. release mode") - #else - guard let item = Test().success(try Fibonacci(1000000)) else { return } - - always: do { - Test().same(item.index, 1000000) - Case(item).checkMathInvariants() - } - - for x in [item.element, item.element.complement()] { - Test().description(roundtripping: IXL(raw: x), radix: 16) - Test().description(roundtripping: UXL(raw: x), radix: 16) - } - #endif - } -} diff --git a/Tests/FibonacciKitTests/Fibonacci+Stride.swift b/Tests/FibonacciKitTests/Fibonacci+Stride.swift new file mode 100644 index 00000000..baeeca0c --- /dev/null +++ b/Tests/FibonacciKitTests/Fibonacci+Stride.swift @@ -0,0 +1,208 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Ultimathnum open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import CoreKit +import FibonacciKit +import RandomIntKit +import TestKit2 + +//*============================================================================* +// MARK: * Fibonacci x Stride +//*============================================================================* + +@Suite struct FibonacciTestsOnStride { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + @Test( + "Fibonacci: for each (index, increment, decrement) in range", + Tag.List.tags(.generic, .exhaustive), + arguments: FibonacciTests.metadata + ) func forEachIndexIncrementDecrementInRange( + metadata: FibonacciTests.Metadata + ) throws { + + try whereIs(metadata.type) + func whereIs(_ type: T.Type) throws where T: BinaryInteger { + let arbitrary: IX = conditional(debug: 144, release: 369) + let low: IX = metadata.low ?? -arbitrary + let high: IX = metadata.high ?? arbitrary + var fibonacci = try #require(try Fibonacci(T(low))) + + scope: if let _ = metadata.low { + try #require(throws: Fibonacci.Error.indexOutOfBounds) { + try fibonacci.decrement() + } + + guard T.isSigned else { break scope } + try #require(throws: Fibonacci.Error.indexOutOfBounds) { + try Fibonacci(T(fibonacci.index - 1)) + } + } + + while fibonacci.index < high { + let (i, a, b) = fibonacci.components() + try #require(try fibonacci.increment()) + try #require(fibonacci.components() == (i + 1, b, b + a)) + + let (indexed) = try Fibonacci(fibonacci.index) + try #require(fibonacci.components() == indexed.components()) + } + + scope: if let _ = metadata.high { + try #require(throws: Fibonacci.Error.overflow) { + try fibonacci.increment() + } + + try #require(throws: Fibonacci.Error.overflow) { + try Fibonacci(T(fibonacci.index + 1)) + } + } + + while fibonacci.index > low { + let (i, a, b) = fibonacci.components() + try #require(try fibonacci.decrement()) + try #require(fibonacci.components() == (i - 1, b - a, a)) + } + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Jump + //=------------------------------------------------------------------------= + + @Test( + "Fibonacci/stride: random jump in range", + Tag.List.tags(.generic, .random), + arguments: FibonacciTests.metadata, fuzzers + ) func randomJumpInRange( + metadata: FibonacciTests.Metadata, + randomness: consuming FuzzerInt + ) throws { + + try whereIs(metadata.type) + func whereIs(_ type: T.Type) throws where T: BinaryInteger { + let low = T(metadata.low ?? -369) + let high = T(metadata.high ?? 369) + + for _ in 0 ..< conditional(debug: 8, release: 32) { + let i = next() + + try #require((low...high).contains(i.0)) + try #require((low...high).contains(i.1)) + try #require((low...high).contains(i.2)) + + let a = try #require(try Fibonacci(i.0)) + let b = try #require(try Fibonacci(i.1)) + let c = try #require(try Fibonacci(i.2)) + + always: do { + var x: Fibonacci = a + try #require(try x.increment(by: b)) + try #require(x.components() == c.components()) + } + + always: do { + var x: Fibonacci = b + try #require(try x.increment(by: a)) + try #require(x.components() == c.components()) + } + + always: do { + var x: Fibonacci = c + try #require(try x.decrement(by: b)) + try #require(x.components() == a.components()) + + } + + always: do { + var x: Fibonacci = c + try #require(try x.decrement(by: a)) + try #require(x.components() == b.components()) + } + } + + /// Two random indices and their sum in [low, high]. + func next() -> (T, T, T) { + var a = low, b = high + + let i = T.random(in: a...b, using: &randomness) + + (a, b) = ( + Swift.max(a, a.minus(i).optional() ?? a), + Swift.min(b, b.minus(i).optional() ?? b) + ) + + let j = T.random(in: a...b, using: &randomness) + return (i, j, i + j) + } + } + } + + @Test( + "Fibonacci/stride: random jump out of bounds throws error", + Tag.List.tags(.generic, .todo, .random), + arguments: FibonacciTests.metadataAsSystemsInteger, fuzzers + ) func randomJumpOutOfBoundsThrowsError( + metadata: FibonacciTests.Metadata, + randomness: consuming FuzzerInt + ) throws { + + try whereIs(metadata.type) + func whereIs(_ type: T.Type) throws where T: BinaryInteger { + let low = try T(#require(metadata.low )) + let high = try T(#require(metadata.high)) + + for _ in 0 ..< conditional(debug: 8, release: 32) { + let i = T.random(in: low...high, using: &randomness) + var a = try Fibonacci(i) + + if let k = (i+1).minus(low).optional(), k <= high { + let j = T.random(in: k...high, using: &randomness) + let b = try Fibonacci(j) + + try #require(throws: Fibonacci.Error.indexOutOfBounds) { + try a.decrement(by: b) // i - j < low + } + } + + if let k = i.minus(high+1).optional(), k >= low { + let j = T.random(in: low...k, using: &randomness) + let b = try Fibonacci(j) + + try #require(low.isNegative, "todo: index < 0") + try #require(throws: Fibonacci.Error.indexOutOfBounds) { + try a.decrement(by: b) // i - j > high + } + } + + if let k = low.minus(i+1).optional(), k >= low { + let j = T.random(in: low...k, using: &randomness) + let b = try Fibonacci(j) + + try #require(low.isNegative, "todo: index < 0") + try #require(throws: Fibonacci.Error.indexOutOfBounds) { + try a.decrement(by: b) // i + j < low + } + } + + if let k = (high+1).minus(i).optional(), k <= high { + let j = T.random(in: k...high, using: &randomness) + let b = try Fibonacci(j) + + try #require(throws: Fibonacci.Error.overflow) { + try a.increment(by: b) // i + j > high + } + } + } + } + } +} diff --git a/Tests/FibonacciKitTests/Fibonacci.swift b/Tests/FibonacciKitTests/Fibonacci.swift index c8376ce8..b2880b62 100644 --- a/Tests/FibonacciKitTests/Fibonacci.swift +++ b/Tests/FibonacciKitTests/Fibonacci.swift @@ -8,84 +8,106 @@ //=----------------------------------------------------------------------------= import CoreKit +import DoubleIntKit import FibonacciKit -import TestKit +import InfiniIntKit +import RandomIntKit +import TestKit2 //*============================================================================* // MARK: * Fibonacci //*============================================================================* -final class FibonacciTests: XCTestCase { +@Suite struct FibonacciTests { - //*========================================================================* - // MARK: * Case - //*========================================================================* + typealias I8x2 = DoubleInt + typealias I8x4 = DoubleInt + typealias I8x8 = DoubleInt - struct Case { - - typealias Item = Fibonacci - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - var test: Test - var item: Item + typealias U8x2 = DoubleInt + typealias U8x4 = DoubleInt + typealias U8x8 = DoubleInt + + typealias I8L = InfiniInt + typealias U8L = InfiniInt + + struct Metadata { + let type: any BinaryInteger.Type + let low: Optional + let high: Optional + } + + static let metadata: [Metadata] = [ + Metadata(type: I8 .self, low: 0, high: 10), + Metadata(type: U8 .self, low: 0, high: 12), + Metadata(type: I16 .self, low: 0, high: 22), + Metadata(type: U16 .self, low: 0, high: 23), + Metadata(type: I32 .self, low: 0, high: 45), + Metadata(type: U32 .self, low: 0, high: 46), + Metadata(type: I64 .self, low: 0, high: 91), + Metadata(type: U64 .self, low: 0, high: 92), - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - init(_ item: Item, test: Test) { - self.test = test - self.item = item - } + Metadata(type: I8x2.self, low: 0, high: 22), + Metadata(type: U8x2.self, low: 0, high: 23), + Metadata(type: I8x4.self, low: 0, high: 45), + Metadata(type: U8x4.self, low: 0, high: 46), + Metadata(type: I8x8.self, low: 0, high: 91), + Metadata(type: U8x8.self, low: 0, high: 92), - init(_ item: Item, file: StaticString = #file, line: UInt = #line) { - self.init(item, test: Test(file: file, line: line)) - } - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Assertions -//=----------------------------------------------------------------------------= - -extension FibonacciTests.Case { + Metadata(type: I8L .self, low: 0, high: nil), + Metadata(type: U8L .self, low: 0, high: nil) + ] + + static let metadataAsSystemsInteger = metadata.filter({ !$0.type.isArbitrary }) //=------------------------------------------------------------------------= - // MARK: Utilities + // MARK: Tests //=------------------------------------------------------------------------= - func element(_ element: Value?) { - test.same(item.element, element) + @Test( + "Fibonacci: start is (0, 0, 1)", + Tag.List.tags(.generic), + arguments: metadata + ) func startIsZeroZeroOne(metadata: Metadata) throws { + + try whereIs(metadata.type) + func whereIs(_ type: T.Type) throws where T: BinaryInteger { + try #require(Fibonacci( ).components() == (0, 0, 1)) + try #require(Fibonacci(T.zero).components() == (0, 0, 1)) + } } - func same(index: Value, element: Value, next: Value) { - test.same(item.index, index, "index") - test.same(item.element, element, "element") - test.same(item.next, next, "next") + @Test( + "Fibonacci: pairs are coprime", + Tag.List.tags(.generic, .random), + arguments: metadata, fuzzers + ) func pairsAreCoprime(metadata: Metadata, randomness: consuming FuzzerInt) throws { + + try whereIs(metadata.type) + func whereIs(_ type: T.Type) throws where T: BinaryInteger { + let arbitrary: IX = conditional(debug: 144, release: 369) + let low = T(metadata.low ?? -arbitrary) + let high = T(metadata.high ?? arbitrary) + + for _ in 0 ..< conditional(debug: 8, release: 32) { + let index = T.random(in: low...high, using: &randomness) + let fibonacci = try #require(try Fibonacci(index)) + try #require(fibonacci.element.euclidean(fibonacci.next) == 1) + } + } } - //=------------------------------------------------------------------------= - // MARK: Utilities x Invariants - //=------------------------------------------------------------------------= - - /// Generates new instances and uses them to check math invariants. - /// - /// #### Invariants + /// Generates random values to check the following invariant: /// - /// ``` - /// f(x) * f(y) == (f(x+y+1) / f(x+1) - f(y+1)) * f(x+1) + f(x+y+1) % f(x+1) - /// ``` + /// f(x) * f(y) == (f(x+y+1) / f(x+1) - f(y+1)) * f(x+1) + f(x+y+1) % f(x+1) /// - /// #### Calls: Fibonacci + /// ### Calls: Fibonacci /// /// - Fibonacci.init(\_:) /// - Fibonacci/increment(by:) /// - Fibonacci/decrement(by:) /// - /// #### Calls: BinaryInteger + /// ### Calls: BinaryInteger /// /// - BinaryInteger/plus(\_:) /// - BinaryInteger/minus(\_:) @@ -93,201 +115,72 @@ extension FibonacciTests.Case { /// - BinaryInteger/quotient(\_:) /// - BinaryInteger/division(\_:) /// - func checkMathInvariants() { - for divisor: Nonzero in [2, 3, 5, 7, 11].map(Nonzero.init) { - always: do { - var a = self.item + @Test( + "Fibonacci: math invariant", + Tag.List.tags(.generic, .random), + arguments: metadata, fuzzers + ) func mathInvariant( + metadata: Metadata, + randomness: consuming FuzzerInt + ) throws { + + try whereIs(metadata.type) + func whereIs(_ type: T.Type) throws where T: BinaryInteger { + let arbitrary: IX = conditional(debug: 144, release: 369) + let low = T(metadata.low ?? -arbitrary) + let high = T(metadata.high ?? arbitrary) + //=----------------------------------= + let x = Bad.message("arithmetic") + //=----------------------------------= + for _ in 0 ..< conditional(debug: 8, release: 32) { + let i = next() - let b = try Fibonacci( - .init(a.index) - .quotient(divisor) - .unwrap("todo: consider Optional/prune(_:)") - .prune(Bad.division) - ) + try #require((low...high).contains(i.0)) + try #require((low...high).contains(i.1)) + try #require((low...high).contains(i.2)) - let c = try Value - .init(a.next) - .division(Nonzero(b.next, prune: Bad.divisor)) - .unwrap("todo: consider Optional/prune(_:)") - .prune(Bad.division) + var a = try Fibonacci(i.0) + let b = try Fibonacci(i.1) + let c = try #require(a.next.division(b.next)).prune(x) try a.decrement(by: b) - let d = try Value - .init (b.element) - .times(a.element) - .prune(Bad.multiplication) - - let e = try Value - .init (c.quotient) - .minus(a.next) - .prune(Bad.subtraction) - .times(b.next) - .prune(Bad.multiplication) - .plus(c.remainder) - .prune(Bad.addition) + let d = try a.element.times(b.element).prune(x) + let e = try c.quotient.minus((a.next)).prune(x).times(b.next).prune(x).plus(c.remainder).prune(x) try a.increment(by: b) + try #require((d) == e) + } + + /// Two random indices and their difference in [low, high]. + func next() -> (T, T, T) { + var a = low, b = high - test.same(d, e, "arithmetic invariant error") - self.same(index: a.index, element: a.element, next: a.next) + let i = T.random(in: a...b, using: &randomness) + + (a, b) = ( + Swift.max(a, i.minus(b).optional() ?? a), + Swift.min(b, i.minus(a).optional() ?? b) + ) - } catch let error { - test.fail("unexpected arithmetic failure: \(error)") + let j = T.random(in: a...b, using: &randomness) + return (i, j, i - j) } } } - - /// Performs a description round-trip for each radix. - func checkTextInvariants() { - for radix: UX in 2 ... 36 { - test.description(roundtripping: item.element, radix: radix) - } - } - - func checkSequencePairIsCoprime() { - test.same(item.element.euclidean(item.next), 1) - } +} + +//*============================================================================* +// MARK: * Fibonacci x Utilities +//*============================================================================* + +extension Fibonacci { //=------------------------------------------------------------------------= - // MARK: Utilities x Min, Max + // MARK: Utilities //=------------------------------------------------------------------------= - func checkIsZeroIndex() { - test.same(item.index, Value.zero) - - var copy = self - copy.test.success(try copy.item.double()) - copy.same(index: item.index, element: item.element, next: item.next) - - copy = self - copy.test.failure(try copy.item.decrement(), Item.Error.indexOutOfBounds) - copy.same(index: item.index, element: item.element, next: item.next) - } - - func checkIsLastIndex() { - var copy = copy self - copy.test.failure(try copy.item.double(), Item.Error.overflow) - copy.same(index: item.index, element: item.element, next: item.next) - - copy = self - copy.test.failure(try copy.item.increment(), Item.Error.overflow) - copy.same(index: item.index, element: item.element, next: item.next) - } - - static func checkInstancesNearZeroIndex(_ test: Test) { - func make(_ item: Item) -> Self { - Self(item, test: test) - } - - beyond: do { - let error: Item.Error = Value.isSigned ? .indexOutOfBounds : .overflow - test.failure(try Item(~0), error) - test.failure(try Item(~1), error) - test.failure(try Item(~2), error) - test.failure(try Item(~3), error) - test.failure(try Item(~4), error) - } - - zero: do { - make( Item( )).checkIsZeroIndex() - make(try Item(0)).checkIsZeroIndex() - } catch { - test.fail(error.localizedDescription) - } - - index: do { - make( Item( )).same(index: 0, element: 0, next: 1) - make(try Item(0)).same(index: 0, element: 0, next: 1) - make(try Item(1)).same(index: 1, element: 1, next: 1) - make(try Item(2)).same(index: 2, element: 1, next: 2) - make(try Item(3)).same(index: 3, element: 2, next: 3) - make(try Item(4)).same(index: 4, element: 3, next: 5) - make(try Item(5)).same(index: 5, element: 5, next: 8) - } catch { - test.fail(error.localizedDescription) - } - - increment: if let item = test.some(try? Item(0)) { - var instance = make(item) - - instance.same(index: 0, element: 0, next: 1) - instance.test.success(try instance.item.increment()) - instance.same(index: 1, element: 1, next: 1) - instance.test.success(try instance.item.increment()) - instance.same(index: 2, element: 1, next: 2) - instance.test.success(try instance.item.increment()) - instance.same(index: 3, element: 2, next: 3) - instance.test.success(try instance.item.increment()) - instance.same(index: 4, element: 3, next: 5) - instance.test.success(try instance.item.increment()) - instance.same(index: 5, element: 5, next: 8) - } - - decrement: if let item = test.some(try? Item(5)) { - var instance = make(item) - - instance.same(index: 5, element: 5, next: 8) - instance.test.success(try instance.item.decrement()) - instance.same(index: 4, element: 3, next: 5) - instance.test.success(try instance.item.decrement()) - instance.same(index: 3, element: 2, next: 3) - instance.test.success(try instance.item.decrement()) - instance.same(index: 2, element: 1, next: 2) - instance.test.success(try instance.item.decrement()) - instance.same(index: 1, element: 1, next: 1) - instance.test.success(try instance.item.decrement()) - instance.same(index: 0, element: 0, next: 1) - } - - double: if let item = test.some(try? Item(1)) { - var instance = make(item) - - instance.same(index: 1, element: 1, next: 1) - instance.test.success(try instance.item.double()) - instance.same(index: 2, element: 1, next: 2) - instance.test.success(try instance.item.double()) - instance.same(index: 4, element: 3, next: 5) - } - - increment: if let item = test.some(try? Item(1)) { - var lhs = make(item) - var rhs = make(item) - - lhs.same(index: 01, element: 01, next: 01) - rhs.same(index: 01, element: 01, next: 01) - - test.success(try lhs.item.increment(by: rhs.item)) - lhs.same(index: 02, element: 01, next: 02) - test.success(try rhs.item.increment(by: lhs.item)) - rhs.same(index: 03, element: 02, next: 03) - test.success(try lhs.item.increment(by: rhs.item)) - lhs.same(index: 05, element: 05, next: 08) - test.success(try rhs.item.increment(by: lhs.item)) - rhs.same(index: 08, element: 21, next: 34) - } - - decrement: if let low = test.some(try? Item(5)), let high = test.some(try? Item(8)) { - var lhs = make(low ) - var rhs = make(high) - - lhs.same(index: 05, element: 05, next: 08) - rhs.same(index: 08, element: 21, next: 34) - - test.success(try rhs.item.decrement(by: lhs.item)) - rhs.same(index: 03, element: 02, next: 03) - test.success(try lhs.item.decrement(by: rhs.item)) - lhs.same(index: 02, element: 01, next: 02) - test.success(try rhs.item.decrement(by: lhs.item)) - rhs.same(index: 01, element: 01, next: 01) - test.success(try lhs.item.decrement(by: rhs.item)) - lhs.same(index: 01, element: 01, next: 01) - test.success(try rhs.item.decrement(by: lhs.item)) - rhs.same(index: 00, element: 00, next: 01) - test.success(try lhs.item.decrement(by: rhs.item)) - lhs.same(index: 01, element: 01, next: 01) - test.failure(try rhs.item.decrement(by: lhs.item), Item.Error.indexOutOfBounds) - rhs.same(index: 00, element: 00, next: 01) - } + @inlinable func components() -> (index: Value, element: Value, next: Value) { + (self.index, self.element, self.next) } }