text: import pytest
  import numpy as np
  from pyGPB import GPB
  from pyGPB._cpu_methods import _GPB_DP_DC_FFT_Combo, _GPB_CF
  from pyGPB._gpu_methods import _GPB_DP_CUDA
  import pyGPB._cpu_methods as cpu
  import pyGPB._gpu_methods as gpu
  
  simple_test_cases = [
      {'probs': [0.040315790866, 0.71982418469],
       'weights': [4, 3],
       'expected': [0.268880305735, 0., 0., 0.6908039034, 0.011295509576, 0., 0., 0.02902028129]},
      {'probs': [0.26464448403, 0.952465307878, 0.574899597624],
       'weights': [4, 2, 2],
       'expected': [0.014859341227, 0., 0.317836141326, 0., 0.408007708938, 0., 0.114384919676, 0., 0.144911888833]},
      {'probs': [0.004952306396, 0.278227527594, 0.454419445766, 0.778937136742],
       'weights': [4, 4, 2, 1],
       'expected': [8.662014081221e-02, 3.052147406131e-01, 7.214677296442e-02, 2.542163795848e-01, 3.382127729695e-02,
                    1.191726575436e-01, 2.817007674693e-02, 9.926008647349e-02, 1.661813475627e-04, 5.855566201520e-04,
                    1.384140898538e-04, 4.877159068987e-04]},
      {'probs': [0.856723522181, 0.001648728171, 0.333930371546, 0.747551500179, 0.11689013997],
       'weights': [3, 5, 2, 2, 5],
       'expected': [2.124053401382e-02, 0.000000000000e+00, 7.354637942747e-02, 1.270080434023e-01, 3.153334511801e-02,
                    4.426180277231e-01, 0.000000000000e+00, 1.984102385383e-01, 1.702077939061e-02, 4.225890709944e-03,
                    5.893991729178e-02, 0.000000000000e+00, 2.528484371970e-02, 2.776259473388e-05, 6.892850701921e-06,
                    9.612933106391e-05, 0.000000000000e+00, 4.121588847743e-05]},
      {'probs': [0.740304850617, 0.516865004419, 0.579051469742, 0.856170930578, 0.920293729432, 0.385671330342],
       'weights': [3, 4, 2, 5, 5, 4],
       'expected': [0.000371964313, 0., 0.000511669401, 0.001060347049, 0.000631449603, 0.007967514886, 0.00086861408,
                    0.010753634613, 0.018804579998, 0.013525717197, 0.051432534087, 0.015911823749, 0.066665864486,
                    0.078229055794, 0.086728901818, 0.106263334355, 0.072161836989, 0.123718097475, 0.034312442355,
                    0.170185048829, 0.02361905032, 0.048946429609, 0., 0.067330088993]},
      {'probs': [0.701436588957, 0.614940930874, 0.742826974376, 0.087849814797, 0.769687855284, 0.811488183321,
                 0.039888801387],
       'weights': [4, 2, 5, 5, 1, 2, 1],
       'expected': [0.001124171728, 0.003803611941, 0.006790621644, 0.022447819935, 0.011290534471, 0.038439909458,
                    0.028379527864, 0.073006547953, 0.087321728258, 0.095131778857, 0.107552027965, 0.05187851189,
                    0.159299309267, 0.06689690348, 0.186500920647, 0.017284402426, 0.004736611925, 0.014671102577,
                    0.005652966404, 0.01708970049, 0.00070129082]},
      {'probs': [0.855124131187, 0.919443012474, 0.216351333075, 0.806322676582, 0.171443055158, 0.090659059102,
                 0.39426161905, 0.445355113337],
       'weights': [1, 3, 5, 4, 1, 2, 4, 5],
       'expected': [0.000448382503, 0.002739338383, 0.000592322635, 0.005390751485, 0.033478793788, 0.02043180087,
                    0.008924459231, 0.027213920528, 0.157810714157, 0.076093638566, 0.038235143482, 0.024655072962,
                    0.113676550467, 0.1835214572, 0.058996014445, 0.024034682974, 0.0203222376, 0.097469111725,
                    0.053461482389, 0.017974522785, 0.005504393821, 0.003903249039, 0.018814128411, 0.004061056596,
                    0.001872452713, 0.000374321245]},
      {'probs': [4.729732958941e-05, 1.308768858592e-01, 5.960962062589e-01, 9.014320656266e-01, 4.456484448449e-01,
                 8.677219339456e-01, 5.451251904484e-01, 2.602791177053e-01, 4.087990990123e-01],
       'weights': [4, 5, 1, 5, 3, 4, 4, 3, 1],
       'expected': [5.047104610493e-04, 1.093863774392e-03, 5.150573328066e-04, 5.833295570274e-04, 5.179944146515e-03,
                    1.377352086242e-02, 1.430714496554e-02, 9.622960380468e-03, 1.934459707968e-02, 6.137016162390e-02,
                    9.027512597388e-02, 4.696598966402e-02, 5.672506816856e-02, 1.349012264578e-01, 1.311295150104e-01,
                    6.287704949133e-02, 7.179112480152e-02, 1.095615162340e-01, 6.268103118186e-02, 2.863851778376e-02,
                    2.971632088136e-02, 2.027313791488e-02, 1.524664870814e-02, 6.446064066681e-03, 1.547004955072e-03,
                    3.350751238102e-03, 1.578006298020e-03, 3.048319726425e-07, 7.310618889528e-08, 1.584437373264e-07,
                    7.460491028020e-08]},
      {'probs': [0.063304693156, 0.188818049832, 0.265862161237, 0.250382997591, 0.298832970207, 0.305199791989,
                 0.110688792413, 0.905993670759, 0.99997431531, 0.421069144849],
       'weights': [2, 4, 3, 1, 5, 4, 5, 4, 4, 3],
       'expected': [2.532368920643e-07, 8.458481055243e-08, 1.711451272437e-08, 2.816089783140e-07, 9.861898656861e-03,
                    3.294145110819e-03, 6.666101252478e-04, 1.096673261136e-02, 1.052350017077e-01, 4.010796540264e-02,
                    1.152351599667e-02, 1.142690368709e-01, 1.080671681185e-01, 8.715685711230e-02, 5.327507381330e-02,
                    8.659517862406e-02, 9.788511952621e-02, 6.538988502725e-02, 4.100273783923e-02, 3.688319274601e-02,
                    4.984911703511e-02, 2.648697769316e-02, 1.295975930970e-02, 1.305200075585e-02, 1.104991775472e-02,
                    6.941055309685e-03, 2.469724782268e-03, 1.998233331846e-03, 1.496404762519e-03, 9.710525644093e-04,
                    2.805988728754e-04, 5.840431518951e-05, 1.484188391041e-04, 4.534057660093e-05, 9.174009731757e-06,
                    3.064252877380e-06]}
  ]
  three_param_test_cases = [
      {'probs': [0.35466529334],
       'weights_success': [4],
       'weights_failure': [-3],
       'expected_pmf': [0.64533470666, 0., 0., 0., 0.,
                        0., 0., 0.35466529334],
       'support_min': -3,
       'support_max': 4},
      {'probs': [0.371924819366],
       'weights_success': [3],
       'weights_failure': [5],
       'expected_pmf': [0.371924819366, 0., 0.628075180634],
       'support_min': 3,
       'support_max': 5},
      {'probs': [0.639653647938],
       'weights_success': [-5],
       'weights_failure': [2],
       'expected_pmf': [0.639653647938, 0., 0., 0.,
                        0., 0., 0., 0.360346352062],
       'support_min': -5,
       'support_max': 2},
      {'probs': [0.792376334318, 0.341131274419],
       'weights_success': [-2, -3],
       'weights_failure': [5, 2],
       'expected_pmf': [0.270304348745, 0., 0., 0.,
                        0., 0.522071985573, 0., 0.070826925674,
                        0., 0., 0., 0.,
                        0.136796740008],
       'support_min': -5,
       'support_max': 7},
      {'probs': [0.821275585553, 0.431710191775],
       'weights_success': [5, 2],
       'weights_failure': [4, -1],
       'expected_pmf': [0.101567263211, 0.466722545014, 0., 0.077157151236,
                        0.354553040539],
       'support_min': 3,
       'support_max': 7},
      {'probs': [0.387864983356, 0.272203097381],
       'weights_success': [3, -5],
       'weights_failure': [-3, -1],
       'expected_pmf': [0.166625047546, 0., 0., 0.,
                        0.445509969098, 0., 0.105578049835, 0.,
                        0., 0., 0.282286933521],
       'support_min': -8,
       'support_max': 2},
      {'probs': [0.894090383459, 0.009142565236, 0.431396711376],
       'weights_success': [0, 3, 3],
       'weights_failure': [-3, 5, 5],
       'expected_pmf': [4.177152141877e-04, 0.000000000000e+00, 4.582191542884e-02,
                        3.526357362327e-03, 5.966998589776e-02, 3.868292160309e-01,
                        0.000000000000e+00, 5.037348100660e-01],
       'support_min': 3,
       'support_max': 10},
      {'probs': [0.746890555284, 0.045742947541, 0.01559276728],
       'weights_success': [3, 5, -3],
       'weights_failure': [-1, -5, 0],
       'expected_pmf': [3.766144043925e-03, 0.000000000000e+00, 0.000000000000e+00,
                        2.377653286199e-01, 1.111336409990e-02, 0.000000000000e+00,
                        0.000000000000e+00, 7.016122156952e-01, 0.000000000000e+00,
                        0.000000000000e+00, 1.805326237720e-04, 0.000000000000e+00,
                        0.000000000000e+00, 1.139743942800e-02, 5.327265119149e-04,
                        0.000000000000e+00, 0.000000000000e+00, 3.363224897738e-02],
       'support_min': -9,
       'support_max': 8},
      {'probs': [0.112471632611, 0.953820996708, 0.795747403238],
       'weights_success': [2, -5, 4],
       'weights_failure': [-1, -4, -3],
       'expected_pmf': [0.172908645235, 0.008371328504, 0., 0.021911770189,
                        0.001060852834, 0., 0., 0.673634546754,
                        0.032613846896, 0., 0.085366034529, 0.004132975058],
       'support_min': -9,
       'support_max': 2},
      {'probs': [0.19928055491, 0.065416952672, 0.547038501058, 0.120736333003],
       'weights_success': [3, 3, -5, -3],
       'weights_failure': [-2, 2, 0, -4],
       'expected_pmf': [0.359944295604, 0.074620464061, 0.003459605346, 0.,
                        0., 0.3876246508, 0.080358910191, 0.003725655137,
                        0., 0., 0.074175970903, 0.01537750546,
                        0.000712942499],
       'support_min': -9,
       'support_max': 3},
      {'probs': [0.924392834447, 0.442881941084, 0.944914531386, 0.130580602551],
       'weights_success': [0, 4, -1, -2],
       'weights_failure': [2, 5, 1, 0],
       'expected_pmf': [0.050514462746, 0.063544066312, 0.343407077297, 0.431984839692,
                        0.047356722556, 0.059571824677, 0.001603678485, 0.002017328235],
       'support_min': 1,
       'support_max': 8},
      {'probs': [0.701492960746, 0.616628492443, 0.911492001455, 0.958401109876],
       'weights_success': [-2, 1, 2, 4],
       'weights_failure': [-3, 0, 5, -3],
       'expected_pmf': [0.004339193479, 0.017176439826, 0.016401422312, 0.000421345804,
                        0.001667872355, 0.001592616348, 0., 0.099971125042,
                        0.395729764516, 0.377874056281, 0.009707429331, 0.038426282804,
                        0.036692451903],
       'support_min': -4,
       'support_max': 8},
      {'probs': [0.964466152752, 0.008384306217, 0.350863942904, 0.103097761895,
                 0.98011117398],
       'weights_success': [1, -5, 5, 2, -1],
       'weights_failure': [-5, -4, 1, 0, -4],
       'expected_pmf': [3.449843168634e-06, 4.080145140857e-04, 3.965550474332e-07,
                        2.169072519745e-04, 2.010861124384e-02, 2.400775857671e-04,
                        2.405095342490e-03, 1.119164458376e-02, 1.087864276715e-02,
                        5.897898777070e-03, 5.470408369800e-01, 6.516229551306e-03,
                        6.273804302416e-02, 3.182158726129e-03, 2.949779616700e-01,
                        2.866932315973e-04, 3.390733835247e-02],
       'support_min': -13,
       'support_max': 3},
      {'probs': [0.834695977775, 0.642949269395, 0.55043470026, 0.142023658384,
                 0.457479768836],
       'weights_success': [3, 3, 2, -1, 3],
       'weights_failure': [0, 4, -5, 2, 2],
       'expected_pmf': [0.003681540175, 0.005148935442, 0.001724005781, 0.040830268547,
                        0.057104474441, 0.019120155066, 0.112302405999, 0.161571682926,
                        0.058893609322, 0.002110822624, 0.049991395337, 0.069917060527,
                        0.023410162726, 0.137499805302, 0.192304738544, 0.064388937241],
       'support_min': -1,
       'support_max': 14},
      {'probs': [0.189407639329, 0.465842288407, 0.464600495683, 0.167572368848,
                 0.500346042564],
       'weights_success': [-2, -5, 0, -3, -5],
       'weights_failure': [-1, 3, -3, -4, 0],
       'expected_pmf': [0.019675751245, 0.088165540571, 0.016950880411, 0.017073911551,
                        0.076506895358, 0.034357901819, 0.088043588853, 0.016927433733,
                        0.039611480145, 0.177496021184, 0.034125734487, 0.019577787911,
                        0.087726574342, 0.039396462424, 0.100955115309, 0.01940982923,
                        0.019550707661, 0.087605229807, 0.01684315396],
       'support_min': -19,
       'support_max': -1},
      {'probs': [0.601088857505, 0.656960213747, 0.757768453998, 0.90476171089,
                 0.080320117922, 0.259536972161],
       'weights_success': [-3, 4, 0, 2, 5, -3],
       'weights_failure': [3, -2, -4, 1, -2, -4],
       'expected_pmf': [0.003239407039, 0.031909730274, 0.010786585861, 0.,
                        0.010133776976, 0.09982261756, 0.042097134051, 0.082570490642,
                        0.03060286213, 0.000942045015, 0.02613259187, 0.258303734886,
                        0.099851524683, 0.044232555402, 0.020895899383, 0.002429309226,
                        0.01287963062, 0.129152893919, 0.065368254595, 0.007959134489,
                        0.003541953456, 0.001197302038, 0., 0.001124840796,
                        0.011080227324, 0.003745497764],
       'support_min': -14,
       'support_max': 11},
      {'probs': [0.801468861204, 0.471528719451, 0.545236373883, 0.72945643724,
                 0.522332834776, 0.076698437214],
       'weights_success': [4, 1, 5, 5, 4, 5],
       'weights_failure': [3, 2, -1, -1, 0, -4],
       'expected_pmf': [0.005079590105, 0.026199280329, 0.022982640819, 0.,
                        0.005554572079, 0.028649120893, 0.044917754807, 0.102051619119,
                        0.08952214251, 0.00042196032, 0.023812575701, 0.113503417547,
                        0.114313807204, 0.085155021776, 0.0766751491, 0.003731307014,
                        0.02643349699, 0.100049711489, 0.081242471071, 0.001797314544,
                        0.009270107748, 0.00949602028, 0.007035477241, 0.006171690382,
                        0., 0.001491608355, 0.00769335018, 0.006748792396],
       'support_min': -2,
       'support_max': 25},
      {'probs': [0.146182881604, 0.09050716845, 0.753136701053, 0.60646945864,
                 0.961853722315, 0.385410716736],
       'weights_success': [-4, 3, 5, -2, -1, -1],
       'weights_failure': [-3, 2, -2, 0, -3, 0],
       'expected_pmf': [0.000292642376, 0.002205029518, 0.010510995798, 0.057301603743,
                        0.080883493419, 0.043093095474, 0.048138545686, 0.005330693583,
                        0.006727158974, 0.032067207779, 0.174817159909, 0.246761376289,
                        0.131469488991, 0.146862274167, 0.013539234294],
       'support_min': -10,
       'support_max': 4},
      {'probs': [0.210279817264, 0.994006392604, 0.929241686182, 0.231881351444,
                 0.769425009474, 0.314968596393, 0.980123758718],
       'weights_success': [0, 5, -5, -1, -5, 2, 1],
       'weights_failure': [4, 4, 4, 5, -1, 3, -1],
       'expected_pmf': [1.308121860349e-06, 2.197897822037e-04, 5.363425689528e-04,
                        1.083812499566e-02, 2.327222878528e-02, 8.913003074581e-04,
                        2.179331037047e-03, 4.467926228409e-02, 9.613109405468e-02,
                        3.614929395802e-02, 7.771078572189e-02, 1.519095457856e-02,
                        3.421555163363e-02, 1.473626483084e-01, 3.126216755964e-01,
                        9.853396361225e-04, 5.401682922157e-03, 4.772531323669e-02,
                        8.949334387160e-02, 5.916114204921e-03, 1.153625092630e-03,
                        2.542545319753e-03, 1.108618164685e-02, 2.379981510262e-02,
                        6.239364004564e-05, 1.522562370865e-04, 3.076712952572e-03,
                        6.604984402794e-03],
       'support_min': -6,
       'support_max': 21},
      {'probs': [0.326375653388, 0.085260427559, 0.119278563709, 0.364016002712,
                 0.433079299254, 0.512031609418, 0.103455838076],
       'weights_success': [3, -3, -2, -5, -2, 0, -1],
       'weights_failure': [-1, 0, 4, 0, 0, -1, -4],
       'expected_pmf': [0.000472475139, 0.000495774338, 0.000618491665, 0.005772589596,
                        0.005605176032, 0.007772707979, 0.012277189131, 0.008151899494,
                        0.018022804485, 0.056469335349, 0.057218127012, 0.071530441521,
                        0.071222231413, 0.039440160076, 0.106436996147, 0.108688237908,
                        0.117411394614, 0.10504546968, 0.047418029323, 0.046355713039,
                        0.05228613129, 0.047644337741, 0.00383635844, 0.004785959129,
                        0.005021969461],
       'support_min': -18,
       'support_max': 6},
      {'probs': [0.945072094414, 0.678922235785, 0.912975147168, 0.073806163824,
                 0.550375003375, 0.885923039772, 0.144045195947],
       'weights_success': [-2, -2, 5, 2, -3, -2, 0],
       'weights_failure': [-1, -4, -5, -2, 3, 5, -5],
       'expected_pmf': [1.020765269170e-02, 5.932721816896e-04, 2.158418663621e-02,
                        1.254480131958e-03, 8.134233433603e-04, 1.765081307669e-03,
                        1.015890165278e-02, 5.531352973002e-03, 1.792055463891e-02,
                        3.941040592549e-03, 1.079221924257e-01, 8.060163628797e-03,
                        2.281698654518e-01, 1.751789923838e-02, 9.249067120549e-03,
                        2.092697024880e-02, 1.067328263012e-01, 5.835231665170e-02,
                        1.882406986101e-01, 4.153894261632e-02, 9.142202059815e-03,
                        1.928533706164e-02, 1.817221656044e-02, 4.571193980889e-02,
                        7.536391465141e-03, 2.528033605831e-02, 1.637542840003e-03,
                        3.389179777453e-03, 2.483128539364e-03, 2.031080965161e-03,
                        4.118924833056e-03, 2.329813087823e-04, 1.510685026429e-04,
                        8.780151799290e-06, 3.194359030798e-04, 1.856572131262e-05],
       'support_min': -23,
       'support_max': 12},
      {'probs': [0.254364658621, 0.638047269328, 0.671758231288, 0.269385558316,
                 0.124581255046, 0.419765564085, 0.510285394635, 0.81258163899],
       'weights_success': [0, 1, 2, 2, 3, -3, -2, 2],
       'weights_failure': [-1, -2, -2, -5, 5, -1, 0, -1],
       'expected_pmf': [3.237018800148e-04, 1.104270594962e-04, 3.032717452970e-03,
                        3.008654766069e-03, 7.092395898886e-03, 2.068462322185e-02,
                        1.800729030005e-02, 4.325568975952e-02, 4.835431087824e-02,
                        6.929615896616e-02, 7.553347688655e-02, 9.330264121164e-02,
                        1.026332772698e-01, 6.834829683263e-02, 1.187914164646e-01,
                        4.852966603784e-02, 7.233448415261e-02, 4.354153535384e-02,
                        3.343751173015e-02, 3.502998648135e-02, 2.275271560527e-02,
                        3.793540898177e-02, 1.132529423428e-02, 1.740187513746e-02,
                        5.936443436973e-03],
       'support_min': -13,
       'support_max': 11},
      {'probs': [0.384564986802, 0.587323662859, 0.624356974942, 0.205371286731,
                 0.11353938685, 0.866503006018, 0.842901273255, 0.732825631914],
       'weights_success': [2, 2, 4, 2, -2, -1, 1, -4],
       'weights_failure': [-5, 1, -1, 5, 1, 3, 2, 0],
       'expected_pmf': [0.001190695741, 0.001916526128, 0.000315838223, 0.013903451909,
                        0.022996337685, 0.006661017402, 0.039319086724, 0.066376421739,
                        0.045521238864, 0.04044000593, 0.035143013836, 0.105236088722,
                        0.118582925639, 0.06003735752, 0.046389995954, 0.061985318954,
                        0.07688936906, 0.026845120605, 0.057123734095, 0.074855779496,
                        0.027568000864, 0.004251584843, 0.02142601619, 0.032332532328,
                        0.006444963074, 0.000215143018, 0.002098354985, 0.003377480926,
                        0.000556599546],
       'support_min': -9,
       'support_max': 19},
      {'probs': [0.199662259919, 0.219461356704, 0.770226667415, 0.926773760311,
                 0.359931675808, 0.769110399704, 0.076349091369, 0.704450031231],
       'weights_success': [-2, 0, 4, -3, 1, -2, 1, 0],
       'weights_failure': [-1, 2, -4, 4, -2, 3, -5, 5],
       'expected_pmf': [2.988824868374e-03, 1.198057831069e-02, 1.063008696770e-02,
                        4.429097034195e-02, 6.737077067444e-03, 8.128859300869e-03,
                        3.283124595587e-02, 8.877480022074e-03, 4.372262927477e-02,
                        4.951029402830e-02, 4.436853935659e-02, 1.684276816953e-01,
                        2.725800231370e-02, 3.605379303406e-02, 1.142204930032e-01,
                        3.350024386493e-02, 1.170558831206e-01, 3.330630820308e-02,
                        3.092724128001e-02, 6.768541268441e-02, 1.623048261031e-02,
                        2.985258805972e-02, 1.430678903079e-02, 1.281231693358e-02,
                        1.378923906191e-02, 6.592223911046e-03, 5.552778039210e-03,
                        2.619221934551e-03, 1.885024723400e-03, 1.150982494887e-03,
                        1.141783878394e-03, 9.017466521151e-04, 4.106058890306e-04,
                        2.931171122619e-05, 1.221292108462e-04, 1.857701240917e-05,
                        1.648294868482e-05, 6.607120397018e-05],
       'support_min': -18,
       'support_max': 19},
      {'probs': [0.11277054844, 0.009966664543, 0.873282204486, 0.29327841012,
                 0.687654060643, 0.114404572973, 0.060149148436, 0.152686585184,
                 0.611024905153],
       'weights_success': [0, 3, 1, 5, 4, -5, -5, 1, 2],
       'weights_failure': [-2, -2, -5, -1, 2, -1, 4, 0, 1],
       'expected_pmf': [5.572452114796e-05, 9.757695315539e-05, 1.455386607395e-04,
                        2.272257444511e-04, 4.836843498346e-04, 7.832002611521e-04,
                        1.539151111561e-03, 2.473348524871e-03, 1.470720837730e-03,
                        2.747181858031e-03, 5.100777358798e-03, 8.007957625061e-03,
                        1.199853551496e-02, 2.070328715571e-02, 1.563234692714e-02,
                        2.627986550326e-02, 4.033741243671e-02, 2.530356733156e-02,
                        3.268720159141e-02, 6.094217800504e-02, 9.077409764452e-02,
                        1.326246624736e-01, 2.055240088349e-01, 5.307398174408e-02,
                        3.489682193835e-02, 2.642633800669e-02, 3.630461189071e-02,
                        5.260780169672e-02, 7.913193832657e-02, 1.844548655900e-02,
                        9.702064653777e-03, 1.878956741370e-03, 5.087996554440e-04,
                        7.912755212722e-04, 1.822161089164e-04, 9.508485295855e-05,
                        1.537107877165e-05],
       'support_min': -17,
       'support_max': 19},
      {'probs': [0.854928485082, 0.418062156958, 0.844263648992, 0.617549957794,
                 0.054989530214, 0.530806283871, 0.575657992519, 0.273458429765,
                 0.127129296826],
       'weights_success': [-3, -3, -3, 1, 2, 3, 4, 3, 0],
       'weights_failure': [3, -2, 4, 3, 0, -5, 5, 2, -3],
       'expected_pmf': [3.016369651361e-02, 7.557559720099e-02, 7.555873672642e-02,
                        6.724439514660e-02, 4.943963912955e-02, 2.162061041939e-02,
                        1.625885696577e-02, 2.440572674366e-02, 6.243324755136e-02,
                        1.111376632934e-01, 1.063354538761e-01, 8.886325752827e-02,
                        6.181047563664e-02, 2.847998110403e-02, 2.213186618302e-02,
                        3.030998475248e-02, 3.419453494096e-02, 3.056325162614e-02,
                        2.426996116913e-02, 1.481666616922e-02, 6.838935850445e-03,
                        4.596560106340e-03, 4.237873648602e-03, 3.055787225178e-03,
                        2.453360345913e-03, 1.763506822896e-03, 7.656249591266e-04,
                        3.945026247257e-04, 2.130834454768e-04, 5.475185216364e-05,
                        1.024526989717e-05, 2.165172518977e-06],
       'support_min': -10,
       'support_max': 21},
      {'probs': [0.270741737521, 0.471458708436, 0.344663493456, 0.566721995399,
                 0.35838435237, 0.245541024187, 0.464459036199, 0.318209920094,
                 0.572395472529],
       'weights_success': [1, 5, -2, 3, 4, 1, 3, -4, 1],
       'weights_failure': [4, -2, 5, -2, 5, -4, -2, -5, -2],
       'expected_pmf': [0.000902124337, 0.002036119451, 0.000753798629, 0.003637515378,
                        0.008209972293, 0.005295393619, 0.008344464323, 0.011746483431,
                        0.017501942586, 0.022636413581, 0.019423733425, 0.034818874331,
                        0.034539695111, 0.036807455019, 0.042428598618, 0.04238780499,
                        0.06537297743, 0.045847439952, 0.053474724894, 0.067174857178,
                        0.052980178251, 0.059100367153, 0.039320026205, 0.054663544162,
                        0.054268825818, 0.037896350746, 0.041959404026, 0.026027868663,
                        0.02900765291, 0.017633138274, 0.014241416834, 0.023411441337,
                        0.010770131044, 0.005140697964, 0.001903155081, 0.002036698942,
                        0.004596885551, 0.001701828459],
       'support_min': -14,
       'support_max': 23},
      {'probs': [0.578279555052, 0.847478008353, 0.284582792497, 0.297042203237,
                 0.057057624629, 0.859341234495, 0.090076192899, 0.987857982456,
                 0.063369336133, 0.368202598528],
       'weights_success': [0, 5, 3, -3, 1, 2, -1, 3, 3, 4],
       'weights_failure': [2, 2, 1, 1, 4, -2, 1, 2, -4, 3],
       'expected_pmf': [9.735884649100e-08, 7.977722287262e-06, 5.709456610309e-06,
                        9.172990860132e-05, 2.299651744923e-04, 2.868400806433e-04,
                        2.089670460557e-03, 2.703189564162e-03, 4.538742300837e-03,
                        1.139609595880e-02, 2.277089212593e-02, 2.651539291347e-02,
                        3.029939853699e-02, 8.532004825106e-02, 7.654199725634e-02,
                        1.031743771398e-01, 8.045404778266e-02, 1.559633146423e-01,
                        9.011191928561e-02, 1.300257790364e-01, 7.769537247508e-02,
                        3.620375073197e-02, 2.491925960664e-02, 5.391092010090e-03,
                        1.044775885034e-02, 5.975373636323e-03, 8.658510112077e-03,
                        4.866712935355e-03, 2.099897796522e-03, 1.215086889164e-03],
       'support_min': -1,
       'support_max': 28},
      {'probs': [0.450983678554, 0.721961105534, 0.001285427509, 0.576056222962,
                 0.864428413984, 0.164031798393, 0.824103710654, 0.330477661241,
                 0.9914964356, 0.05115504535],
       'weights_success': [4, 4, 0, 5, 2, -2, -3, -4, -4, 0],
       'weights_failure': [5, 3, 1, 2, -5, 2, 3, 2, 4, -1],
       'expected_pmf': [3.893402859105e-07, 3.040043729266e-04, 1.171346687901e-03,
                        1.019011839073e-03, 4.666188030191e-04, 3.140951281024e-03,
                        7.354416297051e-03, 5.946578604425e-03, 6.929412879024e-03,
                        1.786480659575e-02, 1.460534422859e-02, 1.037471182662e-02,
                        3.649868393370e-02, 5.883793506742e-02, 4.377289516030e-02,
                        5.047998376235e-02, 8.232606136569e-02, 5.394446398176e-02,
                        5.042952826972e-02, 1.073640159144e-01, 7.732780568412e-02,
                        4.105248571158e-02, 1.220555528298e-01, 1.025797442731e-01,
                        1.446302829100e-02, 2.073605980193e-02, 1.494312225337e-02,
                        7.448814442572e-03, 2.302515663823e-02, 1.979375456351e-02,
                        2.027889205621e-03, 8.760653144103e-04, 1.179908659097e-04,
                        1.738860318570e-04, 1.244594155144e-04, 5.599396408912e-05,
                        1.918102228481e-04, 1.667784741041e-04, 8.441805408982e-06],
       'support_min': -10,
       'support_max': 28},
      {'probs': [0.080906042897, 0.570012565104, 0.767988822646, 0.708707060075,
                 0.246928232736, 0.404660582673, 0.816713413393, 0.260741582003,
                 0.829825964377, 0.195882783733],
       'weights_success': [4, -3, -2, 4, -3, 2, 0, 3, 1, 1],
       'weights_failure': [2, -4, -1, 5, -5, -5, -1, -3, 4, 3],
       'expected_pmf': [2.123971019391e-03, 1.379457261209e-02, 3.116964724423e-02,
                        7.327291958592e-02, 1.055799299009e-01, 7.768652164513e-02,
                        6.042718363343e-02, 4.719693425308e-02, 4.025098138070e-02,
                        5.744627210077e-02, 9.129179789925e-02, 1.002434934843e-01,
                        7.410793700375e-02, 5.553247302936e-02, 3.811124140679e-02,
                        2.465969135635e-02, 2.614474880985e-02, 2.857989228929e-02,
                        1.944754830212e-02, 1.449351441523e-02, 9.828166420493e-03,
                        4.766236165470e-03, 2.497120054323e-03, 1.018508002679e-03,
                        2.586200518005e-04, 6.100268430505e-05, 9.075249009343e-06],
       'support_min': -12,
       'support_max': 14}]
  
  
  class NoBool:
      # Mock up of a class that can't be cast to bool
      def __init__(self):
          pass
  
      def __bool__(self):
          raise ValueError("Can't be cast to bool")
  
  
  def test_GPB_two_param():
      for test_case in simple_test_cases:
          probs = np.array(test_case['probs'])
          weights = np.array(test_case['weights'])
          expected = np.array(test_case['expected'])
          random_var = GPB(probs, weights)
          assert np.allclose(random_var.pmf_vec, expected)
  
  
  def test_GPB_three_param():
      for test_case in three_param_test_cases:
          probs = np.array(test_case['probs'])
          weights_success = np.array(test_case['weights_success'])
          weights_failure = np.array(test_case['weights_failure'])
          support_min = np.array(test_case['support_min'])
          support_max = np.array(test_case['support_max'])
          expected = np.array(test_case['expected_pmf'])
          random_var = GPB(probs, weights_success, weights_failure)
          assert np.allclose(random_var.pmf_vec, expected)
          assert support_min == random_var.support_start
          assert support_max == random_var.support_end
  
  
  def test_GPB_invalid_prob_type():
      with pytest.raises(ValueError):
          random_var = GPB('hello world', np.array([1, 2, 3]))
  
  
  def test_GPB_invalid_prob_dims():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([[0.1, 0.2], [0.3, 0.4]]), np.array([1, 2, 3, 4]))
  
  
  def test_GPB_negative_probs():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([-0.1, 0.2, 0.3]), np.array([1, 2, 3]))
  
  
  def test_GPB_probs_greater_than_one():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([1.1, 0.2, 0.3]), np.array([1, 2, 3]))
  
  
  def test_GPB_probs_equal_to_one():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([1.0, 0.2, 0.3]), np.array([1, 2, 3]))
  
  
  def test_GPB_probs_equal_to_zero():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.0, 0.2, 0.3]), np.array([1, 2, 3]))
  
  
  def test_GPB_invalid_weights_type():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3]), 'hello world')
  
  
  def test_GPB_invalid_weights_dims():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3, 0.4]), np.array([[1, 2], [2, 3]]))
  
  
  def test_GPB_no_zero_weights():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3, 0.4]), np.array([[1, 2, 3, 0]]))
  
  
  def test_GPB_probs_weights_different_length():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3, 0.4]), np.array([1, 2, 3]))
  
  
  def test_GPB_invalid_failure_weights_type():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), 'hello world')
  
  
  def test_GPB_invalid_failure_weights_dims():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3, 0.4]), np.array([1, 2, 3, 4]), np.array([[1, 2], [2, 3]]))
  
  
  def test_GPB_success_and_failure_weights_different_length():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3, 0.4]), np.array([1, 2, 3, 4]), np.array([5, 6, 7]))
  
  
  def test_GPB_success_and_failure_weights_same_value():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3, 0.4]), np.array([1, 2, 3, 4]), np.array([-1, 2, -3, 4]))
  
  
  def test_GPB_3_parameter_values():
      probs = np.array([0.1, 0.2, 0.3])
      weights = np.array([1, 2, 3])
      weights_f = np.array([4, 5, 6])
      random_var = GPB(probs, weights, weights_f)
      assert np.allclose(random_var.probs, probs)
      assert np.allclose(random_var.weights, weights)
      assert np.allclose(random_var.failure_weights, weights_f)
  
  
  def test_GPB_2_parameter_values():
      probs = np.array([0.1, 0.2, 0.3])
      weights = np.array([1, 2, 3])
      random_var = GPB(probs, weights)
      assert np.allclose(random_var.probs, probs)
      assert np.allclose(random_var.weights, weights)
      assert np.allclose(random_var.failure_weights, np.zeros(3))
  
  
  def test_GPB_invalid_allow_GPU():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), 'hello world')
  
  
  def test_GPB_allow_GPU_non_bool():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), allow_GPU=NoBool())
  
  
  def test_GPB_prefer_speed_non_bool():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), prefer_speed=NoBool())
  
  
  def test_GPB_allow_GPU_value():
      random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), allow_GPU=True)
      assert random_var.allow_GPU == True
  
  
  def test_GPB_prefer_speed_value():
      random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), prefer_speed=True)
      assert random_var.prefer_speed == True
  
  
  def test_GPB_pass_method_callable_without_probs_arg():
      def callable_without_probs_param(weights):
          pass
  
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), method=callable_without_probs_param)
  
  
  def test_GPB_pass_method_callable_without_weights_arg():
      def callable_without_weights_param(probs):
          pass
  
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), method=callable_without_weights_param)
  
  
  def test_GPB_pass_method():
      random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), method=_GPB_DP_DC_FFT_Combo)
      assert random_var.method is _GPB_DP_DC_FFT_Combo
      assert np.allclose(np.array([0.504, 0.056, 0.126, 0.23, 0.024, 0.054, 0.006]), random_var.pmf_vec)
  
  
  def test_GPB_pass_method_string():
      random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), method='CF')
      assert random_var.method is _GPB_CF
      assert np.allclose(np.array([0.504, 0.056, 0.126, 0.23, 0.024, 0.054, 0.006]), random_var.pmf_vec)
  
  
  def test_GPB_pass_method_string_GPU():
      random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), method='DP_CUDA')
      assert random_var.method is _GPB_DP_CUDA
      assert np.allclose(np.array([0.504, 0.056, 0.126, 0.23, 0.024, 0.054, 0.006]), random_var.pmf_vec)
  
  
  def test_GPB_pass_method_string_invalid():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), method='Unladen Swallow')
  
  
  def test_GPB_method_choose_CPU_for_small():
      random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]))
      assert random_var.method is cpu._GPB_DP_DC_FFT_Combo
  
  
  def test_GPB_method_choose_CPU_accuracy_over_speed():
      random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), prefer_speed=False)
      assert random_var.method is cpu._GPB_DP
  
  
  def test_GPB_method_choose_CPU_when_forced():
      random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([10000, 20000, 30000]), allow_GPU=False)
      assert random_var.method is cpu._GPB_DP_DC_FFT_Combo
  
  
  def test_GPB_method_choose_GPU_when_allowed():
      random_var = GPB([0.1, 0.2, 0.3], [100000, 200000, 300000])
      assert random_var.method is gpu._GPB_Fastest_CUDA
  
  
  def test_GPB_method_choose_GPU_accuracy_over_speed():
      random_var = GPB([0.1, 0.2, 0.3], [100000, 200000, 300000], prefer_speed=False)
      assert random_var.method is gpu._GPB_DP_CUDA
  
  
  def test_GPB_pass_method_invalid():
      with pytest.raises(ValueError):
          random_var = GPB(np.array([0.1, 0.2, 0.3]), np.array([1, 2, 3]), method=123)
  