module Benchmarks.Mul
    ( initEnv
    , benchmark
    ) where

import Control.Exception (evaluate)
import Test.Tasty.Bench
import Data.Int (Int32, Int64)
import Data.Text.Internal (mul32, mul64)
import qualified Data.Vector.Unboxed as U

oldMul :: Int64 -> Int64 -> Int64
oldMul m n
    | n == 0                 = 0
    | m <= maxBound `quot` n = m * n
    | otherwise              = error "overflow"

type Env = (U.Vector (Int32,Int32), U.Vector (Int64,Int64))

initEnv :: IO Env
initEnv = do
    x <- evaluate testVector32
    y <- evaluate testVector64
    return (x, y)

benchmark :: Env -> Benchmark
benchmark ~(tv32, tv64) = bgroup "Mul"
    [ bench "oldMul" $ whnf (U.map (uncurry oldMul)) tv64
    , bench "mul64" $ whnf (U.map (uncurry mul64)) tv64
    , bench "*64" $ whnf (U.map (uncurry (*))) tv64
    , bench "mul32" $ whnf (U.map (uncurry mul32)) tv32
    , bench "*32" $ whnf (U.map (uncurry (*))) tv32
    ]

testVector64 :: U.Vector (Int64,Int64)
testVector64 = U.fromList [
  (0,1248868987182846646),(169004623633872,24458),(482549039517835,7614),
  (372,8157063115504364),(27,107095594861148252),(3,63249878517962420),
  (4363,255694473572912),(86678474,1732634806),(1572453024,1800489338),
  (9384523143,77053781),(49024709555,75095046),(7,43457620410239131),
  (8,8201563008844571),(387719037,1520696708),(189869238220197,1423),
  (46788016849611,23063),(503077742109974359,0),(104,1502010908706487),
  (30478140346,207525518),(80961140129236192,14),(4283,368012829143675),
  (1028719181728108146,6),(318904,5874863049591),(56724427166898,110794),
  (234539368,31369110449),(2,251729663598178612),(103291548194451219,5),
  (76013,5345328755566),(1769631,2980846129318),(40898,60598477385754),
  (0,98931348893227155),(573555872156917492,3),(318821187115,4476566),
  (11152874213584,243582),(40274276,16636653248),(127,4249988676030597),
  (103543712111871836,5),(71,16954462148248238),(3963027173504,216570),
  (13000,503523808916753),(17038308,20018685905),(0,510350226577891549),
  (175898,3875698895405),(425299191292676,5651),(17223451323664536,50),
  (61755131,14247665326),(0,1018195131697569303),(36433751497238985,20),
  (3473607861601050,1837),(1392342328,1733971838),(225770297367,3249655),
  (14,127545244155254102),(1751488975299136,2634),(3949208,504190668767),
  (153329,831454434345),(1066212122928663658,2),(351224,2663633539556),
  (344565,53388869217),(35825609350446863,54),(276011553660081475,10),
  (1969754174790470349,3),(35,68088438338633),(506710,3247689556438),
  (11099382291,327739909),(105787303549,32824363),(210366111,14759049409),
  (688893241579,3102676),(8490,70047474429581),(152085,29923000251880),
  (5046974599257095,400),(4183167795,263434071),(10089728,502781960687),
  (44831977765,4725378),(91,8978094664238578),(30990165721,44053350),
  (1772377,149651820860),(243420621763408572,4),(32,5790357453815138),
  (27980806337993771,5),(47696295759774,20848),(1745874142313778,1098),
  (46869334770121,1203),(886995283,1564424789),(40679396544,76002479),
  (1,672849481568486995),(337656187205,3157069),(816980552858963,6003),
  (2271434085804831543,1),(0,1934521023868747186),(6266220038281,15825),
  (4160,107115946987394),(524,246808621791561),(0,1952519482439636339),
  (128,2865935904539691),(1044,3211982069426297),(16000511542473,88922),
  (1253596745404082,2226),(27041,56836278958002),(23201,49247489754471),
  (175906590497,21252392),(185163584757182295,24),(34742225226802197,150),
  (2363228,250824838408),(216327527109550,45),(24,81574076994520675),
  (28559899906542,15356),(10890139774837133,511),(2293,707179303654492),
  (2749366833,40703233),(0,4498229704622845986),(439,4962056468281937),
  (662,1453820621089921),(16336770612459631,220),(24282989393,74239137),
  (2724564648490195,3),(743672760,124992589),(4528103,704330948891),
  (6050483122491561,250),(13322953,13594265152),(181794,22268101450214),
  (25957941712,75384092),(43352,7322262295009),(32838,52609059549923),
  (33003585202001564,2),(103019,68430142267402),(129918230800,8742978),
  (0,2114347379589080688),(2548,905723041545274),(222745067962838382,0),
  (1671683850790425181,1),(455,4836932776795684),(794227702827214,6620),
  (212534135175874,1365),(96432431858,29784975),(466626763743380,3484),
  (29793949,53041519613),(8359,309952753409844),(3908960585331901,26),
  (45185288970365760,114),(10131829775,68110174),(58039242399640479,83),
  (628092278238719399,6),(1,196469106875361889),(302336625,16347502444),
  (148,3748088684181047),(1,1649096568849015456),(1019866864,2349753026),
  (8211344830,569363306),(65647579546873,34753),(2340190,1692053129069),
  (64263301,30758930355),(48681618072372209,110),(7074794736,47640197),
  (249634721521,7991792),(1162917363807215,232),(7446433349,420634045),
  (63398619383,60709817),(51359004508011,14200),(131788797028647,7072),
  (52079887791430043,7),(7,136277667582599838),(28582879735696,50327),
  (1404582800566278,833),(469164435,15017166943),(99567079957578263,49),
  (1015285971,3625801566),(321504843,4104079293),(5196954,464515406632),
  (114246832260876,7468),(8149664437,487119673),(12265299,378168974869),
  (37711995764,30766513),(3971137243,710996152),(483120070302,603162),
  (103009942,61645547145),(8476344625340,6987),(547948761229739,1446),
  (42234,18624767306301),(13486714173011,58948),(4,198309153268019840),
  (9913176974,325539248),(28246225540203,116822),(2882463945582154,18),
  (959,25504987505398),(3,1504372236378217710),(13505229956793,374987),
  (751661959,457611342),(27375926,36219151769),(482168869,5301952074),
  (1,1577425863241520640),(714116235611821,1164),(904492524250310488,0),
  (5983514941763398,68),(10759472423,23540686),(72539568471529,34919),
  (4,176090672310337473),(938702842110356453,1),(673652445,3335287382),
  (3111998893666122,917),(1568013,3168419765469)]

testVector32 :: U.Vector (Int32,Int32)
testVector32 = U.fromList [
  (39242,410),(0,100077553),(2206,9538),(509400240,1),(38048,6368),
  (1789,651480),(2399,157032),(701,170017),(5241456,14),(11212,70449),
  (1,227804876),(749687254,1),(74559,2954),(1158,147957),(410604456,1),
  (170851,1561),(92643422,1),(6192,180509),(7,24202210),(3440,241481),
  (5753677,5),(294327,1622),(252,4454673),(127684121,11),(28315800,30),
  (340370905,0),(1,667887987),(592782090,1),(49023,27641),(750,290387),
  (72886,3847),(0,301047933),(3050276,473),(1,788366142),(59457,15813),
  (637726933,1),(1135,344317),(853616,264),(696816,493),(7038,12046),
  (125219574,4),(803694088,1),(107081726,1),(39294,21699),(16361,38191),
  (132561123,12),(1760,23499),(847543,484),(175687349,1),(2963,252678),
  (6248,224553),(27596,4606),(5422922,121),(1542,485890),(131,583035),
  (59096,4925),(3637115,132),(0,947225435),(86854,6794),(2984745,339),
  (760129569,1),(1,68260595),(380835652,2),(430575,2579),(54514,7211),
  (15550606,3),(9,27367402),(3007053,207),(7060988,60),(28560,27130),
  (1355,21087),(10880,53059),(14563646,4),(461886361,1),(2,169260724),
  (241454126,2),(406797,1),(61631630,16),(44473,5943),(63869104,12),
  (950300,1528),(2113,62333),(120817,9358),(100261456,1),(426764723,1),
  (119,12723684),(3,53358711),(4448071,18),(1,230278091),(238,232102),
  (8,57316440),(42437979,10),(6769,19555),(48590,22006),(11500585,79),
  (2808,97638),(42,26952545),(11,32104194),(23954638,1),(785427272,0),
  (513,81379),(31333960,37),(897772,1009),(4,25679692),(103027993,12),
  (104972702,11),(546,443401),(7,65137092),(88574269,3),(872139069,0),
  (2,97417121),(378802603,0),(141071401,4),(22613,10575),(2191743,118),
  (470,116119),(7062,38166),(231056,1847),(43901963,9),(2400,70640),
  (63553,1555),(34,11249573),(815174,1820),(997894011,0),(98881794,2),
  (5448,43132),(27956,9),(904926,1357),(112608626,3),(124,613021),
  (282086,1966),(99,10656881),(113799,1501),(433318,2085),(442,948171),
  (165380,1043),(28,14372905),(14880,50462),(2386,219918),(229,1797565),
  (1174961,298),(3925,41833),(3903515,299),(15690452,111),(360860521,3),
  (7440846,81),(2541026,507),(0,492448477),(6869,82469),(245,8322939),
  (3503496,253),(123495298,0),(150963,2299),(33,4408482),(1,200911107),
  (305,252121),(13,123369189),(215846,8181),(2440,65387),(776764401,1),
  (1241172,434),(8,15493155),(81953961,6),(17884993,5),(26,6893822),
  (0,502035190),(1,582451018),(2,514870139),(227,3625619),(49,12720258),
  (1456769,207),(94797661,10),(234407,893),(26843,5783),(15688,24547),
  (4091,86268),(4339448,151),(21360,6294),(397046497,2),(1227,205936),
  (9966,21959),(160046791,1),(0,159992224),(27,24974797),(19177,29334),
  (4136148,42),(21179785,53),(61256583,31),(385,344176),(7,11934915),
  (1,18992566),(3488065,5),(768021,224),(36288474,7),(8624,117561),
  (8,20341439),(5903,261475),(561,1007618),(1738,392327),(633049,1708)]
