commit 00b87715fa4b41b5274e8fddb129bb1178811910 Author: Mikko Ahlroth Date: Sun Feb 4 00:38:53 2024 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..599be4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.beam +*.ez +/build +erl_crash.dump diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..8ae513a --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +gleam 0.34.1 +erlang 26.1.2 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..efd7dbe --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) Mikko Ahlroth, 2024. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..73cb276 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# bigi + +[![Package Version](https://img.shields.io/hexpm/v/bigi)](https://hex.pm/packages/bigi) +[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/bigi/) + +```sh +gleam add bigi +``` +```gleam +import bigi + +pub fn main() { + // TODO: An example of the project in use +} +``` + +Further documentation can be found at . + +## Development + +```sh +gleam run # Run the project +gleam test # Run the tests +gleam shell # Run an Erlang shell +``` diff --git a/gleam.toml b/gleam.toml new file mode 100644 index 0000000..5d2906c --- /dev/null +++ b/gleam.toml @@ -0,0 +1,17 @@ +name = "bigi" +version = "1.0.0" + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +# description = "" +# licences = ["Apache-2.0"] +# repository = { type = "github", user = "username", repo = "project" } +# links = [{ title = "Website", href = "https://gleam.run" }] +# +# For a full reference of all the available options, you can have a look at +# https://gleam.run/writing-gleam/gleam-toml/. + +[dev-dependencies] +gleam_stdlib = "~> 0.34 or ~> 1.0" +gleeunit = "~> 1.0" diff --git a/manifest.toml b/manifest.toml new file mode 100644 index 0000000..7762492 --- /dev/null +++ b/manifest.toml @@ -0,0 +1,11 @@ +# This file was generated by Gleam +# You typically do not need to edit this file + +packages = [ + { name = "gleam_stdlib", version = "0.34.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "1FB8454D2991E9B4C0C804544D8A9AD0F6184725E20D63C3155F0AEB4230B016" }, + { name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" }, +] + +[requirements] +gleam_stdlib = { version = "~> 0.34 or ~> 1.0" } +gleeunit = { version = "~> 1.0" } diff --git a/src/bigi.gleam b/src/bigi.gleam new file mode 100644 index 0000000..27922b5 --- /dev/null +++ b/src/bigi.gleam @@ -0,0 +1,93 @@ +pub opaque type Bigi { + Bigi(data: BigInt) +} + +type BigInt + +pub fn from_int(int: Int) { + Bigi(bigint_from(int)) +} + +pub fn to_int(bigi: Bigi) { + bigint_to(bigi.data) +} + +pub fn to_string(bigi: Bigi) { + bigint_to_string(bigi.data) +} + +pub fn zero() { + Bigi(bigint_zero()) +} + +pub fn add(a: Bigi, b: Bigi) { + Bigi(bigint_add(a.data, b.data)) +} + +pub fn subtract(a: Bigi, b: Bigi) { + Bigi(bigint_subtract(a.data, b.data)) +} + +pub fn multiply(a: Bigi, b: Bigi) { + Bigi(bigint_multiply(a.data, b.data)) +} + +pub fn divide(a: Bigi, b: Bigi) { + Bigi(bigint_divide(a.data, b.data)) +} + +pub fn remainder(a: Bigi, b: Bigi) { + Bigi(bigint_remainder(a.data, b.data)) +} + +pub fn modulo(a: Bigi, b: Bigi) { + Bigi(bigint_modulo(a.data, b.data)) +} + +pub fn power(a: Bigi, b: Bigi) { + Bigi(bigint_power(a.data, b.data)) +} + +@external(erlang, "bigi_ffi", "from") +@external(javascript, "./bigi_ffi.mjs", "from") +fn bigint_from(int: Int) -> BigInt + +@external(erlang, "bigi_ffi", "to") +@external(javascript, "./bigi_ffi.mjs", "to") +fn bigint_to(bigint: BigInt) -> Result(Int, Nil) + +@external(erlang, "bigi_ffi", "to_string") +@external(javascript, "./bigi_ffi.mjs", "to_string") +fn bigint_to_string(bigint: BigInt) -> String + +@external(erlang, "bigi_ffi", "zero") +@external(javascript, "./bigi_ffi.mjs", "zero") +fn bigint_zero() -> BigInt + +@external(erlang, "bigi_ffi", "add") +@external(javascript, "./bigi_ffi.mjs", "add") +fn bigint_add(a: BigInt, b: BigInt) -> BigInt + +@external(erlang, "bigi_ffi", "subtract") +@external(javascript, "./bigi_ffi.mjs", "subtract") +fn bigint_subtract(a: BigInt, b: BigInt) -> BigInt + +@external(erlang, "bigi_ffi", "multiply") +@external(javascript, "./bigi_ffi.mjs", "multiply") +fn bigint_multiply(a: BigInt, b: BigInt) -> BigInt + +@external(erlang, "bigi_ffi", "divide") +@external(javascript, "./bigi_ffi.mjs", "divide") +fn bigint_divide(a: BigInt, b: BigInt) -> BigInt + +@external(erlang, "bigi_ffi", "remainder") +@external(javascript, "./bigi_ffi.mjs", "remainder") +fn bigint_remainder(a: BigInt, b: BigInt) -> BigInt + +@external(erlang, "bigi_ffi", "modulo") +@external(javascript, "./bigi_ffi.mjs", "modulo") +fn bigint_modulo(a: BigInt, b: BigInt) -> BigInt + +@external(erlang, "bigi_ffi", "power") +@external(javascript, "./bigi_ffi.mjs", "power") +fn bigint_power(a: BigInt, b: BigInt) -> BigInt diff --git a/src/bigi_ffi.erl b/src/bigi_ffi.erl new file mode 100644 index 0000000..3c69912 --- /dev/null +++ b/src/bigi_ffi.erl @@ -0,0 +1,47 @@ +-module(bigi_ffi). + +-export([ + from/1, + to/1, + to_string/1, + zero/0, + add/2, + subtract/2, + multiply/2, + divide/2, + remainder/2, + modulo/2, + power/2 +]). + +from(Int) -> Int. + +to(BigInt) -> {ok, BigInt}. + +to_string(BigInt) -> erlang:integer_to_binary(BigInt). + +zero() -> 0. + +add(A, B) -> A + B. + +subtract(A, B) -> A - B. + +multiply(A, B) -> A * B. + +divide(A, B) -> A div B. + +remainder(A, B) -> A rem B. + +modulo(A, B) -> ((A rem B) + B) rem B. + +power(_, 0) -> + 1; +power(A, 1) -> + A; +power(A, N) -> + B = power(A, N div 2), + B * B * + (case N rem 2 of + 0 -> 1; + 1 -> A + end). diff --git a/src/bigi_ffi.mjs b/src/bigi_ffi.mjs new file mode 100644 index 0000000..5fd52b8 --- /dev/null +++ b/src/bigi_ffi.mjs @@ -0,0 +1,49 @@ +import { Ok, Error } from "./gleam.mjs"; + +export function from(int) { + return BigInt(int); +} + +export function to(bigint) { + if (bigint > Number.MAX_SAFE_INTEGER || bigint < Number.MIN_SAFE_INTEGER) { + return new Error(undefined); + } else { + return new Ok(Number(bigint)); + } +} + +export function to_string(bigint) { + return bigint.toString(); +} + +export function zero() { + return 0n; +} + +export function add(a, b) { + return a + b; +} + +export function subtract(a, b) { + return a - b; +} + +export function multiply(a, b) { + return a * b; +} + +export function divide(a, b) { + return a / b; +} + +export function remainder(a, b) { + return a % b; +} + +export function modulo(a, b) { + return ((a % b) + b) % b; +} + +export function power(a, b) { + return a ** b; +} diff --git a/test/bigi_test.gleam b/test/bigi_test.gleam new file mode 100644 index 0000000..1ce0e70 --- /dev/null +++ b/test/bigi_test.gleam @@ -0,0 +1,81 @@ +import gleeunit +import gleeunit/should +import bigi + +const js_max_safe_int = 9_007_199_254_740_991 + +const js_min_safe_int = -9_007_199_254_740_991 + +pub fn main() { + gleeunit.main() +} + +// gleeunit test functions end in `_test` +pub fn zero_test() { + should.equal( + bigi.zero() + |> bigi.to_int(), + Ok(0), + ) +} + +pub fn add_test() { + should.equal( + bigi.add(bigi.from_int(js_max_safe_int), bigi.from_int(2)) + |> bigi.to_string(), + "9007199254740993", + ) +} + +pub fn subtract_test() { + should.equal( + bigi.subtract(bigi.from_int(js_min_safe_int), bigi.from_int(2)) + |> bigi.to_string(), + "-9007199254740993", + ) +} + +pub fn multiply_test() { + should.equal( + bigi.multiply( + bigi.from_int(js_max_safe_int), + bigi.from_int(js_max_safe_int), + ) + |> bigi.to_string(), + "81129638414606663681390495662081", + ) +} + +pub fn divide_test() { + should.equal( + bigi.divide( + bigi.multiply( + bigi.from_int(js_max_safe_int), + bigi.from_int(js_max_safe_int), + ), + bigi.from_int(js_max_safe_int), + ), + bigi.from_int(js_max_safe_int), + ) +} + +pub fn remainder_test() { + should.equal( + bigi.remainder(bigi.from_int(-5), bigi.from_int(3)), + bigi.from_int(-2), + ) +} + +pub fn modulo_test() { + should.equal( + bigi.modulo(bigi.from_int(-5), bigi.from_int(3)), + bigi.from_int(1), + ) +} + +pub fn power_test() { + should.equal( + bigi.to_string(bigi.power(bigi.from_int(2), bigi.from_int(65_535))), + "1001764965203423232489536175780127875223912737784875709632508486855447029778155726544753065440466674050519117171453631590911474691059406334434753182380773514582520935958175793983173609721465463991042154552427995285079659479819762431686183601501458484796078054382474444627045402955728518837604250103335781851183063179873572403555887407940457067871360483595075918141280309045729426349913070712515061695554136801921883938224521602980189562245452853780157017538081281238015931896563242351871891477487806885490802307206654346059051242979576190097665515146081400080284335052825823375284019370764731921122422646268680721266807186864544151897300637362479207432457965323626007577846961314090345825398190532066137653633571999079254405646314450567118891352783710540035032641981661077538915607144275837777036672553606556213699781491359884575027441952611902178522924098978196578926755009496000012070981853406779920232019736097008034758845078059863491168945008820758595025566733153449070109691740717713193653269776484845694012079080929780550320181059898050929767401393583600061302321246192555696700232175811933783539372629732335451943273871741608948506382227764704546010979792875811486666788079776197442648789977014235971764956771881852993464456878576870000993197166232445026271553314834582621709587345694816238280144707599887738851569032390671154798095480327295650445094443794042366812978032722444250723667853029408545081054249857264784172030989845282734906815581026789684895701618164248116523210533068100110087893925928704581025244855890910200093641469971723093112164004918661882465907394924059726356503720110382840455188101999601746011953313132245954583992730757889419530198860379639689426120647150508729043431131684642362925701519807779282165192725344326106557406819204192389131895229803593438364254881735635994445340239121615197359325262830489075364930570715152908463962485704580529708592676137943752238796109150579390350987767861120700009774051002830886794890749766162604294876731773503893345203214508381904080870275202558835046836601402274669513996245933653269965820360246119237407640309583450466902866060408175353817175834934812510484511581429675035937095289580620768448757404130952423973285868300502946238327722920419167395272072408842127663603657793174673802568709889762595182516099010054382369184341265512591688766954430713092400187004041119052038234439235823776472663473830850212230531655619010567294347266100058282038163511537146213025791405535193509172662283817812975715016018716370390439528141831703482515422112927983519635934730579256896693237849874284335039911980302196739425430824630152472530871706182914176072403363338420903541877431105704118289901480600013720662219216201165628701772509676214388215440116425427943044981387229082340428937557903507371881933988477524995821999142178645207689071719423651742130951694420747015683069927128817788552667790103311092788530041275644446666113218140992419306619785338095704819266916187171879415429616861142322143998122802738466214499216326338689186586644031605376605619340302337354214025583244354542385145604080552456277799161183122434278325701342320604847491295282759608094052170613419498141535827434262768457425149769837751977469185926702950048093744736996440216248186582876901836793355087891997409235899249123474030266040998033091717006238048319759889010720599876273352040304249672089128142546363261854949325769731096502303682253963106487958849146946183507585496045765783907219895624237853118902300004959146660653440285023295729193604044008443722917778963129232562381543574283156764467083058745308763335746336088064165422636968234622291446285694438919528150241241899919846014611107743072951186739111341260819978720400863572073089779613087541944510037084963119150141143124642091335621702875712094284997136165803499356493441385910308607226571287472007533069731584598814590753289872763118095612424031945016834537182994613174782057332751531482980099860318101301760958888370334388731774687659449793933141062734898551032873616360686459072333329710936001737254471415455767594635557143554188079611190138302663911675830777574684687889233335072858985950613558906390225120013192379394169698408981475345399408560845343464769124264915011738034227057089069555324280118274877113748615503807565935012026955255456908921860895711264293716049262478939017341851668909210722008569344062124992209309064635599266657691283660935210765315598874267607335477667313168305432333666146204939924628345554758071809300774454870120956754811521806098064082975259333011015357806842366182330434452507131956953257531954099689426159182529948649562702239721712583387149829905924616575777636441637014176344221204376405641644990312956336849773123670771666750073615715306375195153698567626034669086921661475350524530933769716565392399007827565192379077842618109005209825127798090967493157956616518048230952995118056340598011720921681667297463815973050858326456911858591197149608136269230888032847271148938535691599408518482294344905931605488450177867942312232417853145726526378550639436013982682239862012702724066374195897064413211917585974598604898572968443768599364565415869016955508064273707688688857975864042055813798593192462111401186720962734995991836096065643517792653983471356708195516941377159306821745050471598704523665507238149930862712211677806118717857912966691402493121946249111390357975881378923554737559516741120706012591344356864096552126739098064220088239765752528555361487157284957611725821560924328787893264098782421754479192361461767279732260607915828875735649354112954646327819418325560340971918452058126334355022280121852100331854500970592778580236022321848466425030023464070253559534630696996951367767272783735157451943011012319974130250881215984652820333183313045103524443719449453749076432722190931458691450525910434968191330934151957636632290643391403300668750048296682312573045861590156465173938710617339559227395655554948897324108461252814699978396741900849578719850268771067242937293428023643375532711670946919549555293232797556823030527578419270608729900903566581806286539805584171931883833653677291747394894158165064620400418178412969578556565489015258220858341259173286837967099042479473970491646250043194889281747346606236713051531356872538643078461298314286928952766620320924509225664142316354634876915433654204571123829737219986674065405493199708689894828505343513367080983598295799794268917411494135062802921182794769845153237482792073990655498578771021628197888035242550440789145704125388869279895064564703654731392972252929706136597406376612576162400751733259524114480703323445152551255458118885224243115114744483355690277803978310366224686687013918383650101505807613504460921757826060689607874103429678460395107251138566549993864729798476408522291090978040482905851399031334945602530780371162843421135653147504932210926735405203564458823453275418064958347389011911251394833921744599704828680852293393121277003471258346989646312357262472704429211363076877630035952168164598187888751088002597900346923817894793439244768436061449278903413259096351816049740077937227787587656368235710647768247042192793307604006057539537534276672244629346641929826506636023485347285773479676829285894447431166646232601367926594266685474227701668282678494086291264459028317744181871896674205922790084165913838417323145997802756735019573938404320161314808320780333754076855323361554230982123768745276872402659113001355108200490292248763011517820019041736026574970586482868392533210700421348248551620959591060606603469884571961684187354614133869354066118340043462351745793420495576549157706031783061593752152733768491615413983228708810403296588632842920840918983053072481716272055853470850111328908679175629910540384550980526114631939872524509627155950310280953288726208095956593766992024671988411655149232946659186507904796261414603410431115166292640059633248157220658221386501618896137356165348208574972766130517737572815645334427172713434894223871490888746855058807325812091808340127407648167654245424971503381827403051470047346875304922794279021985242957224792222539989248522791775342704372581658232059041561539852194924595253293793212905369211210295595970837091245226350144131991528975028670855743515593571417092249576728351457640052242572588027653485720880684291192051393829662331344989209159810156131210588695738604002441789166784602266967976627282448514279294867752875617564768270251421040511392624388301787123183336574340139743026222891336813115426489132528557312423297957105139061394470724081997486940942311384122425811025908538361084931632850827158459871325615020878664952236768836268422896377182706413276790929023420034683859302510035273623774200402765212475927247633623630673659087371090039287346732723568018487942059014704019808373473144270339586069300612709751909852269208634003199410328164396419791354255459979419724148887823576013066435544763081708853575821449743976782427276776574377489067004982427249317912423845295016558480651883063961732161564853314205653713523101016006684175192712680156818381787606302353712655604616701418741474726552363709484643637786013807636134141688370696712826326641534234998798548875002780444966342512524606442034137069940815770228245175387935840037027842862010879342719526614066885353707915378134814158477843712030263863242926525305678192425982959484324798167784108487718810715389332967365225082411216482445635354949038338312835758634531029407774833191286914637091041139480342244111491697408335492019512141757153406883626730063003634631484734336375397173095219998309489805964375259721178201322151635868670795640748028084176994094284742022671155712306779962636165032440813733361761875617155946721059442542539679081924497243772378165844606934837787151368976892631271164512440523590969518610333447351102129418447920469999226780474434973416926289837580941079705490812459370906682363482561990338780973956278978723235713934312026875288052102133574683042490119137340287991295665503459970952325953265585954463038974559608973203677564816932261517836672794016656598540182728592395775216327449779852931444143433303309010941124301072499986561082069085326740087755219203312206411401808324452128688820478163241412629203834522804219745162645263168766158254543840668307121199154765403274830939690974560016959744747032566199408321040044197777471118548367420036321352850582544537598077685093132398728190593928087728556700236905381381507476654867587090327739556330469017155689266266441766676012467182989564670642427485473413164537915096536332668891279657165555481924026970429641994453898105239923959843438269993738547956394363737937219903389912484139136100463224972279690207304385320970905220379134902844019474827308293991952330293822670905144953597146510887259988052247521598420751727757022410464466689328681526415309995038874363461499304139526585845938289430454470908528996702445109220779895546338431398298791976241963367441817372825843508083120321212120614480559005307841171269696090026241727361889609955614297957095938745896911670005039064163253355140890698014560457360050473939376275631686442111176934745033963832255817379050596937659828621060738019142387387285852289305208692873955650954291938945076167171506502641398519290179907591464800152841306045975471868662727085528191943523764475281980514921820680467820816294704068990755846669309898669910835380502303990048008012411548471521903478310061606825070274793125307641294016511454192906239234657860161616800949734718823863360939688413215914191301782260349734315108024437264212181796779311166753117972501445279290805637670891875227968063065426320414025606936588745100124776369367292978202580415291526885366266985776310222352714786769180556838761584986370146470837102211624056937537815659539136094432026687347106921084964431470239817652575280394063183103248615628789509799436520597813113671864450258280555547055872638982741395235625290999538749031910779688442773249411469492704145662564538239193161247390508376745846744644052101507805141693071913689080473170667691789170382657160708575327938773910126227390328650671138735308372120984476306582137052347737310741878144149885902093392542273482809575454347937125592217918653295475730490225623704705686949963911246491683898005507693548064874852783150818653601375367379961471896196912213710593079118080658943196276547558594210649254153619129864572071125789701941505679541665825929117483610629810906253529056879747762511373637337184943565963335384649599542233580614369429228792311363286665376867786411975808482087599337506340872714661869147071912407188569930953358328786472903902410279755940843594037606485916318221077668393875637383470395058528754909787542281782608694772089937537261927227600066786016666189947537196952656459106127629916895454731815101092676924427412531448857808481930356191385862810656730274700885206790865965881685068166126409563773595721725460355924419183409087131671474805935045751524582669732381858883219560399173747313698911085751045335095151234881075639260978071035403230815686618258926988146046012750144481006485070689820019027867474634536767572980604337398273866846479386814317830071883982019215398432069281723900664130642294592449264024024422090410819711987007181451740832729057227183230016245309381519751178201022265374105120683447598322110669600378739564341902587575317331284695968870141756037833130414945245938643916926089261396022885923482927639395223781096331996004204651037836962681867814195414908788951076601053204808686641799247033326070599091905442257729886447582286065948898953745970506574184272319808452303515053798409466870608787994082563500380631394584755203157928818767393710035111025535445628806180829013403407929249926315732939043308400366632338415103195848601532447202814097703095342621001526731578310945663654534843676590820547257144018302997610124124443355777214552360964567124173219352684254324374549589406335282832693595524860910021185746370082230471729922696268353066105308266542831010594484117002876337743050738496844369104792276105785961739843444080426815807931440075197974709264744613537205414103584651693909042468102009127611135505492826722408603735378009622957799715536474789098939295289470026270061433758571255592178218592026781512090612736633046651355198984045532469636361341517705233816295677639841918852509927617310611429205278559960865858984902169658853875377813528023915889922223818780127318516684623557110407759986845685987581620651374356099931702274124262285059276671337632357989155365622831714902610727747078126362014457666677174670608931018503630157639935385936245617247238573954760367380692712742655776386650515171238417932748046861162003577259064866346040529212045278862822901840731117246594854069448571649915673808899839856226891155351869575736939346059593783350159660640948401661348297229643105303719413708459732581133816270332535440535515197089430282446884908367079512962597305911821472826334686101577752350106799423146379006263857711008314977431565162456155514813961861949883208401748570613263965953818163068407072758188328279919894244690866541334389950981443466148298689975965810593607727643697085121834942796944396658372266681559770759202044141907596710617061410015475156670525352380079993992736264595332611239659857720165897418418686610410942886670811928220690350270956765122971956751277265943227398126130125881464187165232551180528791757275369721669805108114837730707890563598500869305747139750705626640310627387905256486044232631579047403316843835073655366770358855438307967928407049106483865379598691486720722628344385427662285444479160496911716051359112057381866395678784307710626424828951667546576388462752922822005276096322252656036878143872499081823166417908070165087906983679713663845224460180940193377477875903445029266463600746961750262922573353491314274128941633699367610228614119645103572411109942793551448495967936537138907579878810382011975621930101016298298125106289174978855042813193059116906659254507343288532005338139308791886386447946373019701965168635936925268456478563357533448344246940442571471804981006483379539612541137656906424925763451465850131568164471047898788979663817765581033376744325658661936219374031756657256322444983794914406462740038212593293245120555563650678598590690801291589253466122003999328317685772044227433196590854197867890399529865419547440902030467979595453736980452205075258160874840706050382859588741883677875500366808461193268714539728901600021168726403783076521464507247890314817069191775891799882354425674502428486848982619347922997297796045354529478445725570706342252731058972513305875083464130125475385389105975216308691611781218800888399681398049684487595697482516679253577709218228426308337121844460185518747664212963565805268917490370369579316908983829212629018368603234675624326119240670831904030752852414529945348225968220009298560212861503658205004958493762130188681088881715310808372442465405464950504758987270782125602411043357293424627566222133388563931864105665768112150545912195621690107023121111674576779758445408144243994994136815222686216087140107877888983510833158523984864086241696420507821137253635889634699964870154036385197506790772571247024513268052912704686557326552471691242189859303468607222300413399001235614744702880926946101712804151348526438310688686797197112057353537036451362730653679270872845709723243812178841198532851592084233770366733173146836991810002020700357027138816240066371101342696849434893803504795024342325313385681535489910503278642550653300505390316871672386536739326940871340615371883033321656387678233289301857596461384220229136641621904106420609388066021230232450400527365713374630413461077818702743120858515513959998471322810477809908227273831022511205724702374674916103403595676383993373906729101929785206733088968614267470015815799772046842044786266719351493358914885186666403400882319751045011970965749557504552638410559755499531583075155792791417791303589705026264291805684980651721395086905893706030644091031011631924930757828225615023896483781809172884052521670884771533769020556964276896264620673669740525266012854364093153645579455667971007380936332145782018185963801153141920325212720871167732274993527659363443963212051073681849312731873579872177471721949865025871262555438678943195473406048336714076292959962428820244027535664907149679955731619959556979963376288179503723286405095902920903671113867360698861609115885858458200054413056274546680593390287861195509093084274554250442636137187106043262426186228124348831122692409649335564726472757748515292959653599248552707090818484488065563372013504824333772967283529968497732250279460814023988182843066658281953697851636017194587707633750457505599428436354424097765838465840636446071515688409008222738683759176748928962138231677081216800562980126054750806132055173041732824117798967137028434424612229372746888376060162351901517745578772415647637945969946840438163842719384778847440711422155999297850363760696588418915885169565211530479499568657342284505211047580983535253210128366936723057827638087996363575938830005119472380269894758472854401364368112560538112045905033350441737368802578142766971782921878135620622228825831532042969753973775460231966122601267731817222395877830862981093599639593287745428926475006420114517530757468655053504723075505806856211880713361270866027979601391064662862973573208612488660658190922663277639802135270935748118292626229324466627072531321168942825732335302149282390984230796831644477149890361271132395200308009875987503730272575030145903319135748508055493975668316885689217208097026560722645927590068287779333807509686514845966038060004627532540791637754249670384398626184993511783965513402068372859478320715926339527358584981495181507772822545022401394527850984164156815359498849576583339604479384286145300457736459818190836798336979987855163007785960118674290260564058729305032576299441921557255947440276064572887849573288765020692358562288982524087928197536447668769877911043888753036169722793947952859578368", + ) +}