text:
# Lorem Text

lorem_txt = """Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent rutrum fringilla augue, nec ornare felis venenatis sed. Praesent fermentum, mi vel gravida finibus, arcu est consectetur lorem, id convallis lectus enim tincidunt lacus. Nunc felis lectus, volutpat sed aliquet ac, pretium vel ligula. Cras ultricies mollis odio id convallis. Pellentesque ac quam ut erat maximus porta. Quisque vitae felis massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer magna nunc, posuere ut suscipit eget, tincidunt ut purus. Integer varius auctor augue, vitae molestie erat bibendum sit amet. Aenean volutpat rhoncus commodo. Nullam eu ipsum eget lacus convallis rutrum.

Pellentesque non eleifend mi. Phasellus hendrerit massa consequat purus vestibulum, vitae lacinia enim lobortis. Donec posuere quam eu orci semper, in bibendum enim aliquet. Donec aliquet pharetra ex venenatis gravida. Fusce fringilla dui ante. Mauris vel neque sagittis, accumsan justo vestibulum, pharetra magna. In malesuada feugiat sapien, ac dictum nisl. Nullam mollis lobortis sagittis. Donec facilisis quam metus, non lacinia dui feugiat ut. Ut magna ligula, mollis ut dolor eget, mattis consectetur orci. Integer a ornare risus. Quisque et magna quis dui ullamcorper semper. Duis vel turpis sit amet ligula hendrerit tincidunt. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum fringilla nisi a vehicula lobortis.

Proin non velit dui. Quisque ac nunc ipsum. Nulla facilisi. Vestibulum laoreet ex id dictum rutrum. Quisque placerat erat ac augue elementum laoreet. Morbi tincidunt luctus lacus eget euismod. Etiam ut ex mi. Aliquam gravida at mauris eu fermentum. Fusce blandit et diam eu pellentesque. Sed faucibus justo sit amet quam ultrices posuere. Suspendisse potenti. Nam ac egestas velit. In hac habitasse platea dictumst.

Fusce ex elit, cursus non sapien nec, gravida cursus lectus. Sed pharetra ante vitae maximus vehicula. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aenean in eros ut felis feugiat dapibus in ac felis. Nulla pulvinar turpis arcu, finibus hendrerit ipsum semper et. Aenean viverra justo augue, vel vulputate nunc ultrices vel. In velit nulla, lobortis vel euismod eu, semper ut ante. Aliquam in dolor eros. Proin est enim, scelerisque eu cursus non, scelerisque in neque. Nullam non ante interdum, luctus mi eget, scelerisque tortor. Sed at lacus est. Morbi dignissim orci a nisl laoreet feugiat. Ut velit tortor, hendrerit id eros pulvinar, efficitur consequat ligula. Proin ac lorem quis diam bibendum interdum.

Etiam non quam imperdiet, tincidunt elit in, fermentum urna. Maecenas non consequat odio. Vivamus congue lorem massa. In cursus risus tincidunt purus condimentum iaculis. Suspendisse interdum pulvinar tempus. Praesent dolor ligula, tincidunt quis fringilla sed, malesuada porta leo. Cras non ullamcorper magna. Phasellus a elementum tortor, vel feugiat odio. Sed gravida tincidunt odio, et elementum est maximus vel. Ut eleifend ligula magna, et scelerisque lacus dictum vel. Phasellus felis augue, blandit in dolor non, semper faucibus ligula. Cras efficitur, lectus sed varius pulvinar, urna risus cursus quam, id tincidunt nulla est mattis diam. Proin at dolor viverra, rutrum sapien et, finibus enim. In et magna eros.

Nunc molestie tempus posuere. Aliquam erat volutpat. Nam et neque purus. Vivamus id vulputate nisl, a efficitur odio. Curabitur auctor dapibus urna, vitae iaculis est placerat facilisis. Nullam nulla diam, luctus eu sollicitudin ac, sagittis in mauris. Donec at eros convallis, laoreet augue non, consectetur diam. Nullam id libero urna. Aenean hendrerit diam quis lacus cursus dignissim. Nam id molestie eros. Praesent sed tellus eget purus euismod ultricies. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam posuere metus id mauris pellentesque, a efficitur turpis rutrum. Praesent vehicula posuere pellentesque. Nunc mattis, ligula nec vestibulum sagittis, enim justo eleifend sapien, ultricies pharetra risus metus quis magna.

Phasellus sagittis luctus magna in blandit. Etiam ullamcorper, odio ut mollis lacinia, nunc lorem feugiat ex, vitae accumsan orci nibh ut augue. Nullam sit amet lorem erat. Aliquam at ultrices mi, sed laoreet ligula. Integer dictum eros mauris. Nulla congue efficitur diam, eu auctor nunc venenatis ac. Phasellus eu feugiat felis. In ac risus id erat iaculis finibus sed et turpis. Praesent at condimentum ex, eget tincidunt magna. Donec vehicula odio vitae malesuada volutpat. In hac habitasse platea dictumst.

Fusce dictum gravida est, nec ultrices lacus vehicula eu. Vivamus elementum dapibus porttitor. Phasellus facilisis eu lectus ut cursus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer vitae libero sed enim tempor hendrerit non at quam. Vestibulum augue neque, dictum at elit sed, ultricies molestie enim. Nam eu euismod elit. Sed quis porta quam, eget fermentum felis. Nulla nulla libero, finibus in suscipit vel, pretium eget ipsum. Proin a nibh arcu. Phasellus ac felis sodales, euismod ipsum id, sodales sapien. Sed feugiat egestas velit, et pretium tellus bibendum eu. Suspendisse tempor neque non ante faucibus, tincidunt malesuada felis tempor. Cras efficitur non enim et commodo. In et interdum leo. Aenean auctor sollicitudin pulvinar.

Praesent blandit nisi ex, vitae convallis diam rhoncus ut. Morbi feugiat felis eu mi porttitor porta. Pellentesque consectetur nec risus a euismod. Sed tincidunt lorem et hendrerit lobortis. Cras tristique aliquet eros ac rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ex tellus, convallis eget vulputate in, lobortis in ex. Morbi sagittis venenatis ipsum ac blandit. In aliquet erat et sapien suscipit rhoncus. Curabitur sed semper est. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque tincidunt non orci dignissim vestibulum. Praesent elit enim, tempor ac tempor et, auctor non nisi. Phasellus cursus efficitur justo, eu rutrum felis vulputate sit amet.

Praesent dictum vehicula ultrices. Nullam ac bibendum felis. Morbi molestie molestie nisl, a finibus nisi bibendum ac. Proin hendrerit ullamcorper augue eu varius. In convallis ultrices tortor vel mollis. Mauris eget convallis neque, vel tempor diam. Aliquam eleifend mauris enim, sed ullamcorper quam egestas a. Quisque efficitur vestibulum elit eget mollis. Duis non scelerisque risus, ac consequat quam. In magna quam, luctus sit amet justo id, dapibus aliquet leo. Praesent sagittis accumsan sagittis. Quisque nisi mauris, convallis eget ante et, feugiat iaculis velit. Etiam cursus leo risus, vel pretium libero consectetur vel. Suspendisse luctus rutrum sollicitudin. Donec fermentum et ex ac mollis.

Aenean vulputate ante ut turpis tristique, in vehicula lorem gravida. Maecenas auctor, lorem sit amet consectetur finibus, arcu justo rutrum leo, a dapibus neque risus ut neque. Aenean ex odio, sodales quis sodales a, tempor vitae massa. Praesent dictum venenatis finibus. Aenean facilisis facilisis lectus vel fermentum. Praesent ullamcorper rhoncus sem ac semper. In velit leo, viverra vitae mi non, commodo ultrices elit. Fusce aliquam consectetur ipsum, at vulputate urna euismod eu. Praesent vehicula lacinia consequat. Sed sodales venenatis purus at consectetur. Vestibulum semper vehicula blandit. Maecenas vel accumsan est, vel ullamcorper nisl. Quisque vitae dui eget arcu semper tempus. Curabitur non aliquam sapien. Integer quis odio eu risus interdum interdum quis id nunc.

Integer tempus at neque non finibus. Nunc maximus dolor a neque vestibulum, sit amet tristique neque viverra. Aliquam vehicula commodo lorem ut pharetra. Nullam diam sapien, ornare a interdum a, blandit rutrum nisl. Aliquam ut turpis in lacus tincidunt egestas in ut ligula. Vivamus iaculis neque lectus, vitae commodo leo bibendum sit amet. Cras magna nisl, scelerisque in gravida ut, lobortis at turpis. Vestibulum nec venenatis turpis. Proin id purus ut erat faucibus consequat. Cras est velit, condimentum sed cursus eget, condimentum in ligula. Aenean eget lorem quam.

Nulla facilisi. Sed pretium ut erat non rutrum. Proin rutrum fermentum nisi molestie sollicitudin. Vivamus mollis tortor ac posuere maximus. Aliquam blandit nunc vel diam viverra hendrerit. Morbi quis libero pulvinar, viverra risus non, dictum ligula. Fusce porta purus sed sem maximus rutrum. Nullam tincidunt quam et tristique posuere.

Morbi eget quam purus. Nunc vitae lorem malesuada, placerat orci faucibus, placerat est. In varius et felis ut fringilla. In ullamcorper leo suscipit, auctor quam at, dignissim ipsum. Phasellus ligula nunc, elementum eget mauris sed, iaculis tempus neque. Integer eu vehicula leo. Vivamus sodales quis eros at dictum.

Maecenas ut sapien ac leo posuere tincidunt non eu elit. Duis malesuada ante mauris, nec dignissim tellus ultrices non. Duis nulla enim, porttitor ut ante vitae, pellentesque viverra arcu. Integer sollicitudin sit amet tortor nec ultrices. Mauris ut auctor nulla, a lobortis neque. Vivamus dignissim diam vel nunc rhoncus, eget egestas arcu imperdiet. Aenean est metus, suscipit eget magna nec, accumsan egestas dui. Mauris dignissim vitae nisl quis sollicitudin. Praesent accumsan dapibus vehicula. Fusce consectetur vel risus a ultricies. Quisque ac velit vitae erat scelerisque finibus. Suspendisse imperdiet mauris velit, quis sodales enim pulvinar a. Cras venenatis metus in nisi dapibus tristique. Integer iaculis vulputate urna, fringilla maximus lectus auctor eget. Proin convallis lectus sapien, vitae rutrum urna ultrices id. Suspendisse eu finibus nisl.

Phasellus tincidunt urna ac euismod semper. Morbi hendrerit auctor sapien, eu laoreet ante auctor et. Phasellus sit amet laoreet enim. Nulla volutpat congue ligula eu aliquet. Cras suscipit elit vitae turpis bibendum mollis. Nullam eget convallis quam. Ut suscipit ultrices nisi, eget imperdiet tortor dapibus eget. Nullam nec tellus turpis. Nam accumsan elit feugiat nunc porta convallis. Proin eget viverra sem. Sed nulla elit, rutrum a orci at, pellentesque consequat mi. Curabitur at blandit purus.

Mauris porta, risus eu suscipit iaculis, ex est accumsan urna, ut tristique risus dui non lorem. Vestibulum ex augue, gravida ut odio vitae, laoreet luctus massa. Aliquam tincidunt magna at risus sagittis tincidunt. Donec ut magna lacus. Proin consequat, diam nec cursus efficitur, ligula lorem dapibus massa, a luctus lorem nulla rhoncus enim. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla dapibus efficitur pretium. Maecenas vel ultricies arcu. Vestibulum posuere ligula convallis sodales efficitur.

Vivamus ut massa nunc. Morbi rhoncus ac ipsum vitae auctor. Aliquam porttitor maximus odio vitae interdum. Vivamus fringilla ex sit amet nisi sollicitudin maximus. Proin ornare, mi ac ornare tempus, diam neque laoreet nunc, eget feugiat nibh enim sed nulla. Phasellus sed eleifend massa. Vestibulum justo quam, tincidunt pellentesque turpis a, ornare scelerisque justo. Nunc blandit non nunc quis eleifend. Mauris non quam cursus, suscipit purus sit amet, convallis ipsum. Vestibulum tempor, ligula pharetra laoreet rhoncus, elit urna porta nulla, ut dapibus elit diam vitae leo. Morbi molestie vehicula tempus. Etiam vel mauris ultrices, sagittis ante quis, convallis dolor. Vestibulum felis velit, pretium sit amet dui ac, eleifend scelerisque nulla.

Morbi vestibulum sit amet est vel aliquet. Pellentesque scelerisque auctor massa, ut consequat orci laoreet ac. Quisque efficitur nunc a vehicula finibus. Suspendisse euismod est urna, eget semper erat scelerisque vel. Proin sed orci sed ipsum suscipit finibus sed sed elit. Nam commodo nunc justo, id vulputate sapien viverra eget. Mauris eu risus vel ante placerat ornare.

Fusce ac molestie odio, et fermentum justo. Nullam porttitor odio eget nulla vulputate hendrerit. Praesent vitae semper nulla. In enim eros, auctor sed dapibus eu, faucibus at enim. Donec quis facilisis ligula, nec ullamcorper est. Phasellus cursus lobortis erat, non consectetur lectus molestie eget. Aliquam finibus sapien purus, id bibendum massa bibendum sit amet.

In ut urna tempor, tincidunt risus ac, sodales ante. Cras fermentum erat sit amet pulvinar egestas. Donec pulvinar elementum velit, mollis laoreet quam ultricies quis. Donec pellentesque, turpis eget consectetur vehicula, nunc enim fermentum velit, id fringilla arcu quam imperdiet enim. Curabitur condimentum purus urna, et commodo sem rutrum et. Vestibulum sollicitudin nisl id dolor porta, vitae fringilla lacus placerat. Aenean eleifend pharetra justo. Sed tincidunt vulputate leo, et rhoncus est varius eget. Pellentesque in risus id lorem efficitur consequat a sit amet turpis. Ut at mattis lorem.

Fusce libero nibh, tincidunt eu vestibulum vel, pellentesque vel dolor. Suspendisse aliquet egestas orci, sit amet scelerisque dui. Curabitur quam tortor, scelerisque sed pharetra a, facilisis sed enim. Vestibulum ultrices, nisl eu elementum convallis, justo metus ullamcorper diam, nec porttitor tortor turpis quis urna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi aliquam varius nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent ac aliquet lorem, vel vulputate lacus. Phasellus nisi arcu, feugiat eu dolor sed, tristique luctus leo. Nullam a elementum orci, eget rhoncus neque. Quisque blandit libero sit amet erat ultrices condimentum. Suspendisse tristique neque ac orci hendrerit mattis. Curabitur posuere viverra tempus. Quisque mollis orci id vestibulum tincidunt. Aliquam nec elit enim.

Nunc magna ex, varius id elit sit amet, laoreet ornare libero. Vivamus semper lectus sit amet mauris faucibus, vel fringilla libero venenatis. Maecenas bibendum enim at nunc facilisis, in consequat massa auctor. Ut euismod, dolor sit amet lacinia consequat, odio nulla tincidunt risus, eu fermentum urna felis ut erat. Morbi ac enim vel est euismod luctus id a sapien. Mauris dapibus eleifend varius. Fusce vestibulum dui vitae lacus egestas vehicula. In eu mauris maximus, faucibus diam ut, varius felis. Donec interdum nisl eu nibh scelerisque molestie. Sed hendrerit consequat mauris, at consectetur erat ornare eget. Mauris ac mi tempor, pulvinar felis imperdiet, imperdiet dolor. Pellentesque vel enim purus. Sed aliquam ac tellus in viverra.

Aliquam erat volutpat. Vivamus mi velit, commodo et nibh quis, iaculis posuere ex. Fusce luctus iaculis pharetra. Vivamus porttitor hendrerit gravida. Sed in finibus justo. Sed ornare sed libero sed maximus. Sed in dui ut massa tincidunt maximus vitae porttitor metus. Nam finibus orci odio, at feugiat mauris sodales sed. Phasellus non volutpat risus. Maecenas vehicula venenatis sapien, et dapibus mi tempor a.

Donec congue facilisis quam at semper. Phasellus viverra aliquam est, nec dapibus neque ullamcorper et. Pellentesque in lobortis mauris. In purus mauris, sagittis congue interdum quis, bibendum et purus. Nam non cursus mi. Etiam in arcu in mauris aliquet lobortis id nec elit. Cras egestas velit a sodales tempus. Suspendisse sollicitudin, massa varius volutpat rhoncus, ex enim fringilla felis, in semper nulla felis et ligula. Nam elementum dui ut ante mattis, vitae dictum justo posuere. Etiam interdum non mauris nec sollicitudin. Fusce pellentesque lobortis lobortis. Pellentesque iaculis at neque id elementum. Sed vulputate nisi vel urna feugiat pharetra. Vivamus sit amet fringilla sapien. Etiam mi neque, molestie a tellus eget, tristique placerat risus.

Nam egestas mi vitae ipsum pellentesque, sed tempus ipsum facilisis. Pellentesque neque eros, consequat ut magna id, dapibus vulputate nisi. Donec a congue ex. Etiam suscipit velit vel magna suscipit accumsan. Nunc convallis quam ac facilisis convallis. Mauris at sem at dolor molestie hendrerit non in felis. Maecenas convallis ornare efficitur. Integer eget dignissim nibh. Quisque ultrices tempus pellentesque. Quisque non ornare sapien, non interdum arcu. Nullam volutpat laoreet elit, nec faucibus enim tincidunt vitae. Donec volutpat in mauris nec blandit. Integer fermentum, augue ut ultrices tristique, quam massa rhoncus metus, ac placerat nibh neque eu ipsum. Ut id sapien dolor.

Vestibulum sit amet ultrices libero. In dignissim et tortor vitae luctus. Maecenas bibendum risus ac lorem pellentesque, a pulvinar mauris dignissim. Aliquam et nisl quis neque finibus hendrerit quis ac tellus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi nec nisl felis. Sed cursus diam eu vulputate tincidunt. Integer elementum nibh lorem, at porta enim viverra in. Integer aliquam diam scelerisque lorem aliquet blandit.

Donec vitae lectus augue. Cras lorem velit, vulputate id maximus in, vehicula efficitur arcu. Praesent elementum lorem at luctus imperdiet. Etiam non sollicitudin mauris. Quisque posuere ultricies dui a semper. Donec rutrum leo a leo eleifend, et gravida eros imperdiet. Donec consectetur vitae dolor vel auctor. Cras pretium varius auctor. Donec nec nisi vitae dui sodales interdum. Cras vel viverra augue. Donec ornare ipsum diam, porta ultricies ante lobortis sed. Integer neque arcu, vestibulum ut tempus eu, aliquam eu justo. Morbi lacus erat, rutrum non lacus vitae, vestibulum efficitur orci. Vestibulum gravida eros at enim commodo cursus. Donec laoreet lobortis convallis.

Curabitur at scelerisque dolor, eget pulvinar neque. Praesent ultricies eu leo at vestibulum. Proin a eleifend orci. Donec elementum, enim nec vulputate tincidunt, augue ipsum molestie nibh, nec tincidunt est ex vel urna. Donec tellus nulla, ultrices pulvinar ullamcorper non, pulvinar sit amet dui. Proin at facilisis nunc. Nullam mollis est ut pellentesque ullamcorper. Aenean nisl felis, dignissim ut sollicitudin vel, rhoncus placerat odio. Nullam vehicula elementum lectus, sit amet auctor augue ullamcorper et. Nam luctus est odio, in semper eros commodo non. Vivamus eu erat eget erat congue posuere id vel nunc.

Sed nibh mi, pretium vel metus ut, lobortis tincidunt dolor. Etiam non scelerisque nisl. Nulla porta sapien odio, sed volutpat leo auctor ut. Nulla non elit ut massa porttitor ultrices ut at ipsum. Nulla nec massa mi. Aliquam gravida metus rutrum euismod pharetra. Suspendisse sit amet ornare justo. Donec pretium leo volutpat purus fringilla, a maximus nibh dignissim. Duis vitae mattis metus. Cras viverra molestie eros, a tincidunt erat interdum quis. Suspendisse a ultricies ipsum, tristique accumsan diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut ut ipsum vel eros elementum viverra cursus ac mauris.

Quisque eu egestas mauris. Donec pharetra tincidunt tincidunt. Fusce pharetra felis sit amet ligula posuere condimentum. Nam eros quam, tincidunt eget finibus ut, vulputate ut quam. In a feugiat urna, id semper tortor. Quisque vel ultrices turpis. Donec hendrerit nibh orci, ut fringilla lectus iaculis quis. Maecenas vitae justo vitae nunc suscipit pretium ac in nulla. Vivamus erat augue, accumsan eget libero eget, egestas facilisis ipsum. Etiam nunc tellus, cursus posuere ultrices quis, ullamcorper vitae dolor. Ut nisi ligula, convallis sit amet lorem sit amet, egestas mattis neque. Aenean nec ligula id lacus pretium volutpat ac ullamcorper arcu. Quisque tempus lobortis lacus id euismod. Vivamus quis interdum sem.

Donec varius vel felis ac congue. Cras vitae vulputate leo. Mauris consequat, ex eu vehicula ullamcorper, odio nisi porttitor tellus, non luctus felis massa vitae quam. Integer ullamcorper nisl non ornare porttitor. Vivamus et hendrerit metus, lacinia malesuada massa. Vivamus hendrerit tortor felis, et porta arcu pulvinar sed. Aliquam sollicitudin, ex non maximus laoreet, mauris ex dapibus elit, vitae blandit augue nulla eu eros. Donec vestibulum quis massa id semper. Suspendisse tempus volutpat metus, quis sodales sapien consectetur sit amet. Aenean vitae mi hendrerit, ultrices mi et, porttitor enim. Curabitur id enim in risus venenatis pellentesque. Curabitur fringilla dolor at vestibulum faucibus. Vivamus justo orci, convallis eu arcu nec, sollicitudin vestibulum est.

Duis cursus, lectus eget elementum ornare, neque ipsum fringilla risus, sit amet aliquet eros dui vel augue. Phasellus ultrices urna lorem, at interdum tellus gravida ut. Vivamus quis fringilla lectus. Mauris tempor enim vitae dui congue interdum. Fusce mauris mi, imperdiet sed bibendum sed, congue nec dui. Curabitur varius purus ac suscipit tincidunt. Etiam erat dolor, euismod a est et, auctor tempor elit. Fusce tincidunt sit amet mi vel consequat. Cras eleifend nisi a eros imperdiet, eu tempor urna aliquet. Sed in cursus diam, at pharetra ex. Phasellus urna neque, iaculis at euismod non, consectetur sit amet lorem. Fusce eget sem ipsum. Vestibulum quis tincidunt enim. Suspendisse venenatis velit lacus, vitae scelerisque nisl ultricies et.

Sed volutpat neque eget nisi mattis, eget bibendum est sollicitudin. Sed dictum aliquet nulla ut ornare. Cras a venenatis turpis. Ut et nisi felis. Nullam ultricies faucibus risus, tincidunt bibendum odio dapibus in. In vitae justo sit amet ante laoreet semper blandit nec orci. Donec rhoncus quis lacus a lacinia. Nam in odio commodo, ornare velit eget, suscipit justo. Etiam elit neque, ultricies vitae hendrerit sed, dictum vitae metus. Maecenas ultricies magna ac faucibus pretium. Sed semper leo id dapibus rhoncus. Pellentesque malesuada mauris nec vestibulum iaculis. Aenean vel elit sit amet ex ornare mollis vitae sed tortor. Ut tincidunt efficitur metus, tempus sodales nulla dignissim ac.

Ut ac eros quis enim lacinia ornare. Praesent volutpat lacus quis eros eleifend, at finibus massa fermentum. Donec quis lorem et augue egestas rutrum. Cras erat quam, mattis nec aliquet sollicitudin, elementum sit amet tellus. Suspendisse iaculis aliquam quam ac malesuada. Aenean mattis dolor ut tellus mollis convallis. Mauris magna sapien, pellentesque ut lacus id, placerat mollis sapien. Nullam vulputate suscipit ex, nec ultricies erat tempus quis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis suscipit sapien non augue ultricies, ut consectetur ante sodales. Morbi at rutrum arcu. Aliquam pharetra lacus tempus est convallis, mollis volutpat odio hendrerit.

Quisque quis felis sit amet velit aliquet rhoncus. Proin aliquet lobortis malesuada. Nunc sit amet viverra dolor, sit amet pulvinar dolor. Curabitur ut ultricies ligula. Nulla facilisi. Phasellus viverra dui mauris, ac luctus neque pretium quis. Pellentesque sit amet justo eget lorem semper eleifend.

Nulla ac venenatis justo. Duis hendrerit, nulla in faucibus mollis, erat risus dignissim lorem, id ullamcorper elit est non ex. Nulla facilisi. Vivamus tristique arcu libero, vel scelerisque ligula vehicula at. Sed ex dui, facilisis et laoreet nec, ornare at tortor. Donec varius vel felis at ultrices. Vivamus mollis justo eget ante semper egestas. Integer eget sagittis est. Praesent finibus ante sit amet pellentesque bibendum. Aliquam posuere congue nisi a faucibus. Maecenas sit amet elit ac urna mattis blandit sit amet molestie mauris. Donec vestibulum lobortis dignissim. Phasellus efficitur sodales mi, vitae ornare elit.

Nulla vestibulum semper sapien, non consequat erat gravida quis. Nulla consequat varius ex, eget consequat metus luctus eget. Pellentesque maximus id neque vitae euismod. Nullam et laoreet erat. Proin mi felis, pulvinar ut interdum a, mattis et ante. Ut ut ante a urna ornare fringilla. Nulla facilisi. Praesent a quam et elit mollis venenatis. Etiam quis diam ante. Nullam quis sem eu nunc semper blandit id non ipsum.

Etiam et magna ut lacus congue vehicula. Ut nec arcu augue. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin scelerisque tincidunt lectus quis blandit. Praesent fermentum dolor at congue congue. Vivamus pharetra libero imperdiet porta tristique. Suspendisse ut nisl malesuada, consectetur nibh vitae, pretium ligula. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed pharetra elit non metus pellentesque, sit amet iaculis erat finibus. Praesent nec mattis enim. Aliquam eu arcu eu nibh malesuada viverra. Cras tortor massa, sagittis eget mollis in, tincidunt ut dolor. In ultrices venenatis pellentesque. Pellentesque eu tellus in nisi cursus finibus ac suscipit ex. Vivamus finibus, ex malesuada venenatis hendrerit, orci felis interdum nulla, in dictum libero dolor sed ex.

Mauris pretium vestibulum eros, a viverra neque varius id. Phasellus imperdiet diam quis dui varius faucibus. Nullam justo mauris, luctus ut diam sit amet, varius rhoncus libero. Aenean felis felis, porttitor iaculis tempus a, ullamcorper eget felis. Integer laoreet molestie massa, tincidunt cursus orci commodo quis. Aliquam erat volutpat. Praesent euismod ex ante, eu sodales sem fringilla a. Phasellus vitae nunc lectus. Phasellus sodales quis enim at molestie.

Vivamus dignissim enim at ornare tristique. Nulla a magna id purus cursus pellentesque. Aliquam pellentesque egestas vulputate. Nulla id neque metus. Nullam eget nisl sagittis, lacinia quam non, efficitur neque. Suspendisse potenti. Donec bibendum varius ex sit amet tempus. Nam at pellentesque diam, et fermentum metus. Donec vel cursus massa.

Fusce imperdiet est ac tortor facilisis, fringilla blandit tortor consequat. Vivamus pellentesque nunc vel neque placerat laoreet. Nunc euismod semper ligula, a auctor nibh imperdiet eu. Praesent a pretium mi. Morbi eget arcu at ex vulputate gravida. Duis facilisis tincidunt metus, eu ullamcorper turpis vehicula sed. Aenean a tempus velit. Phasellus accumsan metus non risus fringilla laoreet. Integer id orci urna. Vestibulum ac eleifend ante. Ut vel malesuada leo. Nullam libero nisi, finibus vitae orci non, pretium sagittis tellus. Mauris eleifend tempor porta.

Suspendisse vitae pulvinar lacus. Nullam tempus, magna quis hendrerit tristique, dui augue fermentum dui, in accumsan augue ex vel nulla. Proin ut tincidunt ante, vitae faucibus tellus. Duis id scelerisque nisi. Nam libero lectus, dignissim at neque sed, pretium vestibulum lectus. Duis tempus augue ac nisl dapibus rutrum. Donec in nisi ante. Vestibulum quis odio fringilla, euismod nulla et, accumsan ex. Etiam molestie molestie augue, ac varius orci. In sollicitudin lacus vitae felis tempor dapibus. Vestibulum vestibulum erat ex, accumsan dictum lacus venenatis vitae. Etiam vestibulum imperdiet sapien et malesuada. Suspendisse ullamcorper leo vel lorem faucibus, sed pretium nisi molestie. Nullam vel ipsum vitae tortor porttitor egestas. Etiam luctus sagittis ligula nec consectetur.

Integer et nunc dui. Integer malesuada tempus odio vitae blandit. Nullam sit amet lacus a nibh facilisis ultricies a sed ex. Sed commodo vel metus sagittis fermentum. Nam mauris sem, rutrum in diam nec, hendrerit scelerisque dui. Quisque at commodo augue. Donec viverra neque non eros fringilla, vitae accumsan sem interdum. Ut congue tincidunt nibh, nec laoreet magna ullamcorper in. In justo mi, lacinia id tellus vel, varius dignissim tortor. Praesent consectetur, lacus interdum rhoncus viverra, purus nibh scelerisque purus, at cursus justo lorem eget justo. Phasellus posuere tortor eu neque maximus scelerisque. Nunc maximus, nunc accumsan placerat faucibus, mi turpis interdum urna, vitae viverra libero ante vitae justo. Nunc varius at leo sed pharetra. Vestibulum egestas egestas suscipit. Maecenas quis accumsan urna.

Suspendisse id semper orci. Sed erat ante, lacinia eu nisl eget, blandit dignissim dolor. Nulla tempor eros ut nisi vehicula tempus. Aliquam porta ullamcorper tortor a auctor. Curabitur a suscipit mi. Donec ut mattis est. Donec ultrices tortor vitae pulvinar consectetur. Aliquam egestas molestie nulla, efficitur lobortis justo rutrum ac. Maecenas pulvinar quis magna at elementum. Praesent sed suscipit sapien, ac tempus ex. Duis vel tortor luctus libero fermentum tempus. Quisque fermentum dictum elementum. Donec non nisl vehicula orci consequat interdum. Cras pretium enim sit amet tellus venenatis placerat. Proin venenatis vulputate purus. Fusce lectus diam, vulputate eget blandit quis, consectetur ut metus.

Aenean non lobortis diam. Phasellus blandit et dui sit amet ornare. Quisque tellus augue, aliquet eget nisl vel, tempus laoreet mi. Donec fringilla risus leo, sed faucibus ante eleifend id. Vivamus condimentum, lorem elementum lobortis mollis, metus risus suscipit mauris, ac condimentum neque mauris quis magna. Phasellus commodo, nisl cursus dignissim vehicula, ex arcu feugiat turpis, id suscipit quam nisi at mauris. Etiam euismod metus et nunc accumsan, sit amet sodales justo placerat. Vestibulum vel malesuada lorem. Maecenas dapibus, velit vitae ultrices luctus, massa nisl pharetra leo, et porttitor dolor magna nec nisi.

Etiam pulvinar dolor augue, nec mattis sapien maximus at. In tincidunt consequat dolor. In faucibus dui vel enim semper tempor. Mauris enim enim, placerat a justo et, maximus scelerisque mi. Morbi ut commodo ante, eget sollicitudin urna. Integer venenatis, dui ac ornare sodales, ex tellus tincidunt metus, non molestie urna neque eget ipsum. Duis tincidunt fringilla pellentesque. Aenean in libero et ex rutrum sodales. In in ultricies dolor, in commodo massa. Sed mattis libero eget aliquam iaculis. Donec at odio orci. Nullam nunc tortor, dictum quis risus nec, cursus malesuada nunc. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer mattis eros ac ex tincidunt congue.

Morbi eu tincidunt nisl. Fusce facilisis vel nunc sit amet commodo. Duis tincidunt arcu sed convallis aliquet. Nullam fringilla purus tincidunt neque euismod, ac dictum sem elementum. Vivamus eget libero ex. Nulla at pretium metus. Duis tincidunt nulla ex, vel egestas ipsum iaculis non. Donec ornare mollis dapibus.

Phasellus ac nibh et dolor finibus consequat blandit a metus. Nullam semper pulvinar enim, in accumsan ipsum facilisis nec. Sed ultricies suscipit odio, quis placerat lectus gravida nec. Integer eu sem vitae sapien ullamcorper congue eget posuere nisl. Sed vitae velit enim. Ut ut mi varius, maximus velit ac, tristique enim. Nulla euismod, lorem vel tempor vestibulum, augue tortor sodales lacus, id gravida felis felis nec lacus. Cras lacinia pretium augue sed tincidunt. Cras dignissim a nisi at tristique. Etiam quis ipsum convallis, volutpat sapien auctor, maximus ante. Donec euismod eleifend convallis. Proin dapibus leo sed erat consequat varius. Aliquam lacus dolor, mattis a mi id, vestibulum maximus ex. Donec ac hendrerit est. Vestibulum vel arcu fringilla, lobortis dolor eu, vehicula urna.

Pellentesque suscipit aliquet leo, aliquet posuere velit facilisis vitae. Morbi ultricies at tortor mattis fringilla. Aliquam at leo ullamcorper, fermentum ante ut, volutpat lorem. Quisque imperdiet vulputate mi nec pharetra. Donec condimentum eu enim vel pharetra. Aenean sit amet libero non sem placerat dignissim. Suspendisse ac semper odio, id pellentesque dui. Suspendisse mattis nisl elit, ut rhoncus libero suscipit vehicula. In non augue nisi. Nulla facilisi.

Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec ligula sapien, cursus eu sapien ut, aliquet varius quam. Integer auctor leo vitae odio auctor semper. In mattis sed neque non bibendum. Vestibulum eget sagittis nibh. Nullam eu rutrum lorem. Pellentesque mollis, leo et hendrerit ultricies, risus leo maximus urna, sed placerat elit augue a magna. Nam pretium purus elit, a cursus metus pulvinar fringilla. Mauris id scelerisque diam. Maecenas in laoreet arcu, non porttitor nibh. Sed in volutpat leo. Sed at tellus laoreet, pulvinar nunc posuere, rhoncus nibh. Nullam ornare tempor diam, at lacinia mauris rhoncus vehicula. Vivamus nulla odio, vulputate at mauris vitae, lacinia sagittis magna. Nulla non volutpat massa, in consectetur nulla.

Maecenas at eros tincidunt, finibus dolor non, convallis lacus. Phasellus sit amet auctor felis, nec mollis nunc. Fusce feugiat lacus a ligula auctor semper. Nunc consectetur leo vel blandit luctus. Proin consectetur justo eget mi fringilla suscipit. In nec tempus eros, nec imperdiet libero. Nam nec sollicitudin lorem. Nullam eget diam eu risus venenatis posuere. Quisque sit amet mattis erat. Proin porta lacinia lectus, ut luctus leo. Phasellus nec ipsum efficitur, vestibulum urna et, blandit lorem. Aliquam massa nunc, vulputate eget aliquet in, pharetra eget erat. Curabitur ullamcorper sodales iaculis.

Nullam varius erat vitae ultricies dapibus. Cras ligula nisl, faucibus commodo dapibus eu, scelerisque et tortor. Suspendisse ornare lorem ac mauris congue semper. Aliquam id justo aliquam, dictum nisi vitae, sagittis metus. Vivamus diam justo, cursus vitae suscipit vitae, maximus et nibh. Cras ullamcorper mi eu augue hendrerit posuere. Pellentesque posuere accumsan libero, at lacinia erat ullamcorper id. Aliquam eu magna dui. Sed ultricies neque eget mattis imperdiet. In facilisis tempus lacus eu maximus. Nunc pulvinar fermentum scelerisque. Maecenas sit amet nisi non nisl auctor lobortis nec ut lorem. Donec sagittis, nisi id condimentum maximus, ex orci malesuada orci, et laoreet nisi velit tincidunt neque.

Morbi non dapibus eros, vel pulvinar tellus. Curabitur ut consectetur sem, non fermentum felis. Praesent ut mauris vitae nisi vestibulum vulputate at sed leo. Vivamus elementum odio id ultrices pellentesque. Sed vitae justo fringilla, imperdiet elit ac, cursus neque. Quisque iaculis egestas dictum. Quisque pretium metus ac imperdiet sodales. In vestibulum mauris mauris, malesuada elementum sem maximus non. Donec congue ipsum tellus, laoreet luctus libero mollis eget.

Phasellus condimentum urna vitae mattis tincidunt. Aenean orci mi, condimentum ut semper vitae, sodales eget nunc. Morbi vulputate, justo et efficitur blandit, nisi mi convallis arcu, quis dictum nisl nisi nec tortor. Sed faucibus eros id ipsum sollicitudin, vel sollicitudin turpis facilisis. Curabitur eu porta elit. Pellentesque scelerisque tristique diam id condimentum. Quisque nec aliquam ipsum. Etiam tincidunt fermentum libero sit amet consectetur. In maximus, erat vel pretium vestibulum, eros nulla varius quam, non tristique arcu justo rutrum lacus.

Nulla consectetur nec tellus vitae porttitor. Sed fringilla ipsum et aliquam fermentum. Fusce metus ante, semper ac magna nec, suscipit ullamcorper diam. Duis vitae nulla sed neque imperdiet viverra. Ut auctor elit vitae felis fringilla, eu efficitur sapien sodales. Maecenas auctor pulvinar nibh, sed volutpat nisi volutpat vulputate. Duis quam tortor, molestie eu arcu non, lobortis elementum ipsum. Cras in volutpat risus. Proin consequat justo at dapibus ultricies. Curabitur ac arcu eu nisl ornare ullamcorper. Phasellus ut tempus mauris, nec hendrerit ipsum.

Curabitur lobortis felis eget lorem pulvinar pellentesque. Donec vel posuere tortor, vel eleifend dolor. Nam condimentum urna diam, in eleifend odio sodales et. Ut nec tellus elementum, vestibulum ex ut, vestibulum magna. Nulla rutrum, nulla id porta rutrum, purus orci ullamcorper sapien, eu varius arcu ipsum sed elit. Curabitur a ex non ante tincidunt lacinia nec vitae elit. Etiam facilisis felis dui, ut vehicula dolor malesuada id. Cras lobortis lobortis orci, ut placerat velit porttitor vel. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus euismod egestas eros et ullamcorper. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus nibh ex, finibus vel maximus sed, aliquet pretium risus. Etiam convallis, sem in sagittis lacinia, ligula augue blandit felis, faucibus lacinia mi ligula quis dolor.

Sed fermentum lacinia arcu quis pretium. Aliquam nec odio a diam blandit cursus. Fusce fermentum libero elit, a tristique dolor mattis tempus. Donec mattis nisi eu accumsan facilisis. Duis ac pharetra augue. Vestibulum a nisl tellus. Integer sollicitudin elementum diam, sed scelerisque massa viverra suscipit. Proin semper justo quam, vel ultrices tellus bibendum id.

Aliquam fermentum pretium ante id placerat. Etiam ultricies leo orci, et dignissim nunc varius nec. Ut elementum facilisis sagittis. Nunc rutrum tortor vitae leo vehicula congue. Suspendisse est elit, ullamcorper id tellus sed, scelerisque rhoncus magna. Vivamus ornare ut mi et hendrerit. Nullam mollis luctus mauris, quis commodo lacus. Vestibulum et nunc ipsum. Vestibulum ultrices, est nec tempus consectetur, leo leo scelerisque purus, id fermentum orci libero sed nibh. Duis at tincidunt lorem. Praesent tempus felis id tristique feugiat. Mauris sit amet tincidunt odio, pretium iaculis augue. Duis et sapien sed nulla porta bibendum ac non ipsum. Sed convallis purus a massa faucibus, eget euismod libero eleifend. Duis ut ullamcorper tellus, et dignissim eros. Curabitur congue, metus tempus tincidunt molestie, lectus lacus suscipit orci, in placerat arcu dolor nec erat.

Nulla non suscipit diam. Praesent eu ligula a risus luctus vestibulum. In sollicitudin fermentum mauris, bibendum viverra urna eleifend non. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a rhoncus lectus. In non lacus dignissim, feugiat leo at, tempor elit. Vestibulum sagittis elementum lacus, at maximus justo hendrerit ut. Nunc suscipit hendrerit finibus. Nullam tempus, erat non sollicitudin efficitur, urna metus varius lorem, in consequat purus tortor vitae quam.

Nulla lacinia leo turpis, nec accumsan nisi tincidunt eu. Ut fermentum pulvinar nibh vitae aliquet. Fusce lacinia urna sit amet faucibus luctus. Sed placerat felis id est laoreet, sed finibus enim porta. Nullam nisl felis, bibendum eget semper non, congue et nulla. Sed malesuada non odio ut maximus. In nec sapien vel ligula blandit tincidunt. Aenean ut placerat mi, a mattis ex. Pellentesque a rutrum nulla.

Etiam mi ex, semper sit amet augue eu, pulvinar fermentum neque. Praesent arcu felis, mollis a leo eget, ullamcorper volutpat nulla. Vestibulum eu elementum leo, quis congue sem. Duis dictum, mauris non pellentesque eleifend, lectus urna convallis lectus, at volutpat felis mi sit amet est. In quis ullamcorper justo. In elit risus, pulvinar nec pulvinar quis, blandit a libero. Maecenas nulla massa, pharetra in magna sed, tempor luctus nibh. Aliquam volutpat iaculis posuere. Phasellus ultrices sed neque sed consequat. In in ex id magna dapibus tempor. Integer ultrices ultricies sodales. Vestibulum sodales blandit turpis. Morbi rutrum sem nec ipsum porttitor, non hendrerit arcu fringilla. Pellentesque ut ullamcorper risus. Nunc pellentesque quis justo non semper.

Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce fringilla quam sed leo auctor rutrum. Suspendisse ultricies metus laoreet lorem laoreet, id viverra risus tempor. Ut id rhoncus neque. In arcu mauris, dapibus eu lacus nec, eleifend suscipit augue. Sed auctor ac tellus id sagittis. Pellentesque a congue nibh. Praesent at vulputate eros. Nam tellus neque, lobortis nec dignissim sit amet, ullamcorper nec neque. Maecenas a odio felis. In convallis libero quis augue mattis, sit amet vestibulum tortor mattis. Donec vestibulum accumsan velit.

Duis faucibus gravida urna, nec scelerisque leo sodales nec. Nulla rutrum, justo eu commodo finibus, nisl turpis aliquet est, dapibus euismod nisi neque vel ante. Vestibulum ultricies eget mi dignissim viverra. Cras volutpat metus non accumsan feugiat. Nunc iaculis at est a condimentum. Nullam non magna sed libero rutrum hendrerit. Nullam varius dolor quis nulla consequat eleifend. Fusce ex ante, dapibus id ullamcorper non, auctor et felis. Aliquam vitae mauris a tellus convallis tempor. Nullam porta elit in viverra accumsan. Phasellus ipsum mauris, pretium ornare libero ac, porta commodo lectus. In enim lectus, pulvinar quis vulputate eu, venenatis volutpat mauris. Donec urna dolor, fringilla vel augue quis, sollicitudin volutpat lectus. Praesent accumsan hendrerit turpis nec volutpat. Nam magna diam, accumsan non pellentesque sit amet, vehicula non felis. Vivamus vitae fringilla urna.

Vestibulum faucibus mi eros, sed malesuada quam pharetra sit amet. Suspendisse sit amet justo laoreet, faucibus ante et, tincidunt lectus. Nullam vitae rhoncus metus. Etiam ultrices malesuada euismod. Praesent elementum nunc vitae neque fringilla, quis aliquam orci dictum. Nulla eu neque vestibulum risus viverra scelerisque. Praesent venenatis felis eget turpis iaculis, eu elementum mi pulvinar. Pellentesque a suscipit nisl.

Suspendisse eu nisi arcu. Maecenas dui urna, malesuada malesuada arcu vel, feugiat consectetur neque. Vivamus ut massa sit amet quam sodales ultricies scelerisque nec odio. Maecenas et nibh quis felis ullamcorper fringilla nec at odio. Nunc volutpat arcu magna, at porta diam lacinia vitae. Proin vestibulum finibus velit eu euismod. Quisque magna enim, consequat at leo eu, pretium volutpat ipsum. Proin ligula sem, tempus id pretium semper, gravida non ipsum.

Nulla tempor purus ut lectus ultricies, efficitur lobortis turpis iaculis. Maecenas placerat porttitor mauris, et accumsan dolor elementum ut. Sed ut semper urna. Quisque venenatis dolor scelerisque ullamcorper tristique. Sed et justo sed dui vestibulum tristique. Morbi nec ultrices massa. Aliquam dictum tristique sapien, eget ultricies mauris interdum sed. Aenean a ullamcorper quam. Nulla facilisi.

In finibus tortor a lorem commodo, sit amet cursus nulla sollicitudin. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris ut finibus lectus. Pellentesque eleifend massa metus, id scelerisque erat accumsan eget. Praesent faucibus nulla mauris, non placerat nunc gravida et. Nam consectetur rhoncus metus id interdum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

Sed vestibulum iaculis ante, ac vehicula lectus. Proin volutpat, dolor non mollis viverra, sapien ex mattis risus, dictum maximus orci nisi ut erat. Nam at ultrices nunc. Vestibulum sollicitudin, odio in scelerisque accumsan, justo dolor consequat arcu, nec fermentum lacus massa et lectus. Donec ac erat leo. Mauris viverra tempor orci at faucibus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;

Sed elementum condimentum dui nec egestas. Suspendisse consequat metus congue augue feugiat, vitae auctor leo consequat. Nunc hendrerit erat vitae pharetra tincidunt. Nam non sagittis eros. Quisque tincidunt erat porttitor fermentum ullamcorper. Sed lacus justo, hendrerit sagittis lacinia condimentum, facilisis non tellus. Vestibulum posuere, nisl non aliquet tristique, est massa tincidunt ante, at feugiat sem augue a lectus. Etiam auctor magna nibh, et ultrices nisl ultricies tincidunt. Nullam facilisis fringilla lacus vitae dignissim. In posuere gravida libero ac bibendum. Sed sit amet fringilla erat.

Donec posuere euismod enim, at consectetur lacus finibus nec. Nunc tempus ligula ut velit sagittis, eu condimentum risus lacinia. Cras maximus nulla eros, a varius libero dictum eget. Sed pulvinar tristique maximus. Maecenas eleifend pharetra felis sed malesuada. Nulla pharetra, nisl in egestas pretium, metus sem dignissim lorem, eget viverra mauris ex ut eros. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam consequat tristique tortor ut laoreet. Pellentesque sit amet turpis iaculis, elementum lorem non, faucibus neque. Integer pretium volutpat elit, rhoncus vulputate nisi imperdiet in. Curabitur efficitur augue ut varius sagittis. Aliquam erat volutpat. Duis at neque a lectus placerat porta. Ut vel pretium mi, eget malesuada tortor. Ut fringilla eleifend imperdiet.

Suspendisse egestas suscipit arcu, sed congue metus pretium ac. Integer aliquet, augue id pulvinar ornare, ex ligula cursus enim, a fermentum eros augue at nunc. In quis nunc dolor. Morbi sed convallis diam. Integer rutrum justo quam, non fermentum leo facilisis in. Quisque iaculis, quam a fermentum consectetur, turpis nibh feugiat risus, ac dapibus justo felis sed neque. Maecenas bibendum mi nunc, a dapibus purus porttitor a. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent ut auctor metus. Morbi sed risus lobortis, vestibulum nisl et, lacinia nibh. Mauris dignissim vulputate urna, quis porttitor diam accumsan quis. Duis id tellus volutpat, venenatis metus vel, dapibus purus.

Pellentesque ipsum dolor, faucibus ac vulputate eu, tempus nec eros. Nulla et imperdiet quam, ut pretium elit. Donec eu egestas lectus. Quisque vel turpis ut nulla consequat congue. Sed sed gravida erat, vel laoreet risus. Sed laoreet neque sit amet molestie ultrices. Donec eget lacus fermentum, pretium lacus vel, posuere elit. Quisque euismod egestas lectus. Nullam tincidunt interdum mauris, in ornare nisl venenatis nec.

Donec eu ex lorem. Proin tincidunt semper auctor. In sit amet euismod augue. Aenean luctus ipsum quis accumsan ullamcorper. Duis eu metus interdum, imperdiet justo ut, pharetra felis. Proin elementum feugiat nulla, sed eleifend ipsum convallis eget. Aliquam erat volutpat. Morbi in est imperdiet, vulputate ligula et, finibus orci. In tristique risus arcu, sit amet interdum mi aliquet sed. Donec tempus dictum interdum. Aliquam tortor turpis, varius ac consectetur at, placerat vitae urna.

Pellentesque mollis consectetur augue sit amet vestibulum. Praesent pellentesque vel erat a euismod. Donec quis leo turpis. Aliquam eleifend vel dolor ac molestie. Phasellus eu rhoncus nulla. Proin tempor lorem eu nisl sollicitudin rhoncus. Pellentesque eget luctus enim. Suspendisse elementum rutrum porta. Aenean iaculis, nulla sed sollicitudin sagittis, libero libero consectetur sapien, finibus congue arcu leo in urna.

Etiam auctor, sem quis tempus hendrerit, lacus nisi pharetra leo, at euismod metus risus nec lacus. Vivamus eu velit varius, feugiat tellus nec, venenatis arcu. Phasellus eleifend arcu tortor, et condimentum diam hendrerit ac. Fusce ac malesuada elit. Donec scelerisque urna eget elit sodales posuere. Vestibulum eu auctor est, porta cursus mauris. Mauris eu lectus at diam malesuada sodales. Integer sed sapien varius, lacinia enim sed, sagittis nulla. Nam leo tortor, tincidunt vel pharetra sit amet, mollis quis odio. Nulla facilisi.

Curabitur placerat sodales lorem et auctor. Sed luctus leo sit amet elit facilisis scelerisque. Proin bibendum ipsum arcu, eu commodo neque gravida eget. Nulla a gravida purus. Vivamus non lectus aliquam, fringilla mi sed, dignissim est. Vestibulum tristique dignissim est nec gravida. Quisque faucibus a mi at aliquet. Phasellus tempor convallis quam vitae feugiat. Curabitur fermentum eros mi, et dapibus risus tincidunt sit amet. Nulla accumsan bibendum felis ut fermentum. Sed aliquam et purus et pulvinar. In eget velit ac nibh egestas vulputate sed ut metus. Aliquam sapien turpis, blandit in orci sit amet, maximus accumsan nisl. Mauris imperdiet vitae libero ut ultrices. Duis tristique velit in nibh gravida efficitur at at felis. Vivamus porttitor tincidunt felis ut aliquet.

Ut eu dapibus nibh, vel fringilla nisl. Sed posuere sagittis augue non finibus. Pellentesque iaculis consequat eros, maximus dignissim libero malesuada nec. Duis pulvinar nisi et quam pulvinar consequat. Proin euismod euismod ante, eu maximus quam aliquam id. Quisque at lacus purus. Nullam vehicula erat auctor lorem bibendum, nec vehicula dui feugiat. Nam ullamcorper egestas aliquam. Ut ex erat, pellentesque sit amet pharetra eget, ultricies eu ipsum. Sed quis dolor aliquet, ultrices urna eget, lacinia leo. Aliquam mollis sodales nisl, id imperdiet ligula. Maecenas ex risus, viverra vitae hendrerit rhoncus, rhoncus eu ipsum.

Praesent eu blandit ipsum. Suspendisse sed cursus lacus. Vestibulum eget odio tincidunt, convallis metus sit amet, condimentum purus. Sed eget sollicitudin est. Aliquam lobortis consectetur odio pellentesque consequat. Donec tristique, est sed ultricies dictum, ipsum urna ullamcorper metus, id aliquet dui lacus sit amet justo. Donec non tincidunt ex. Integer lacinia leo venenatis, mattis ante a, lobortis nibh. Etiam rutrum, ante a gravida posuere, elit felis vehicula eros, vitae ultrices lectus massa ut leo.

Sed cursus mattis ligula. Aliquam nisi velit, bibendum vitae neque eu, iaculis mattis nisl. Praesent ac elit sed odio mollis sodales. Nulla non porta tortor. Fusce pulvinar volutpat felis in hendrerit. Phasellus eu finibus erat. Suspendisse et orci ut orci mattis placerat nec cursus risus. Etiam tincidunt libero vitae ligula efficitur laoreet. Nam vel ornare sapien, a pharetra arcu. Quisque commodo risus non tortor scelerisque tincidunt. Vestibulum vel neque imperdiet, porta mi vitae, varius orci. Pellentesque eget diam imperdiet, iaculis quam ac, semper felis. Nunc congue tempor faucibus. In hac habitasse platea dictumst. Pellentesque vitae aliquet ex.

Aenean fringilla metus vel elit accumsan, sit amet porta magna pulvinar. Suspendisse laoreet posuere dolor, nec malesuada metus iaculis non. Aenean lobortis nulla in odio semper congue. Nunc vulputate dictum nisi, quis pulvinar eros rhoncus sed. Vivamus ac fringilla quam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla quis iaculis nulla. Curabitur dolor purus, vehicula sed libero in, pharetra laoreet tortor. Curabitur vel lacus quis metus lacinia lobortis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam consequat justo tortor, sit amet tempor diam feugiat sed. Interdum et malesuada fames ac ante ipsum primis in faucibus.

Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi vel turpis massa. Integer semper enim eget libero lobortis, non convallis neque vehicula. Nam laoreet quam commodo ex luctus, eget gravida quam cursus. Quisque ac porttitor libero, a lobortis justo. Ut tristique rhoncus odio et malesuada. Morbi finibus leo urna, in tincidunt leo suscipit pharetra. Praesent ligula augue, semper eget aliquet non, consequat dapibus diam. Praesent in luctus tortor. Quisque dapibus tristique sapien non pulvinar. Nam consectetur vitae dolor at aliquet. Sed non massa eleifend, ornare arcu vitae, scelerisque urna. Fusce dignissim ligula quis dui pharetra, vel blandit nibh consequat.

Vivamus varius posuere neque quis molestie. Donec eget vehicula nibh, id mattis odio. Praesent nec ipsum ipsum. Praesent metus ipsum, iaculis et nibh vel, varius tincidunt leo. Integer ut posuere dui. Donec consequat, velit in consectetur ultricies, elit nisi mattis lorem, ut euismod massa quam ut neque. Integer sagittis posuere mi, quis euismod massa consectetur et. Morbi suscipit efficitur eros, non dictum metus tempus in. In eget nisi commodo, tincidunt sapien non, placerat tortor. Vestibulum iaculis, arcu in gravida vestibulum, libero eros vulputate est, et feugiat lacus ex sit amet metus. Donec rhoncus commodo rhoncus. Mauris rutrum libero sit amet mollis dignissim.

Pellentesque sollicitudin eleifend fringilla. Phasellus in odio convallis ligula convallis varius. Quisque eu lorem in lectus feugiat vestibulum. Donec non turpis id nibh accumsan egestas id id nisl. In hendrerit ultricies fermentum. Phasellus nec ante lobortis magna sollicitudin tincidunt ut nec orci. Phasellus imperdiet quam ac turpis tincidunt, ac pharetra lectus condimentum. Vestibulum porttitor, nibh ut pharetra porta, quam justo efficitur diam, at placerat ex justo at dui. Nam at laoreet orci, sit amet cursus neque. Suspendisse augue velit, malesuada hendrerit orci et, dignissim rutrum velit.

Cras imperdiet maximus justo, a accumsan ex posuere in. Vestibulum molestie velit et aliquam elementum. Cras vitae facilisis tortor, ut malesuada dui. Cras placerat augue condimentum convallis vestibulum. Vivamus lectus quam, venenatis a dui pulvinar, laoreet tincidunt justo. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis rhoncus iaculis arcu, et auctor leo. Suspendisse at dui odio. Quisque mollis nisi ut sapien dignissim, non faucibus sem pharetra.

Suspendisse feugiat ex porttitor, ornare magna vitae, molestie est. Praesent rutrum pretium nisi vel gravida. Nunc euismod tempor nisi, ac cursus leo dignissim vel. Nullam lacinia mollis quam sit amet consequat. Nunc a mi aliquam, cursus velit at, varius risus. Duis commodo metus ac ornare facilisis. Sed sapien odio, maximus vitae nisi a, viverra laoreet arcu. Praesent varius vestibulum augue non vulputate. Proin ornare dolor in scelerisque auctor.

Nunc eu tincidunt diam. Fusce sollicitudin, justo placerat venenatis hendrerit, urna nisl rutrum nibh, eu scelerisque erat leo ac risus. Maecenas pretium euismod egestas. Morbi luctus pellentesque euismod. Mauris blandit, nunc eu facilisis tristique, sem nunc ullamcorper nulla, et viverra metus est eu erat. Nam eget dolor cursus, condimentum lacus sit amet, finibus tortor. Mauris ultricies finibus magna sed pharetra. Sed pellentesque varius arcu, posuere gravida turpis interdum sit amet. Quisque varius purus sed diam porta pharetra. In lobortis at neque ac lacinia. Sed scelerisque, justo at molestie maximus, leo metus commodo enim, at pulvinar tortor libero eu elit. Vivamus accumsan, leo nec commodo congue, lacus turpis convallis libero, eu feugiat elit sapien vel ex. Aenean sodales iaculis tortor eget congue.

Phasellus mattis vehicula posuere. Curabitur vehicula viverra laoreet. Cras mollis efficitur est, ac posuere metus semper et. Donec id orci vitae tellus sagittis aliquam. Mauris in odio ante. Morbi ultrices suscipit tortor, nec pharetra dui iaculis et. Phasellus lobortis ultrices justo vel condimentum. Sed vehicula nunc cursus tellus posuere euismod.

Nunc at tortor finibus, viverra leo vel, condimentum magna. Nunc posuere nibh sit amet elit lacinia, sed varius mauris venenatis. Etiam eu cursus lacus. Fusce fringilla tristique laoreet. Donec et urna pellentesque, aliquam tellus nec, porta nibh. Etiam lobortis sagittis sodales. In semper tempor turpis, at scelerisque ipsum venenatis et. Mauris rhoncus ligula id pharetra varius. Quisque ultrices vehicula felis, ut fermentum risus malesuada in.

Aliquam at nulla commodo, lobortis sapien eu, consectetur justo. Curabitur eget convallis nibh. Vestibulum rhoncus velit tellus, tempus volutpat risus feugiat sit amet. Nullam viverra ultricies nibh, ut congue felis tincidunt at. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec urna est, volutpat quis mi at, dignissim consectetur erat. Donec non purus bibendum, rhoncus nunc et, luctus mauris.

Vestibulum congue justo est, fringilla facilisis enim interdum eu. Aenean sed lacus lacinia, venenatis turpis ac, ullamcorper ligula. Ut quis libero et diam facilisis tristique. Nam scelerisque sem nec augue consectetur elementum a sit amet lorem. Duis posuere finibus eros, ut semper diam tempor eu. Phasellus blandit arcu enim, vel volutpat nunc pharetra id. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Interdum et malesuada fames ac ante ipsum primis in faucibus. Praesent iaculis volutpat nibh, et eleifend eros aliquam eget. Duis porttitor purus sit amet massa blandit, a condimentum sem volutpat. Proin ut purus mattis, dictum sem eu, ultrices lorem. Maecenas in ex ut enim congue convallis. Donec vel tempor lorem. Suspendisse sem nunc, mollis nec arcu nec, volutpat dictum justo. Ut sed volutpat arcu. Nullam finibus, leo ornare porttitor pulvinar, augue erat congue erat, eu suscipit nisi nisi quis dui. Morbi malesuada porttitor fermentum. Fusce orci leo, molestie sed dapibus at, efficitur id est.

Aenean nec nunc urna. Vivamus feugiat congue augue sed fermentum. Sed lobortis a ex non rutrum. Praesent eu eros augue. Quisque tristique turpis elit, non finibus est tincidunt sed. Donec et magna gravida, molestie odio id, aliquam diam. Proin venenatis sem sit amet libero semper auctor. Morbi mattis lobortis odio ut accumsan. Quisque nec iaculis ante, et porta justo.

Donec bibendum sem quis tellus mattis fringilla. Morbi pellentesque augue ligula, ut ultricies odio condimentum ac. Mauris mollis lobortis libero, quis aliquam turpis lacinia non. Quisque rhoncus facilisis felis, in fringilla nunc sagittis nec. Proin posuere purus vel purus rhoncus sollicitudin. Morbi eget sollicitudin ex, vitae porttitor lacus. Aliquam tortor tortor, pharetra et lacus ac, placerat dapibus sapien. Suspendisse eget metus ac neque pretium varius et sed leo. Quisque a erat vel tortor aliquet rutrum ut vel arcu. Nam bibendum lectus et ipsum congue, id facilisis ipsum pellentesque. Donec ut eleifend felis. Nunc lobortis tortor felis, vitae lobortis orci ornare at. Nulla facilisi. Morbi eu dictum nulla. Integer finibus ligula vel magna gravida, vel pharetra augue dapibus.

Ut ligula lectus, fermentum a ornare et, tincidunt nec mi. Proin tellus ligula, faucibus a sem a, lacinia faucibus tortor. Praesent aliquam metus vel ligula efficitur varius. Mauris velit metus, porttitor ut erat non, fermentum aliquam tellus. Praesent aliquam sit amet nulla nec pulvinar. Fusce vulputate quam et neque sollicitudin, ut mollis arcu ullamcorper. Sed tempus ligula quis neque gravida, eu auctor nisl consequat. Nulla cursus tellus non varius hendrerit.

Mauris in hendrerit enim. Nam porta nibh quis luctus elementum. Pellentesque tristique velit a mi aliquam, convallis ultricies turpis commodo. In tempor turpis vel congue vehicula. Nunc et bibendum ipsum. Nunc imperdiet sapien sed dapibus porttitor. Nullam euismod eget nulla ac pellentesque. Nullam eget erat egestas, viverra tortor a, venenatis odio. Morbi ipsum odio, hendrerit ut purus in, volutpat pretium diam. Aenean egestas dictum sapien, a finibus dolor blandit in. Duis facilisis sapien quis sem suscipit malesuada. In vel nunc iaculis, fringilla eros vel, facilisis ipsum. Quisque tempor congue quam, eu imperdiet erat pellentesque vel. Praesent sagittis libero id enim faucibus venenatis.

Curabitur eget ultrices ipsum, at tempor augue. Fusce finibus vel elit at rhoncus. Praesent enim dui, convallis at justo quis, dapibus rhoncus lectus. Vivamus condimentum orci sit amet risus porttitor faucibus. Morbi vitae luctus lacus. Maecenas in scelerisque arcu. Duis rutrum, ipsum ut accumsan placerat, ipsum enim sagittis sapien, id placerat ex ex sit amet elit. Nam malesuada erat vel ex sagittis ullamcorper. Nullam fringilla, arcu in finibus luctus, tellus odio molestie elit, mollis mollis nunc enim sit amet dolor. Nunc nec velit vel sem luctus tincidunt pharetra vel lectus. Phasellus scelerisque vel velit id molestie. Praesent tincidunt in dui non porta. Pellentesque pharetra nisl hendrerit nisl malesuada, vitae ornare dui feugiat.

Donec gravida blandit dignissim. Nam elementum metus mauris, et mollis tellus dictum eu. Phasellus in leo at ligula blandit tincidunt ut sed tortor. Aliquam feugiat ac lectus non convallis. Sed nisi sem, consequat ut sapien in, feugiat bibendum mauris. Integer mattis a turpis vel consectetur. Nunc efficitur diam at finibus tincidunt. Donec dictum, quam at tristique congue, purus turpis viverra ante, sit amet sollicitudin nisl mauris hendrerit dui.

Curabitur mollis vitae felis id faucibus. Maecenas gravida orci a ligula porttitor, vitae euismod magna aliquam. Ut at magna quis neque luctus bibendum. Maecenas metus ante, ultrices nec dolor in, aliquam aliquam mi. Vestibulum vitae leo convallis, consequat massa vitae, lacinia libero. Donec bibendum maximus ultrices. Donec porttitor commodo odio id eleifend. Fusce eros justo, dignissim eu commodo vel, elementum tincidunt dui. Aenean euismod id nisl non elementum. Phasellus auctor vestibulum congue. Pellentesque id quam et nisl eleifend semper vitae aliquam nunc. Nunc non ex eleifend, fringilla sem vitae, hendrerit quam.

Proin quis pulvinar lacus. Donec pulvinar egestas diam eu tempus. Pellentesque nec massa neque. Nulla facilisi. Quisque vehicula eget lorem a ultricies. Fusce vitae consectetur ex. Nunc sollicitudin id nulla quis pulvinar. Suspendisse et orci accumsan, dapibus justo sed, efficitur lectus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut fermentum commodo faucibus. Sed ac aliquet orci, vel laoreet augue. Proin tincidunt erat feugiat, accumsan mauris vitae, interdum odio. Vivamus ac venenatis neque. Quisque elementum nulla ut neque finibus blandit. Curabitur ut hendrerit neque, ac efficitur quam."""

max_stars_repo_name: ColinFay/LoremJulia

max_issues_repo_name: ColinFay/LoremJulia

max_forks_repo_name: ColinFay/LoremJulia


text:
import APTDecoder

wavname = "gqrx_20190825_182745_137620000.wav"
download("https://archive.org/download/gqrx_20190825_182745_137620000/gqrx_20190825_182745_137620000.wav",wavname)

APTDecoder.makeplots(wavname,"NOAA 15")

ext: jl

max_stars_repo_name: Alexander-Barth/APTDecoder

max_issues_repo_name: Alexander-Barth/APTDecoder

max_forks_repo_name: Alexander-Barth/APTDecoder


text:
using Test
using WorldBankData

indicator_data = Any[ Dict("total" => 5, "per_page" => "25000", "pages" => 1, "page" => 1),
                      Any[ Dict("sourceOrganization" => "World Bank and International Energy Agency (IEA Statistics © OECD/IEA, http://www.iea.org/stats/index.asp).  ", "id" => "12.1_TD.LOSSES", "topics" => [], "sourceNote" => "Transmission and distribution losses (%): Transmission and distribution (T&D) losses measure power lost in the transmission of (high-voltage) electricity from power generators to distributors and in the distribution of (medium- and low-voltage) electricity from distributors to end-users. T&D losses are represented as a percentage of gross electricity production. They include both technical and nontechnical (or commercial) losses. Included in the latter are unmetered, unbilled, and unpaid electricity, including theft, which could be significant in developing countries. Aggregate T&D system indicators may be dominated by factors other than losses. The location of primary energy resources (such as hydro lakes and coal seams) and large loads (cities and industries) may be more significant factors in T&D efficiency indicators than the losses or efficiency of the transmission system itself. Properly separating true losses (and hence the efficiency potential of transmission systems) from exogenous location and scale factors and nontechnical losses would require detailed studies of system-dynamic interactions and real operating requirements that are not practical for global tracking purposes.", "name" => "Transmission and distribution losses (%)", "source" => Dict("id" => "35", "value" => "Sustainable Energy for All")),
                       Dict("sourceOrganization" => "World Bank and International Energy Agency (IEA Statistics © OECD/IEA, http://www.iea.org/stats/index.asp).  ", "id" => "13.1_INDUSTRY.ENERGY.INTENSITY", "topics" => [], "sourceNote" => "Energy intensity of industrial sector (MJ/\$2005):  A ratio between energy consumption in industry (including energy industry own use) and industry sector value added measured at purchasing power parity. Energy intensity is an indication of how much energy is used to produce one unit of economic output. Lower ratio indicates that less energy is used to produce one unit of output. ", "name" => "Energy intensity of industrial sector (MJ/\$2005)", "source" => Dict("id" => "35", "value" => "Sustainable Energy for All")),
                       Dict("sourceOrganization" => "World Bank and International Energy Agency (IEA Statistics © OECD/IEA, http://www.iea.org/stats/index.asp).  ", "id" => "14.1_AGR.ENERGY.INTENSITY", "topics" => [], "sourceNote" => "Energy intensity of agricultural sector (MJ/\$2005):  A ratio between energy consumption in agricultural sector (including forestry and fishing) and agricultural sector value added measured at purchasing power parity. Energy intensity is an indication of how much energy is used to produce one unit of economic output. Lower ratio indicates that less energy is used to produce one unit of output. ", "name" => "Energy intensity of agricultural sector (MJ/\$2005)", "source" => Dict("id" => "35", "value" => "Sustainable Energy for All")),
                       Dict("sourceOrganization" => "World Bank and International Energy Agency (IEA Statistics © OECD/IEA, http://www.iea.org/stats/index.asp).  ", "id" => "15.1_OTHER.SECT.ENER.INTENS", "topics" => [], "sourceNote" => "Energy intensity of other sectors (MJ/\$2005): A ratio between energy consumption in other sectors (including services, residential and transport) and services sector value added measured at purchasing power parity. Energy intensity is an indication of how much energy is used to produce one unit of economic output. Lower ratio indicates that less energy is used to produce one unit of output. ", "name" => "Energy intensity of other sectors (MJ/\$2005)", "source" => Dict("id" => "35", "value" => "Sustainable Energy for All")),
                       Dict("sourceOrganization" => "World Bank and International Energy Agency (IEA Statistics © OECD/IEA, http://www.iea.org/stats/index.asp).  ", "id" => "16.1_DECOMP.EFFICIENCY.IND", "topics" => [], "sourceNote" => "The Index is created from the series of year to year Energy Intensity component of the Decomposition Analysis with the DIVISIA LMDI I method. The Significant Period is defined as the period for which the available data is consistent in the energy and value added databases such that all the sectors have energy and value added for those years. The CAGR is calculated over that Significant Period.", "name" => "Divisia Decomposition Analysis - Energy Intensity component Index", "source" => Dict("id" => "35", "value" => "Sustainable Energy for All"))
                      ]
                    ]

df_indicator = WorldBankData.parse_indicator(indicator_data)

@test df_indicator[!, :indicator] == String["12.1_TD.LOSSES", "13.1_INDUSTRY.ENERGY.INTENSITY", "14.1_AGR.ENERGY.INTENSITY", "15.1_OTHER.SECT.ENER.INTENS", "16.1_DECOMP.EFFICIENCY.IND"]
@test df_indicator[!, :name] == String["Transmission and distribution losses (%)", "Energy intensity of industrial sector (MJ/\$2005)", "Energy intensity of agricultural sector (MJ/\$2005)", "Energy intensity of other sectors (MJ/\$2005)", "Divisia Decomposition Analysis - Energy Intensity component Index"]


text:
export MPIArray, MPIVector, MPIMatrix, MPIVecOrMat, localindices, getblock, getblock!, putblock!, allocate, forlocalpart, forlocalpart!, free, redistribute, redistribute!, sync, GlobalBlock, GhostedBlock, getglobal, globaltolocal, globalids
using MPI
import LinearAlgebra
import Base: show, print_array, summary, array_summary, copyto!
import Adapt: adapt
"""
Store the distribution of the array indices over the different partitions.
This class forces a continuous, ordered distribution without overlap
    ContinuousPartitioning(partition_sizes...)
Construct a distribution using the number of elements per partition in each direction, e.g:
```
p = ContinuousPartitioning([2,5,3], [2,3])
```
will construct a distribution containing 6 partitions of 2, 5 and 3 rows and 2 and 3 columns.
"""
struct ContinuousPartitioning{N} <: AbstractArray{Int,N}
    ranks::LinearIndices{N,NTuple{N,Base.OneTo{Int}}}
    index_starts::NTuple{N,Vector{Int}}
    index_ends::NTuple{N,Vector{Int}}

    function ContinuousPartitioning(partition_sizes::Vararg{Any,N}) where {N}
        index_starts = Vector{Int}.(undef,length.(partition_sizes))
        index_ends = Vector{Int}.(undef,length.(partition_sizes))
        for (idxstart,idxend,nb_elems_dist) in zip(index_starts,index_ends,partition_sizes)
            currentstart = 1
            currentend = 0
            for i in eachindex(idxstart)
                currentend += nb_elems_dist[i]
                idxstart[i] = currentstart
                idxend[i] = currentend
                currentstart += nb_elems_dist[i]
            end
        end
        ranks = LinearIndices(length.(partition_sizes))
        return new{N}(ranks, index_starts, index_ends)
    end
end

Base.IndexStyle(::Type{ContinuousPartitioning{N}}) where {N} = IndexCartesian()
Base.size(p::ContinuousPartitioning) = length.(p.index_starts)
@inline function Base.getindex(p::ContinuousPartitioning{N}, I::Vararg{Int, N}) where {N}
    return UnitRange.(getindex.(p.index_starts,I), getindex.(p.index_ends,I))
end

function partition_sizes(p::ContinuousPartitioning)
    result = (p.index_ends .- p.index_starts)
    for v in result
        v .+= 1
    end
    return result
end

"""
  (private method)
Get the rank and local 0-based index
"""
function local_index(p::ContinuousPartitioning, I::NTuple{N,Int}) where {N}
    proc_indices = searchsortedfirst.(p.index_ends, I)
    lininds = LinearIndices(Base.Slice.(p[proc_indices...]))
    return (p.ranks[proc_indices...]-1, lininds[I...] - first(lininds))
end

# Evenly distribute nb_elems over parts partitions
function distribute(nb_elems, parts)
    local_len = nb_elems ÷ parts
    remainder = nb_elems % parts
    return [p <= remainder ? local_len+1 : local_len for p in 1:parts]
end

function local_lengths(x::ContinuousPartitioning{N}) where N
    convert(Vector{Int}, vec(map(x) do y
        prod(map(z -> length(z), y))
    end))
end

@inline allsame(x) = all(y -> y == first(x), x)

mutable struct MPIArray{T,N,A} <: AbstractArray{T,N}
    sizes::NTuple{N,Int}
    localarray::Union{A,Nothing}
    partitioning::ContinuousPartitioning{N}
    comm::MPI.Comm
    # win::MPI.Win
    myrank::Int
    local_lengths::Vector{Int}

    MPIArray{T,N,A}(sizes, localarray, partitioning, comm, myrank, local_lengths) where {T,N,A} = new{T,N,A}(sizes, localarray, partitioning, comm, myrank, local_lengths)
    function MPIArray{T,N,A}(comm::MPI.Comm, partition_sizes::Vararg{AbstractVector{<:Integer},N}) where {T,N,A}
        nb_procs = MPI.Comm_size(comm)
        rank = MPI.Comm_rank(comm)
        partitioning = ContinuousPartitioning(partition_sizes...)

        localarray = A{T}(undef,length.(partitioning[rank+1]))
        # win = MPI.Win_create(localarray, comm)
        sizes = sum.(partition_sizes)
        # return new{T,N,A}(sizes, localarray, partitioning, comm, win, rank, local_lengths(partitioning))
        return new{T,N,A}(sizes, localarray, partitioning, comm, rank, local_lengths(partitioning))
    end
    MPIArray{T,N,A}(comm::MPI.Comm, partitions::NTuple{N,<:Integer}, sizes::Vararg{<:Integer,N}) where {T,N,A} = MPIArray{T,N,A}(comm, distribute.(sizes, partitions)...)
    MPIArray{T,N,A}(::UndefInitializer, sizes::Vararg{<:Integer,N}) where {T,N,A} = MPIArray{T,N,A}(MPI.COMM_WORLD, (ones(Int, N-1)..., MPI.Comm_size(MPI.COMM_WORLD)), sizes...)

end

function MPIArray(comm::MPI.Comm, init::Function, partition_sizes::Vararg{AbstractVector{<:Integer}, N}; T=nothing, A=nothing) where N
    nb_procs = MPI.Comm_size(comm)
    rank = MPI.Comm_rank(comm)
    partitioning = ContinuousPartitioning(partition_sizes...)

    localarray = construct_localpart(init, partitioning;T=T,A=A)

    T = eltype(localarray)
    TLA = typeof(localarray)
    A = hasproperty(TLA, :name) ? TLA.name.wrapper : TLA

    sizes = sum.(partition_sizes)

    MPIArray{T,N,A}(sizes, localarray, partitioning, comm, rank, local_lengths(partitioning))

end

MPIArray(init::Function, partition_sizes::Vararg{AbstractVector{<:Integer}, N};T=nothing,A=nothing) where N = MPIArray(MPI.COMM_WORLD, init, partition_sizes...;T=T,A=A)

MPIArray(init::Function, partitions::NTuple{N,<:Integer}, sizes::Vararg{<:Integer,N};T=nothing, A=nothing) where N = MPIArray(init, distribute.(sizes, partitions)...; T=T,A=A)

MPIArray(init::Function, sizes::Vararg{<:Integer,N}; T=nothing, A=nothing) where N = MPIArray(init, (ones(Int, N-1)..., MPI.Comm_size(MPI.COMM_WORLD)), sizes...; T=T, A=A)

function MPIArray(comm::MPI.Comm, localarray::AbstractArray)
    #TODO, construct from localarrays
end

MPIArray(localarray::AbstractArray) = MPIArray(MPI.COMM_WORLD, localarray)

function construct_localpart(init, partitioning; T=nothing, A=nothing)
    localidx = partitioning[Rank() + 1]
    localpart = init(localidx)
    if A == nothing
        TLA = typeof(localpart)
        A = hasproperty(TLA, :name) ? TLA.name.wrapper : TLA
    end
    if T == nothing
        T = eltype(localpart)
    end
    adapt(A{T}, localpart)
end

MPIVector{T,A} = MPIArray{T,1,A}
MPIMatrix{T,A} = MPIArray{T,2,A}
MPIVecOrMat{T,A} = Union{MPIVector{T,A},MPIMatrix{T,A}}

Base.IndexStyle(::Type{MPIArray{T,N,A}}) where {T,N,A} = IndexCartesian()

Base.size(a::MPIArray) = a.sizes

"""
    show(io::IO, x::MPIArray)

String representation of an MPIArray
"""
function show(io::IO, m::MIME"text/plain", X::MPIArray)
    summary(io, X)
    print(io, "\nlocal part:\n")
    show(io, m, X.localarray)
end

function show(io::IO, X::MPIArray)
    print(io, "local part:\n")
    show(io, X.localarray)
end

function summary(io::IO, a::MPIArray)
    array_summary(io, a, axes(a))
    print(io, " with local block of ")
    array_summary(io, a.localarray, axes(a.localarray))
end

"""
    split_data(arr; root=0, T=T, A=A)
Splits the data (an AbstractArray in root) to the processes.
"""
function split_data(arr::AbstractArray; root=0, T=nothing, A=nothing)
    sz = MPI.bcast(size(arr), root=root, comm=MPI.COMM_WORLD)
    #TODO
end

"""
    sync(a::MPIArray)
Collective call, making sure all operations modifying any part of the array are finished when it completes
"""
sync(a::MPIArray, ::Vararg{MPIArray, N}) where N = MPI.Barrier(a.comm)

function Base.similar(a::MPIArray{T,N,A}, ::Type{T}, dims::NTuple{N,Int}) where {T,N,A}
    old_partition_sizes = partition_sizes(a.partitioning)
    old_dims = size(a)
    new_partition_sizes = Vector{Int}[]
    remaining_nb_partitons = prod(length.(old_partition_sizes))
    for i in eachindex(dims)
        if i <= length(old_dims)
            if dims[i] == old_dims[i]
                push!(new_partition_sizes, old_partition_sizes[i])
            else
                push!(new_partition_sizes, distribute(dims[i], length(old_partition_sizes[i])))
            end
        elseif remaining_nb_partitons != 1
            push!(new_partition_sizes, distribute(dims[i], remaining_nb_partitons))
        else
            push!(new_partition_sizes, [dims[i]])
        end
        @assert remaining_nb_partitons % length(last(new_partition_sizes)) == 0
        remaining_nb_partitons ÷= length(last(new_partition_sizes))
    end
    if remaining_nb_partitons > 1
        remaining_nb_partitons *= length(last(new_partition_sizes))
        new_partition_sizes[end] = distribute(dims[end], remaining_nb_partitons)
        remaining_nb_partitons ÷= length(last(new_partition_sizes))
    end
    @assert remaining_nb_partitons == 1
    return MPIArray{T,N,A}(a.comm, new_partition_sizes...)
end

function Base.filter(f,a::MPIArray)
    error("filter is only supported on 1D MPIArrays")
end

function Base.filter(f,a::MPIArray{T,1}) where T
    return MPIArray(forlocalpart(v -> filter(f,v), a), length(a.partitioning))
end

function Base.filter!(f,a::MPIArray)
    error("filter is only supported on 1D MPIArrays")
end

function copyto!(dest::MPIArray{T,N,A}, src::MPIArray{T,N,A}) where {T,N,A}
    @assert all(dest.sizes .== src.sizes)
    @assert all(dest.partitioning .== src.partitioning)
    @assert dest.comm == src.comm
    # dest.win = src.win
    @assert dest.myrank == src.myrank

    dest.localarray .= src.localarray
    return dest
end

Base.filter!(f,a::MPIArray{T,1,A}) where {T,A} = copy_into!(a, filter(f,a))

"""
    localindices(a::MPIArray, rank::Integer)
Get the local index range (expressed in terms of global indices) of the given rank
"""
@inline localindices(a::MPIArray, rank::Integer=a.myrank) = a.partitioning[rank+1]

"""
    forlocalpart(f, a::MPIArray)
Execute the function f on the part of a owned by the current rank. It is assumed f does not modify the local part.
"""
function forlocalpart(f, a::MPIArray)
    # MPI.Win_lock(MPI.LOCK_SHARED, a.myrank, 0, a.win)
    result = f(a.localarray)
    # MPI.Win_unlock(a.myrank, a.win)
    return result
end

"""
    forlocalpart(f, a::MPIArray)
Execute the function f on the part of a owned by the current rank. The local part may be modified by f.
"""
function forlocalpart!(f, As::Vararg{AbstractArray,N}) where N
    isMPIArray = x -> (typeof(x) <: MPIArray)
    for a in As
        isMPIArray(a) # && MPI.Win_lock(MPI.LOCK_EXCLUSIVE, a.myrank, 0, a.win)
    end
    result = f([isMPIArray(a) ? a.localarray : a for a in As]...)
    for a in As
        isMPIArray(a) # && MPI.Win_unlock(a.myrank, a.win)
    end
    return result
end


text:
export CuArray, CuVector, CuMatrix, CuVecOrMat, cu

@enum ArrayState begin
  ARRAY_UNMANAGED
  ARRAY_MANAGED
  ARRAY_FREED
end

mutable struct CuArray{T,N} <: AbstractGPUArray{T,N}
  ptr::CuPtr{T}
  dims::Dims{N}

  state::ArrayState
  ctx::CuContext

  function CuArray{T,N}(::UndefInitializer, dims::Dims{N})  where {T,N}
    Base.isbitsunion(T) && error("CuArray does not yet support union bits types")
    Base.isbitstype(T)  || error("CuArray only supports bits types") # allocatedinline on 1.3+
    ptr = alloc(prod(dims) * sizeof(T))
    obj = new{T,N}(ptr, dims, ARRAY_MANAGED, context())
    finalizer(unsafe_free!, obj)
    return obj
  end

  function CuArray{T,N}(ptr::CuPtr{T}, dims::Dims{N}, ctx=context()) where {T,N}
    Base.isbitsunion(T) && error("CuArray does not yet support union bits types")
    Base.isbitstype(T)  || error("CuArray only supports bits types") # allocatedinline on 1.3+
    return new{T,N}(ptr, dims, ARRAY_UNMANAGED, ctx)
  end
end

function unsafe_free!(xs::CuArray)
  # this call should only have an effect once, becuase both the user and the GC can call it
  if xs.state == ARRAY_FREED
    return
  elseif xs.state == ARRAY_UNMANAGED
    throw(ArgumentError("Cannot free an unmanaged buffer."))
  end

  if isvalid(xs.ctx)
    free(convert(CuPtr{Nothing}, pointer(xs)))
  end
  xs.state = ARRAY_FREED

  # the object is dead, so we can also wipe the pointer
  xs.ptr = CU_NULL

  return
end

Base.dataids(A::CuArray) = (UInt(pointer(A)),)

Base.unaliascopy(A::CuArray) = copy(A)

## convenience constructors

CuVector{T} = CuArray{T,1}
CuMatrix{T} = CuArray{T,2}
CuVecOrMat{T} = Union{CuVector{T},CuMatrix{T}}

# type and dimensionality specified, accepting dims as series of Ints
CuArray{T,N}(::UndefInitializer, dims::Integer...) where {T,N} = CuArray{T,N}(undef, dims)

# type but not dimensionality specified
CuArray{T}(::UndefInitializer, dims::Dims{N}) where {T,N} = CuArray{T,N}(undef, dims)
CuArray{T}(::UndefInitializer, dims::Integer...) where {T} =
  CuArray{T}(undef, convert(Tuple{Vararg{Int}}, dims))

# empty vector constructor
CuArray{T,1}() where {T} = CuArray{T,1}(undef, 0)

# do-block constructors
for (ctor, tvars) in (:CuArray => (), :(CuArray{T}) => (:T,), :(CuArray{T,N}) => (:T, :N))
  @eval begin
    function $ctor(f::Function, args...) where {$(tvars...)}
      xs = $ctor(args...)
      try
        f(xs)
      finally
        unsafe_free!(xs)
      end
    end
  end
end

Base.similar(a::CuArray{T,N}) where {T,N} = CuArray{T,N}(undef, size(a))
Base.similar(a::CuArray{T}, dims::Base.Dims{N}) where {T,N} = CuArray{T,N}(undef, dims)
Base.similar(a::CuArray, ::Type{T}, dims::Base.Dims{N}) where {T,N} = CuArray{T,N}(undef, dims)

function Base.copy(a::CuArray{T,N}) where {T,N}
  b = similar(a)
  @inbounds copyto!(b, a)
end

"""
  unsafe_wrap(::CuArray, ptr::CuPtr{T}, dims; own=false, ctx=context())

Wrap a `CuArray` object around the data at the address given by `ptr`. The pointer
element type `T` determines the array element type. `dims` is either an integer (for a 1d
array) or a tuple of the array dimensions. `own` optionally specified whether Julia should
take ownership of the memory, calling `cudaFree` when the array is no longer referenced. The
`ctx` argument determines the CUDA context where the data is allocated in.
"""
function Base.unsafe_wrap(::Union{Type{CuArray},Type{CuArray{T}},Type{CuArray{T,N}}},
                          p::CuPtr{T}, dims::NTuple{N,Int};
                          own::Bool=false, ctx::CuContext=context()) where {T,N}
  xs = CuArray{T, length(dims)}(p, dims, ctx)
  if own
    base = convert(CuPtr{Cvoid}, p)
    buf = Mem.DeviceBuffer(base, prod(dims) * sizeof(T))
    finalizer(xs) do obj
      if isvalid(obj.ctx)
        Mem.free(buf)
      end
    end
  end
  return xs
end

function Base.unsafe_wrap(Atype::Union{Type{CuArray},Type{CuArray{T}},Type{CuArray{T,1}}},
                          p::CuPtr{T}, dim::Integer;
                          own::Bool=false, ctx::CuContext=context()) where {T}
  unsafe_wrap(Atype, p, (dim,); own=own, ctx=ctx)
end

Base.unsafe_wrap(T::Type{<:CuArray}, ::Ptr, dims::NTuple{N,Int}; kwargs...) where {N} =
  throw(ArgumentError("cannot wrap a CPU pointer with a $T"))

## array interface

Base.elsize(::Type{<:CuArray{T}}) where {T} = sizeof(T)

Base.size(x::CuArray) = x.dims
Base.sizeof(x::CuArray) = Base.elsize(x) * length(x)

## derived types

export DenseCuArray, DenseCuVector, DenseCuMatrix, DenseCuVecOrMat,
       StridedCuArray, StridedCuVector, StridedCuMatrix, StridedCuVecOrMat,
       AnyCuArray, AnyCuVector, AnyCuMatrix, AnyCuVecOrMat

ContiguousSubCuArray{T,N,A<:CuArray} = Base.FastContiguousSubArray{T,N,A}

# dense arrays: stored contiguously in memory
DenseReinterpretCuArray{T,N,A<:Union{CuArray,ContiguousSubCuArray}} = Base.ReinterpretArray{T,N,S,A} where S
DenseReshapedCuArray{T,N,A<:Union{CuArray,ContiguousSubCuArray,DenseReinterpretCuArray}} = Base.ReshapedArray{T,N,A}
DenseSubCuArray{T,N,A<:Union{CuArray,DenseReshapedCuArray,DenseReinterpretCuArray}} = Base.FastContiguousSubArray{T,N,A}
DenseCuArray{T,N} = Union{CuArray{T,N}, DenseSubCuArray{T,N}, DenseReshapedCuArray{T,N}, DenseReinterpretCuArray{T,N}}
DenseCuVector{T} = DenseCuArray{T,1}
DenseCuMatrix{T} = DenseCuArray{T,2}
DenseCuVecOrMat{T} = Union{DenseCuVector{T}, DenseCuMatrix{T}}

# strided arrays
StridedSubCuArray{T,N,A<:Union{CuArray,DenseReshapedCuArray,DenseReinterpretCuArray},
                  I<:Tuple{Vararg{Union{Base.RangeIndex, Base.ReshapedUnitRange,
                                        Base.AbstractCartesianIndex}}}} = SubArray{T,N,A,I}
StridedCuArray{T,N} = Union{CuArray{T,N}, StridedSubCuArray{T,N}, DenseReshapedCuArray{T,N}, DenseReinterpretCuArray{T,N}}
StridedCuVector{T} = StridedCuArray{T,1}
StridedCuMatrix{T} = StridedCuArray{T,2}
StridedCuVecOrMat{T} = Union{StridedCuVector{T}, StridedCuMatrix{T}}

Base.pointer(x::StridedCuArray{T}) where {T} = Base.unsafe_convert(CuPtr{T}, x)
@inline function Base.pointer(x::StridedCuArray{T}, i::Integer) where T
    Base.unsafe_convert(CuPtr{T}, x) + Base._memory_offset(x, i)
end

# anything that's (secretly) backed by a CuArray
AnyCuArray{T,N} = Union{CuArray{T,N}, WrappedArray{T,N,CuArray,CuArray{T,N}}}
AnyCuVector{T} = AnyCuArray{T,1}
AnyCuMatrix{T} = AnyCuArray{T,2}
AnyCuVecOrMat{T} = Union{AnyCuVector{T}, AnyCuMatrix{T}}

## interop with other arrays

@inline function CuArray{T,N}(xs::AbstractArray{<:Any,N}) where {T,N}
  A = CuArray{T,N}(undef, size(xs))
  copyto!(A, convert(Array{T}, xs))
  return A
end

# underspecified constructors
CuArray{T}(xs::AbstractArray{S,N}) where {T,N,S} = CuArray{T,N}(xs)
(::Type{CuArray{T,N} where T})(x::AbstractArray{S,N}) where {S,N} = CuArray{S,N}(x)
CuArray(A::AbstractArray{T,N}) where {T,N} = CuArray{T,N}(A)

# idempotency
CuArray{T,N}(xs::CuArray{T,N}) where {T,N} = xs

## conversions

Base.convert(::Type{T}, x::T) where T <: CuArray = x

## interop with C libraries

Base.unsafe_convert(::Type{Ptr{T}}, x::CuArray{T}) where {T} = throw(ArgumentError("cannot take the CPU address of a $(typeof(x))"))
Base.unsafe_convert(::Type{CuPtr{T}}, x::CuArray{T}) where {T} = x.ptr

## interop with device arrays

function Base.unsafe_convert(::Type{CuDeviceArray{T,N,AS.Global}}, a::DenseCuArray{T,N}) where {T,N}
  CuDeviceArray{T,N,AS.Global}(size(a), reinterpret(LLVMPtr{T,AS.Global}, pointer(a)))
end

Adapt.adapt_storage(::Adaptor, xs::CuArray{T,N}) where {T,N} =
  Base.unsafe_convert(CuDeviceArray{T,N,AS.Global}, xs)

# we materialize ReshapedArray/ReinterpretArray/SubArray/... directly as a device array
Adapt.adapt_structure(::Adaptor, xs::DenseCuArray{T,N}) where {T,N} =
  Base.unsafe_convert(CuDeviceArray{T,N,AS.Global}, xs)

## interop with CPU arrays

# We don't convert isbits types in `adapt`, since they are already
# considered GPU-compatible.

Adapt.adapt_storage(::Type{CuArray}, xs::AT) where {AT<:AbstractArray} =
  isbitstype(AT) ? xs : convert(CuArray, xs)

# if an element type is specified, convert to it
Adapt.adapt_storage(::Type{<:CuArray{T}}, xs::AT) where {T, AT<:AbstractArray} =
  isbitstype(AT) ? xs : convert(CuArray{T}, xs)

Adapt.adapt_storage(::Type{Array}, xs::CuArray) = convert(Array, xs)

Base.collect(x::CuArray{T,N}) where {T,N} = copyto!(Array{T,N}(undef, size(x)), x)

function Base.copyto!(dest::DenseCuArray{T}, doffs::Integer, src::Array{T}, soffs::Integer,
                      n::Integer) where T
  n==0 && return dest
  @boundscheck checkbounds(dest, doffs)
  @boundscheck checkbounds(dest, doffs+n-1)
  @boundscheck checkbounds(src, soffs)
  @boundscheck checkbounds(src, soffs+n-1)
  unsafe_copyto!(dest, doffs, src, soffs, n)
  return dest
end

Base.copyto!(dest::DenseCuArray{T}, src::Array{T}) where {T} =
    copyto!(dest, 1, src, 1, length(src))

function Base.copyto!(dest::Array{T}, doffs::Integer, src::DenseCuArray{T}, soffs::Integer,
                      n::Integer) where T
  n==0 && return dest
  @boundscheck checkbounds(dest, doffs)
  @boundscheck checkbounds(dest, doffs+n-1)
  @boundscheck checkbounds(src, soffs)
  @boundscheck checkbounds(src, soffs+n-1)
  unsafe_copyto!(dest, doffs, src, soffs, n)
  return dest
end

Base.copyto!(dest::Array{T}, src::DenseCuArray{T}) where {T} =
    copyto!(dest, 1, src, 1, length(src))

function Base.copyto!(dest::DenseCuArray{T}, doffs::Integer, src::DenseCuArray{T}, soffs::Integer,
                      n::Integer) where T
  n==0 && return dest
  @boundscheck checkbounds(dest, doffs)
  @boundscheck checkbounds(dest, doffs+n-1)
  @boundscheck checkbounds(src, soffs)
  @boundscheck checkbounds(src, soffs+n-1)
  unsafe_copyto!(dest, doffs, src, soffs, n)
  return dest
end

Base.copyto!(dest::DenseCuArray{T}, src::DenseCuArray{T}) where {T} =
    copyto!(dest, 1, src, 1, length(src))

function Base.unsafe_copyto!(dest::DenseCuArray{T}, doffs, src::Array{T}, soffs, n) where T
  GC.@preserve src dest unsafe_copyto!(pointer(dest, doffs), pointer(src, soffs), n)
  if Base.isbitsunion(T)
    # copy selector bytes
    error("Not implemented")
  end
  return dest
end

function Base.unsafe_copyto!(dest::Array{T}, doffs, src::DenseCuArray{T}, soffs, n) where T
  GC.@preserve src dest unsafe_copyto!(pointer(dest, doffs), pointer(src, soffs), n)
  if Base.isbitsunion(T)
    # copy selector bytes
    error("Not implemented")
  end
  return dest
end

function Base.unsafe_copyto!(dest::DenseCuArray{T}, doffs, src::DenseCuArray{T}, soffs, n) where T
  GC.@preserve src dest unsafe_copyto!(pointer(dest, doffs), pointer(src, soffs), n;
                                       async=true, stream=CuStreamPerThread())
  if Base.isbitsunion(T)
    # copy selector bytes
    error("Not implemented")
  end
  return dest
end

function Base.deepcopy_internal(x::CuArray, dict::IdDict)
  haskey(dict, x) && return dict[x]::typeof(x)
  return dict[x] = copy(x)
end

## Float32-preferring conversion

struct Float32Adaptor end

Adapt.adapt_storage(::Float32Adaptor, xs::AbstractArray) =
  isbits(xs) ? xs : convert(CuArray, xs)

Adapt.adapt_storage(::Float32Adaptor, xs::AbstractArray{<:AbstractFloat}) =
  isbits(xs) ? xs : convert(CuArray{Float32}, xs)

# not for Float16
Adapt.adapt_storage(::Float32Adaptor, xs::AbstractArray{Float16}) =
  isbits(xs) ? xs : convert(CuArray, xs)
Adapt.adapt_storage(::Float32Adaptor, xs::AbstractArray{BFloat16}) =
  isbits(xs) ? xs : convert(CuArray, xs)

cu(xs) = adapt(Float32Adaptor(), xs)
Base.getindex(::typeof(cu), xs...) = CuArray([xs...])

## utilities

zeros(T::Type, dims...) = fill!(CuArray{T}(undef, dims...), 0)
ones(T::Type, dims...) = fill!(CuArray{T}(undef, dims...), 1)
zeros(dims...) = zeros(Float32, dims...)
ones(dims...) = ones(Float32, dims...)
fill(v, dims...) = fill!(CuArray{typeof(v)}(undef, dims...), v)
fill(v, dims::Dims) = fill!(CuArray{typeof(v)}(undef, dims...), v)

# optimized implementation of `fill!` for types that are directly supported by memset
memsettype(T::Type) = T
memsettype(T::Type{<:Signed}) = unsigned(T)
memsettype(T::Type{<:AbstractFloat}) = Base.uinttype(T)
const MemsetCompatTypes = Union{UInt8, Int8,
                                UInt16, Int16, Float16,
                                UInt32, Int32, Float32}
function Base.fill!(A::DenseCuArray{T}, x) where T <: MemsetCompatTypes
  U = memsettype(T)
  y = reinterpret(U, convert(T, x))
  Mem.set!(convert(CuPtr{U}, pointer(A)), y, length(A))
  A
end

## views

@inline function Base.view(A::CuArray, I::Vararg{Any,N}) where {N}
    J = to_indices(A, I)
    @boundscheck begin
        # Base's boundscheck accesses the indices, so make sure they reside on the CPU.
        # this is expensive, but it's a bounds check after all.
        J_cpu = map(j->adapt(Array, j), J)
        checkbounds(A, J_cpu...)
    end
    J_gpu = map(j->adapt(CuArray, j), J)
    Base.unsafe_view(Base._maybe_reshape_parent(A, Base.index_ndims(J_gpu...)), J_gpu...)
end

## reshape

Base.unsafe_convert(::Type{CuPtr{T}}, a::Base.ReshapedArray{T}) where {T} =
  Base.unsafe_convert(CuPtr{T}, parent(a))

## reinterpret

Base.unsafe_convert(::Type{CuPtr{T}}, a::Base.ReinterpretArray{T,N,S} where N) where {T,S} =
  CuPtr{T}(Base.unsafe_convert(CuPtr{S}, parent(a)))

## resizing

"""
  resize!(a::CuVector, n::Int)

Resize `a` to contain `n` elements. If `n` is smaller than the current collection length,
the first `n` elements will be retained. If `n` is larger, the new elements are not
guaranteed to be initialized.

Note that this operation is only supported on managed buffers, i.e., not on arrays that are
created by `unsafe_wrap` with `own=false`.
"""
function Base.resize!(A::CuVector{T}, n::Int) where T
  ptr = convert(CuPtr{T}, alloc(n * sizeof(T)))
  m = Base.min(length(A), n)
  unsafe_copyto!(ptr, pointer(A), m)

  unsafe_free!(A)

  A.state = ARRAY_MANAGED
  A.dims = (n,)
  A.ptr = ptr

  A
end


text:
df = DataFrame(CSV.File("../datasets/creeprupt/taka", header=0))
data = convert(Matrix, df[:,3:end])
target = convert(Array, df[:, 2])

max_stars_repo_name: dbindel/btg

max_issues_repo_name: dbindel/btg

max_forks_repo_name: dbindel/btg


text:
function setlogger(path, level)
    filepath = joinpath(path, "simlog.log")
    loglevel = getfield(Logging, Symbol(level))
    TeeLogger(
        MinLevelLogger(FileLogger(filepath), loglevel),
        MinLevelLogger(ConsoleLogger(), loglevel)
    ) |> global_logger
end


text:
using Test

project = abspath(joinpath(@__DIR__(), ".."))
path = readdir(joinpath(project, "solutions"); join=true)
solutions = filter(isdir, path)

for student in solutions
	files = filter(x->endswith(x, ".jl"), readdir(student; join=true))
	for file in files
		try
			run(`julia --project=$project $file`)
		catch err
			if err isa ProcessFailedException
				@error "Tests failed for student `$(basename(student))` in file `$file`"
			end
			rethrow(err)
		end
	end
end