# HG changeset patch # User jlaskey # Date 1573750208 14400 # Node ID da026c172c1eedd91ff7880668998428d2327763 # Parent effb66aab08b04befa4ca27f9c66ce0ad0eb9f11 add missing files diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/DoubleZigguratTables.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/DoubleZigguratTables.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,532 @@ +// This Java source file is generated automatically by the program `create_ziggurat_tables.c`. + +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +class DoubleZigguratTables { + + // Implementation support for modified-ziggurat implementation of nextExponential() + + // Fraction of the area under the curve that lies outside the layer boxes: 0.0156 + // Fraction of non-box area that lies in the tail of the distribution: 0.0330 + + static final int exponentialNumberOfLayers = 252; + static final int exponentialLayerMask = 0xff; + static final int exponentialAliasMask = 0xff; + static final int exponentialSignCorrectionMask = 0xff; + static final double exponentialX0 = 7.56927469414806264; + static final long exponentialConvexMargin = 853965788476313645L; // unscaled convex margin = 0.0926 + + // exponential_X[i] = length of ziggurat layer i for exponential distribution, scaled by 2**(-63) + static final double[] exponentialX = { // 253 entries, which is exponential_number_of_layers+1 + 8.2066240675348816e-19, 7.3973732351607284e-19, 6.9133313377915293e-19, 6.5647358820964533e-19, + 6.2912539959818508e-19, 6.0657224129604964e-19, 5.8735276103737269e-19, 5.7058850528536941e-19, + 5.5570945691622390e-19, 5.4232438903743953e-19, 5.3015297696508776e-19, 5.1898739257708062e-19, + 5.0866922617998330e-19, 4.9907492938796469e-19, 4.9010625894449536e-19, 4.8168379010649187e-19, + 4.7374238653644714e-19, 4.6622795807196824e-19, 4.5909509017784048e-19, 4.5230527790658154e-19, + 4.4582558816353960e-19, 4.3962763126368381e-19, 4.3368675967106470e-19, 4.2798143618469714e-19, + 4.2249273027064889e-19, 4.1720391253464110e-19, 4.1210012522465616e-19, 4.0716811225869233e-19, + 4.0239599631006903e-19, 3.9777309342877357e-19, 3.9328975785334499e-19, 3.8893725129310323e-19, + 3.8470763218720385e-19, 3.8059366138180143e-19, 3.7658872138544730e-19, 3.7268674692030177e-19, + 3.6888216492248162e-19, 3.6516984248800068e-19, 3.6154504153287473e-19, 3.5800337915318032e-19, + 3.5454079284533432e-19, 3.5115350988784242e-19, 3.4783802030030962e-19, 3.4459105288907336e-19, + 3.4140955396563316e-19, 3.3829066838741162e-19, 3.3523172262289001e-19, 3.3223020958685874e-19, + 3.2928377502804472e-19, 3.2639020528202049e-19, 3.2354741622810815e-19, 3.2075344331080789e-19, + 3.1800643250478609e-19, 3.1530463211820845e-19, 3.1264638534265134e-19, 3.1003012346934211e-19, + 3.0745435970137301e-19, 3.0491768350005559e-19, 3.0241875541094565e-19, 2.9995630232144550e-19, + 2.9752911310742592e-19, 2.9513603463113224e-19, 2.9277596805684267e-19, 2.9044786545442563e-19, + 2.8815072666416712e-19, 2.8588359639906928e-19, 2.8364556156331615e-19, 2.8143574876779799e-19, + 2.7925332202553125e-19, 2.7709748061152879e-19, 2.7496745707320232e-19, 2.7286251537873397e-19, + 2.7078194919206054e-19, 2.6872508026419050e-19, 2.6669125693153442e-19, 2.6467985271278891e-19, + 2.6269026499668434e-19, 2.6072191381359757e-19, 2.5877424068465143e-19, 2.5684670754248168e-19, + 2.5493879571835479e-19, 2.5305000499077481e-19, 2.5117985269112710e-19, 2.4932787286227806e-19, + 2.4749361546638660e-19, 2.4567664563848669e-19, 2.4387654298267842e-19, 2.4209290090801527e-19, + 2.4032532600140538e-19, 2.3857343743505147e-19, 2.3683686640614648e-19, 2.3511525560671253e-19, + 2.3340825872163284e-19, 2.3171553995306794e-19, 2.3003677356958333e-19, 2.2837164347843482e-19, + 2.2671984281957174e-19, 2.2508107358001938e-19, 2.2345504622739592e-19, 2.2184147936140775e-19, + 2.2024009938224424e-19, 2.1865064017486842e-19, 2.1707284280826716e-19, 2.1550645524878675e-19, + 2.1395123208673778e-19, 2.1240693427550640e-19, 2.1087332888245875e-19, 2.0935018885097035e-19, + 2.0783729277295508e-19, 2.0633442467130712e-19, 2.0484137379170616e-19, 2.0335793440326865e-19, + 2.0188390560756090e-19, 2.0041909115551697e-19, 1.9896329927183254e-19, 1.9751634248643090e-19, + 1.9607803747261946e-19, 1.9464820489157862e-19, 1.9322666924284314e-19, 1.9181325872045647e-19, + 1.9040780507449479e-19, 1.8901014347767504e-19, 1.8762011239677479e-19, 1.8623755346860768e-19, + 1.8486231138030984e-19, 1.8349423375370566e-19, 1.8213317103353295e-19, 1.8077897637931708e-19, + 1.7943150556069476e-19, 1.7809061685599652e-19, 1.7675617095390567e-19, 1.7542803085801941e-19, + 1.7410606179414531e-19, 1.7279013112017240e-19, 1.7148010823836362e-19, 1.7017586450992059e-19, + 1.6887727317167824e-19, 1.6758420925479093e-19, 1.6629654950527621e-19, 1.6501417230628659e-19, + 1.6373695760198277e-19, 1.6246478682288560e-19, 1.6119754281258616e-19, 1.5993510975569615e-19, + 1.5867737310692309e-19, 1.5742421952115544e-19, 1.5617553678444595e-19, 1.5493121374578016e-19, + 1.5369114024951992e-19, 1.5245520706841019e-19, 1.5122330583703858e-19, 1.4999532898563561e-19, + 1.4877116967410352e-19, 1.4755072172615974e-19, 1.4633387956347966e-19, 1.4512053813972103e-19, + 1.4391059287430991e-19, 1.4270393958586506e-19, 1.4150047442513381e-19, 1.4030009380730888e-19, + 1.3910269434359025e-19, 1.3790817277185197e-19, 1.3671642588626657e-19, 1.3552735046573446e-19, + 1.3434084320095729e-19, 1.3315680061998685e-19, 1.3197511901207148e-19, 1.3079569434961214e-19, + 1.2961842220802957e-19, 1.2844319768333099e-19, 1.2726991530715219e-19, 1.2609846895903523e-19, + 1.2492875177568625e-19, 1.2376065605693940e-19, 1.2259407316813331e-19, 1.2142889343858445e-19, + 1.2026500605581765e-19, 1.1910229895518744e-19, 1.1794065870449425e-19, 1.1677997038316715e-19, + 1.1562011745554883e-19, 1.1446098163777869e-19, 1.1330244275772562e-19, 1.1214437860737343e-19, + 1.1098666478700728e-19, 1.0982917454048923e-19, 1.0867177858084351e-19, 1.0751434490529747e-19, + 1.0635673859884002e-19, 1.0519882162526621e-19, 1.0404045260457141e-19, 1.0288148657544097e-19, + 1.0172177474144965e-19, 1.0056116419943559e-19, 9.9399497648346677e-20, 9.8236613076667446e-20, + 9.7072343426320094e-20, 9.5906516230690634e-20, 9.4738953224154196e-20, 9.3569469920159036e-20, + 9.2397875154569468e-20, 9.1223970590556472e-20, 9.0047550180852874e-20, 8.8868399582647627e-20, + 8.7686295519767450e-20, 8.6501005086071005e-20, 8.5312284983141187e-20, 8.4119880684385214e-20, + 8.2923525516513420e-20, 8.1722939648034506e-20, 8.0517828972839211e-20, 7.9307883875099226e-20, + 7.8092777859524425e-20, 7.6872166028429042e-20, 7.5645683383965122e-20, 7.4412942930179128e-20, + 7.3173533545093332e-20, 7.1927017587631075e-20, 7.0672928197666785e-20, 6.9410766239500362e-20, + 6.8139996829256425e-20, 6.6860045374610234e-20, 6.5570293040210081e-20, 6.4270071533368528e-20, + 6.2958657080923559e-20, 6.1635263438143136e-20, 6.0299033732151700e-20, 5.8949030892850181e-20, + 5.7584226359885930e-20, 5.6203486669597397e-20, 5.4805557413499315e-20, 5.3389043909003295e-20, + 5.1952387717989917e-20, 5.0493837866338355e-20, 4.9011415222629489e-20, 4.7502867933366117e-20, + 4.5965615001265455e-20, 4.4396673897997565e-20, 4.2792566302148588e-20, 4.1149193273430015e-20, + 3.9461666762606287e-20, 3.7724077131401685e-20, 3.5929164086204360e-20, 3.4067836691100565e-20, + 3.2128447641564046e-20, 3.0095646916399994e-20, 2.7948469455598328e-20, 2.5656913048718645e-20, + 2.3175209756803909e-20, 2.0426695228251291e-20, 1.7261770330213485e-20, 1.3281889259442578e-20, + 0.0000000000000000e+00 }; + + // exponential_Y[i] = value of the exponential distribution function at exponential_X[i], scaled by 2**(-63) + static final double[] exponentialY = { // 253 entries, which is exponential_number_of_layers+1 + 5.5952054951127360e-23, 1.1802509982703313e-22, 1.8444423386735829e-22, 2.5439030466698309e-22, + 3.2737694311509334e-22, 4.0307732132706715e-22, 4.8125478319495115e-22, 5.6172914896583308e-22, + 6.4435820540443526e-22, 7.2902662343463681e-22, 8.1563888456321941e-22, 9.0411453683482223e-22, + 9.9438488486399206e-22, 1.0863906045969114e-21, 1.1800799775461269e-21, 1.2754075534831208e-21, + 1.3723331176377290e-21, 1.4708208794375214e-21, 1.5708388257440445e-21, 1.6723581984374566e-21, + 1.7753530675030514e-21, 1.8797999785104595e-21, 1.9856776587832504e-21, 2.0929667704053244e-21, + 2.2016497009958240e-21, 2.3117103852306179e-21, 2.4231341516125464e-21, 2.5359075901420891e-21, + 2.6500184374170538e-21, 2.7654554763660391e-21, 2.8822084483468604e-21, 3.0002679757547711e-21, + 3.1196254936130377e-21, 3.2402731888801749e-21, 3.3622039464187092e-21, 3.4854113007409036e-21, + 3.6098893927859475e-21, 3.7356329310971768e-21, 3.8626371568620053e-21, 3.9908978123552837e-21, + 4.1204111123918948e-21, 4.2511737184488913e-21, 4.3831827151633737e-21, 4.5164355889510656e-21, + 4.6509302085234806e-21, 4.7866648071096003e-21, 4.9236379662119969e-21, 5.0618486007478993e-21, + 5.2012959454434732e-21, 5.3419795423648946e-21, 5.4838992294830959e-21, 5.6270551301806347e-21, + 5.7714476436191935e-21, 5.9170774358950678e-21, 6.0639454319177027e-21, 6.2120528079531677e-21, + 6.3614009847804375e-21, 6.5119916214136427e-21, 6.6638266093481696e-21, 6.8169080672926277e-21, + 6.9712383363524377e-21, 7.1268199756340822e-21, 7.2836557582420336e-21, 7.4417486676430174e-21, + 7.6011018943746355e-21, 7.7617188330775411e-21, 7.9236030798322572e-21, 8.0867584297834842e-21, + 8.2511888750363333e-21, 8.4168986028103258e-21, 8.5838919938383098e-21, 8.7521736209986459e-21, + 8.9217482481700712e-21, 9.0926208292996504e-21, 9.2647965076751277e-21, 9.4382806153938292e-21, + 9.6130786730210328e-21, 9.7891963894314161e-21, 9.9666396618278840e-21, 1.0145414575932636e-20, + 1.0325527406345955e-20, 1.0506984617068672e-20, 1.0689792862184811e-20, 1.0873958986701341e-20, + 1.1059490027542400e-20, 1.1246393214695825e-20, 1.1434675972510121e-20, 1.1624345921140471e-20, + 1.1815410878142659e-20, 1.2007878860214202e-20, 1.2201758085082226e-20, 1.2397056973538040e-20, + 1.2593784151618565e-20, 1.2791948452935152e-20, 1.2991558921150600e-20, 1.3192624812605428e-20, + 1.3395155599094805e-20, 1.3599160970797774e-20, 1.3804650839360727e-20, 1.4011635341137284e-20, + 1.4220124840587164e-20, 1.4430129933836705e-20, 1.4641661452404201e-20, 1.4854730467093280e-20, + 1.5069348292058084e-20, 1.5285526489044050e-20, 1.5503276871808626e-20, 1.5722611510726402e-20, + 1.5943542737583543e-20, 1.6166083150566702e-20, 1.6390245619451956e-20, 1.6616043290999594e-20, + 1.6843489594561079e-20, 1.7072598247904713e-20, 1.7303383263267072e-20, 1.7535858953637607e-20, + 1.7770039939284241e-20, 1.8005941154528286e-20, 1.8243577854777398e-20, 1.8482965623825808e-20, + 1.8724120381431627e-20, 1.8967058391181452e-20, 1.9211796268653192e-20, 1.9458350989888484e-20, + 1.9706739900186868e-20, 1.9956980723234356e-20, 2.0209091570579904e-20, 2.0463090951473895e-20, + 2.0718997783083593e-20, 2.0976831401101350e-20, 2.1236611570762130e-20, 2.1498358498287976e-20, + 2.1762092842777868e-20, 2.2027835728562592e-20, 2.2295608758045219e-20, 2.2565434025049041e-20, + 2.2837334128696004e-20, 2.3111332187840010e-20, 2.3387451856080863e-20, 2.3665717337386111e-20, + 2.3946153402349610e-20, 2.4228785405117410e-20, 2.4513639301013211e-20, 2.4800741664897764e-20, + 2.5090119710298442e-20, 2.5381801309347597e-20, 2.5675815013570500e-20, 2.5972190075566336e-20, + 2.6270956471628253e-20, 2.6572144925351523e-20, 2.6875786932281841e-20, 2.7181914785659148e-20, + 2.7490561603315974e-20, 2.7801761355793055e-20, 2.8115548895739172e-20, 2.8431959988666534e-20, + 2.8751031345137833e-20, 2.9072800654466307e-20, 2.9397306620015486e-20, 2.9724588996191657e-20, + 3.0054688627228112e-20, 3.0387647487867642e-20, 3.0723508726057078e-20, 3.1062316707775905e-20, + 3.1404117064129991e-20, 3.1748956740850969e-20, 3.2096884050352357e-20, 3.2447948726504914e-20, + 3.2802201982306013e-20, 3.3159696570631373e-20, 3.3520486848272230e-20, 3.3884628843476888e-20, + 3.4252180327233346e-20, 3.4623200888548644e-20, 3.4997752014001677e-20, 3.5375897171869060e-20, + 3.5757701901149035e-20, 3.6143233905835799e-20, 3.6532563154827400e-20, 3.6925761987883572e-20, + 3.7322905228086981e-20, 3.7724070301302117e-20, 3.8129337363171041e-20, 3.8538789434235234e-20, + 3.8952512543827862e-20, 3.9370595883442399e-20, 3.9793131970351439e-20, 4.0220216822325769e-20, + 4.0651950144388133e-20, 4.1088435528630944e-20, 4.1529780668232712e-20, 4.1976097586926582e-20, + 4.2427502885307452e-20, 4.2884118005513604e-20, 4.3346069515987453e-20, 4.3813489418210257e-20, + 4.4286515477520838e-20, 4.4765291580372353e-20, 4.5249968120658306e-20, 4.5740702418054417e-20, + 4.6237659171683015e-20, 4.6741010952818368e-20, 4.7250938740823415e-20, 4.7767632507051219e-20, + 4.8291291852069895e-20, 4.8822126702292804e-20, 4.9360358072933852e-20, 4.9906218905182021e-20, + 5.0459954986625539e-20, 5.1021825965285324e-20, 5.1592106469178258e-20, 5.2171087345169234e-20, + 5.2759077033045284e-20, 5.3356403093325858e-20, 5.3963413910399511e-20, 5.4580480596259246e-20, + 5.5207999124535584e-20, 5.5846392729873830e-20, 5.6496114614193770e-20, 5.7157651009290713e-20, + 5.7831524654956632e-20, 5.8518298763794323e-20, 5.9218581558791713e-20, 5.9933031488338700e-20, + 6.0662363246796887e-20, 6.1407354758435000e-20, 6.2168855320499763e-20, 6.2947795150103727e-20, + 6.3745196643214394e-20, 6.4562187737537985e-20, 6.5400017881889097e-20, 6.6260077263309343e-20, + 6.7143920145146620e-20, 6.8053293447301698e-20, 6.8990172088133000e-20, 6.9956803158564498e-20, + 7.0955761794878430e-20, 7.1990022788945080e-20, 7.3063053739105458e-20, 7.4178938266266893e-20, + 7.5342542134173124e-20, 7.6559742171142969e-20, 7.7837749863412850e-20, 7.9185582674029512e-20, + 8.0614775537353300e-20, 8.2140502769818073e-20, 8.3783445978280519e-20, 8.5573129249678161e-20, + 8.7554459669590100e-20, 8.9802388057706877e-20, 9.2462471421151086e-20, 9.5919641344951721e-20, + 1.0842021724855044e-19 }; + + // alias_threshold[j] is a threshold for the probability mass function that has been + // scaled by (2**64 - 1), translated by -(2**63), and represented as a long value; + // in this way it can be directly compared to a randomly chosen long value. + static final long[] exponentialAliasThreshold = { // 256 entries + 9223372036854775807L, 1623796909450829958L, 2664290944894281002L, 7387971354164055035L, + 6515064486552722205L, 8840508362680707094L, 6099647593382923818L, 7673130333659514446L, + 6220332867583438718L, 5045979640552814279L, 4075305837223956071L, 3258413672162525964L, + 2560664887087763045L, 1957224924672900129L, 1429800935350578000L, 964606309710808688L, + 551043923599587587L, 180827629096889062L, -152619738120023316L, -454588624410291246L, + -729385126147774679L, -980551509819444511L, -1211029700667463575L, -1423284293868546830L, + -1619396356369066372L, -1801135830956194794L, -1970018048575634032L, -2127348289059688469L, + -2274257249303687482L, -2411729520096654942L, -2540626634159182211L, -2661705860113406183L, + -2775635634532464842L, -2883008316030448462L, -2984350790383654449L, -3080133339198118132L, + -3170777096303105047L, -3256660348483802362L, -3338123885075135933L, -3415475560473298752L, + -3488994201966444258L, -3558932970354456420L, -3625522261068040742L, -3688972217741991689L, + -3749474917563779627L, -3807206277531072172L, -3862327722496826830L, -3914987649156779312L, + -3965322714631864882L, -4013458973776911635L, -4059512885612766613L, -4103592206186240662L, + -4145796782586127736L, -4186219260694346585L, -4224945717447274810L, -4262056226866285147L, + -4297625367836519229L, -4331722680528536958L, -4364413077437472159L, -4395757214229421760L, + -4425811824915119137L, -4454630025296932322L, -4482261588141294467L, -4508753193105275908L, + -4534148654077813412L, -4558489126279965349L, -4581813295192216486L, -4604157549138252679L, + -4625556137145250151L, -4646041313519109096L, -4665643470413305673L, -4684391259530342697L, + -4702311703971745066L, -4719430301145102986L, -4735771117539946027L, -4751356876102086987L, + -4766209036859150188L, -4780347871385996716L, -4793792531638885869L, -4806561113635132333L, + -4818670716409312334L, -4830137496634465358L, -4840976719260854030L, -4851202804490332239L, + -4860829371376476047L, -4869869278311650511L, -4878334660640770576L, -4886236965617426832L, + -4893586984900802224L, -4900394884772702384L, -4906670234238884945L, -4912422031164489009L, + -4917658726580135697L, -4922388247283531793L, -4926618016851042065L, -4930354975163351025L, + -4933605596540650674L, -4936375906575303186L, -4938671497741357106L, -4940497543854583186L, + -4941858813449628882L, -4942759682136114354L, -4943204143989086194L, -4943195822025527282L, + -4942737977813222130L, -4941833520255011698L, -4940485013586759090L, -4938694684624342322L, + -4936464429291795314L, -4933795818458824946L, -4930690103114057265L, -4927148218896863345L, + -4923170790008291569L, -4918758132519196401L, -4913910257091661489L, -4908626871126522161L, + -4902907380349538608L, -4896750889844272240L, -4890156204540530416L, -4883121829162570096L, + -4875645967641780528L, -4867726521994909999L, -4859361090668119087L, -4850546966345102383L, + -4841281133215538414L, -4831560263698491374L, -4821380714613452974L, -4810738522790065581L, + -4799629400105481389L, -4788048727936296621L, -4775991551010524588L, -4763452570642113772L, + -4750426137329493931L, -4736906242696388587L, -4722886510751367403L, -4708360188440104938L, + -4693320135461420394L, -4677758813316098089L, -4661668273553495721L, -4645040145179234152L, + -4627865621182771687L, -4610135444140936871L, -4591839890849352486L, -4572968755929944934L, + -4553511334358213029L, -4533456402849109028L, -4512792200036270244L, -4491506405372580067L, + -4469586116675401954L, -4447017826233099938L, -4423787395382284961L, -4399880027458416864L, + -4375280239014124063L, -4349971829190464606L, -4323937847117722654L, -4297160557210942813L, + -4269621402214950684L, -4241300963840750107L, -4212178920821854874L, -4182234004204445017L, + -4151443949668869272L, -4119785446662323159L, -4087234084103169942L, -4053764292396165205L, + -4019349281473092435L, -3983960974549686930L, -3947569937258414993L, -3910145301787337104L, + -3871654685619049615L, -3832064104425389837L, -3791337878631529676L, -3749438533114328651L, + -3706326689447979465L, -3661960950051859912L, -3616297773528542022L, -3569291340409179909L, + -3520893408440947267L, -3471053156460649921L, -3419717015797783872L, -3366828488034801534L, + -3312327947826461820L, -3256152429334023226L, -3198235394669709240L, -3138506482563174262L, + -3076891235255164340L, -3013310801389715890L, -2947681612411392816L, -2879915029671670702L, + -2809916959107519276L, -2737587429961855017L, -2662820133571332903L, -2585501917733374884L, + -2505512231579392929L, -2422722515205190175L, -2336995527534106140L, -2248184604988712345L, + -2156132842510782614L, -2060672187261016979L, -1961622433929380112L, -1858790108950090508L, + -1751967229002904073L, -1640929916937134981L, -1525436855617591297L, -1405227557075245821L, + -1280020420662651897L, -1149510549536605301L, -1013367289578706928L, -871231448632089708L, + -722712146453677415L, -567383236774421729L, -404779231966956764L, -234390647591531478L, + -55658667960121553L, 132030985907831093L, 329355128892817467L, 537061298001091010L, + 755977262693561929L, 987022116608030929L, 1231219266829437401L, 1489711711346524770L, + 1763780090187559275L, 2054864117341782772L, 2364588157623782527L, 2694791916990482441L, + 3047567482883491349L, 3425304305830820514L, 3830744187097285423L, 4267048975685836605L, + 4737884547990014029L, 5247525842199011422L, 5800989391535342064L, 6404202162993303300L, + 7064218894258526746L, 7789505049452354354L, 8590309807749425484L, 7643763810684501605L, + 8891950541491453167L, 5457384281016234818L, 9083704440929285914L, 7976211653914461751L, + 8178631350487124609L, 2821287825726757492L, 6322989683301736617L, 4309503753387630347L, + 4685170734960191673L, 8404845967535252693L, 7330522972447610419L, 1960945799077061994L, + 4742910674644933674L, -751799822533438695L, 7023456603742021660L, 3843116882594755262L, + 3927231442413889375L, -9223372036854775807L, -9223372036854775807L, -9223372036854775807L }; + + static final byte[] exponentialAliasMap = { // 256 entries + (byte) 0, (byte) 0, (byte) 1, (byte)235, (byte) 3, (byte) 4, (byte) 5, (byte) 0, + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, + (byte) 0, (byte) 0, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 2, (byte) 2, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)251, (byte)251, (byte)251, (byte)251, (byte)251, (byte)251, (byte)251, + (byte)251, (byte)251, (byte)251, (byte)251, (byte)251, (byte)251, (byte)250, (byte)250, + (byte)250, (byte)250, (byte)250, (byte)250, (byte)250, (byte)249, (byte)249, (byte)249, + (byte)249, (byte)249, (byte)249, (byte)248, (byte)248, (byte)248, (byte)248, (byte)247, + (byte)247, (byte)247, (byte)247, (byte)246, (byte)246, (byte)246, (byte)245, (byte)245, + (byte)244, (byte)244, (byte)243, (byte)243, (byte)242, (byte)241, (byte)241, (byte)240, + (byte)239, (byte)237, (byte) 3, (byte) 3, (byte) 4, (byte) 4, (byte) 6, (byte) 0, + (byte) 0, (byte) 0, (byte) 0, (byte)236, (byte)237, (byte)238, (byte)239, (byte)240, + (byte)241, (byte)242, (byte)243, (byte)244, (byte)245, (byte)246, (byte)247, (byte)248, + (byte)249, (byte)250, (byte)251, (byte)252, (byte) 2, (byte) 0, (byte) 0, (byte) 0 }; + + // Implementation support for modified-ziggurat implementation of nextGaussian() + + // Fraction of the area under the curve that lies outside the layer boxes: 0.0117 + // Fraction of non-box area that lies in the tail of the distribution: 0.0236 + + static final int normalNumberOfLayers = 253; + static final int normalLayerMask = 0xff; + static final int normalAliasMask = 0xff; + static final int normalSignCorrectionMask = 0xff; + static final double normalX0 = 3.63600662550094578; + static final int normalInflectionIndex = 204; + static final long normalConvexMargin = 760463704284035183L; // unscaled convex margin = 0.0824 + static final long normalConcaveMargin = 2269182951627976012L; // unscaled concave margin = 0.2460 + + // normal_X[i] = length of ziggurat layer i for normal distribution, scaled by 2**(-63) + static final double[] normalX = { // 254 entries, which is normal_number_of_layers+1 + 3.9421662825398133e-19, 3.7204945004119012e-19, 3.5827024480628678e-19, 3.4807476236540249e-19, + 3.3990177171882136e-19, 3.3303778360340139e-19, 3.2709438817617550e-19, 3.2183577132495100e-19, + 3.1710758541840432e-19, 3.1280307407034065e-19, 3.0884520655804019e-19, 3.0517650624107352e-19, + 3.0175290292584600e-19, 2.9853983440705320e-19, 2.9550967462801797e-19, 2.9263997988491663e-19, + 2.8991225869977476e-19, 2.8731108780226291e-19, 2.8482346327101335e-19, 2.8243831535194389e-19, + 2.8014613964727031e-19, 2.7793871261807797e-19, 2.7580886921411212e-19, 2.7375032698308758e-19, + 2.7175754543391047e-19, 2.6982561247538484e-19, 2.6795015188771505e-19, 2.6612724730440033e-19, + 2.6435337927976633e-19, 2.6262537282028438e-19, 2.6094035335224142e-19, 2.5929570954331002e-19, + 2.5768906173214726e-19, 2.5611823497719608e-19, 2.5458123593393361e-19, 2.5307623292372459e-19, + 2.5160153867798400e-19, 2.5015559533646191e-19, 2.4873696135403158e-19, 2.4734430003079206e-19, + 2.4597636942892726e-19, 2.4463201347912450e-19, 2.4331015411139206e-19, 2.4200978427132955e-19, + 2.4072996170445879e-19, 2.3946980340903347e-19, 2.3822848067252674e-19, 2.3700521461931801e-19, + 2.3579927220741330e-19, 2.3460996262069972e-19, 2.3343663401054455e-19, 2.3227867054673840e-19, + 2.3113548974303765e-19, 2.3000654002704238e-19, 2.2889129852797606e-19, 2.2778926905921897e-19, + 2.2669998027527321e-19, 2.2562298398527416e-19, 2.2455785360727260e-19, 2.2350418274933911e-19, + 2.2246158390513294e-19, 2.2142968725296249e-19, 2.2040813954857555e-19, 2.1939660310297601e-19, + 2.1839475483749618e-19, 2.1740228540916853e-19, 2.1641889840016519e-19, 2.1544430956570613e-19, + 2.1447824613540345e-19, 2.1352044616350571e-19, 2.1257065792395107e-19, 2.1162863934653125e-19, + 2.1069415749082026e-19, 2.0976698805483467e-19, 2.0884691491567363e-19, 2.0793372969963634e-19, + 2.0702723137954107e-19, 2.0612722589717129e-19, 2.0523352580895635e-19, 2.0434594995315797e-19, + 2.0346432313698148e-19, 2.0258847584216418e-19, 2.0171824394771313e-19, 2.0085346846857531e-19, + 1.9999399530912015e-19, 1.9913967503040585e-19, 1.9829036263028144e-19, 1.9744591733545175e-19, + 1.9660620240469857e-19, 1.9577108494251485e-19, 1.9494043572246307e-19, 1.9411412901962161e-19, + 1.9329204245152935e-19, 1.9247405682708168e-19, 1.9166005600287074e-19, 1.9084992674649826e-19, + 1.9004355860642340e-19, 1.8924084378793725e-19, 1.8844167703488436e-19, 1.8764595551677749e-19, + 1.8685357872097450e-19, 1.8606444834960934e-19, 1.8527846822098793e-19, 1.8449554417517928e-19, + 1.8371558398354868e-19, 1.8293849726199566e-19, 1.8216419538767393e-19, 1.8139259141898448e-19, + 1.8062360001864453e-19, 1.7985713737964743e-19, 1.7909312115393845e-19, 1.7833147038364200e-19, + 1.7757210543468428e-19, 1.7681494793266395e-19, 1.7605992070083140e-19, 1.7530694770004409e-19, + 1.7455595397057217e-19, 1.7380686557563475e-19, 1.7305960954655264e-19, 1.7231411382940904e-19, + 1.7157030723311378e-19, 1.7082811937877138e-19, 1.7008748065025788e-19, 1.6934832214591352e-19, + 1.6861057563126349e-19, 1.6787417349268046e-19, 1.6713904869190636e-19, 1.6640513472135291e-19, + 1.6567236556010242e-19, 1.6494067563053266e-19, 1.6420999975549115e-19, 1.6348027311594532e-19, + 1.6275143120903661e-19, 1.6202340980646725e-19, 1.6129614491314931e-19, 1.6056957272604589e-19, + 1.5984362959313479e-19, 1.5911825197242491e-19, 1.5839337639095554e-19, 1.5766893940370800e-19, + 1.5694487755235889e-19, 1.5622112732380261e-19, 1.5549762510837070e-19, 1.5477430715767271e-19, + 1.5405110954198330e-19, 1.5332796810709688e-19, 1.5260481843056974e-19, 1.5188159577726683e-19, + 1.5115823505412761e-19, 1.5043467076406199e-19, 1.4971083695888395e-19, 1.4898666719118714e-19, + 1.4826209446506113e-19, 1.4753705118554365e-19, 1.4681146910669830e-19, 1.4608527927820112e-19, + 1.4535841199031451e-19, 1.4463079671711862e-19, 1.4390236205786415e-19, 1.4317303567630177e-19, + 1.4244274423783481e-19, 1.4171141334433217e-19, 1.4097896746642792e-19, 1.4024532987312287e-19, + 1.3951042255849034e-19, 1.3877416616527576e-19, 1.3803647990516385e-19, 1.3729728147547174e-19, + 1.3655648697200824e-19, 1.3581401079782068e-19, 1.3506976556752901e-19, 1.3432366200692418e-19, + 1.3357560884748263e-19, 1.3282551271542047e-19, 1.3207327801488087e-19, 1.3131880680481524e-19, + 1.3056199866908076e-19, 1.2980275057923788e-19, 1.2904095674948608e-19, 1.2827650848312727e-19, + 1.2750929400989213e-19, 1.2673919831340482e-19, 1.2596610294799512e-19, 1.2518988584399374e-19, + 1.2441042110056523e-19, 1.2362757876504165e-19, 1.2284122459762072e-19, 1.2205121982017852e-19, + 1.2125742084782245e-19, 1.2045967900166973e-19, 1.1965784020118020e-19, 1.1885174463419555e-19, + 1.1804122640264091e-19, 1.1722611314162064e-19, 1.1640622560939109e-19, 1.1558137724540874e-19, + 1.1475137369333185e-19, 1.1391601228549047e-19, 1.1307508148492592e-19, 1.1222836028063025e-19, + 1.1137561753107903e-19, 1.1051661125053526e-19, 1.0965108783189755e-19, 1.0877878119905372e-19, + 1.0789941188076655e-19, 1.0701268599703640e-19, 1.0611829414763286e-19, 1.0521591019102928e-19, + 1.0430518990027552e-19, 1.0338576948035472e-19, 1.0245726392923699e-19, 1.0151926522209310e-19, + 1.0057134029488235e-19, 9.9613028799672809e-20, 9.8643840599459914e-20, 9.7663252964755816e-20, + 9.6670707427623454e-20, 9.5665606240866670e-20, 9.4647308380433213e-20, 9.3615125017323508e-20, + 9.2568314370887282e-20, 9.1506075837638774e-20, 9.0427543267725716e-20, 8.9331777233763680e-20, + 8.8217756102327883e-20, 8.7084365674892319e-20, 8.5930387109612162e-20, 8.4754482764244349e-20, + 8.3555179508462343e-20, 8.2330848933585364e-20, 8.1079683729129853e-20, 7.9799669284133864e-20, + 7.8488549286072745e-20, 7.7143783700934692e-20, 7.5762496979467566e-20, 7.4341413578485329e-20, + 7.2876776807378431e-20, 7.1364245443525374e-20, 6.9798760240761066e-20, 6.8174368944799054e-20, + 6.6483992986198539e-20, 6.4719110345162767e-20, 6.2869314813103699e-20, 6.0921687548281263e-20, + 5.8859873575576818e-20, 5.6662675116090981e-20, 5.4301813630894571e-20, 5.1738171744494220e-20, + 4.8915031722398545e-20, 4.5744741890755301e-20, 4.2078802568583416e-20, 3.7625986722404761e-20, + 3.1628589805881879e-20, 0.0000000000000000e+00 }; + + // normal_Y[i] = value of the normal distribution function at normal_X[i], scaled by 2**(-63) + static final double[] normalY = { // 254 entries, which is normal_number_of_layers+1 + 1.4598410796619063e-22, 3.0066613427942797e-22, 4.6129728815103466e-22, 6.2663350049234362e-22, + 7.9594524761881544e-22, 9.6874655021705039e-22, 1.1446877002379439e-21, 1.3235036304379167e-21, + 1.5049857692053131e-21, 1.6889653000719298e-21, 1.8753025382711626e-21, 2.0638798423695191e-21, + 2.2545966913644708e-21, 2.4473661518801799e-21, 2.6421122727763533e-21, 2.8387681187879908e-21, + 3.0372742567457284e-21, 3.2375775699986589e-21, 3.4396303157948780e-21, 3.6433893657997798e-21, + 3.8488155868912312e-21, 4.0558733309492775e-21, 4.2645300104283590e-21, 4.4747557422305067e-21, + 4.6865230465355582e-21, 4.8998065902775257e-21, 5.1145829672105489e-21, 5.3308305082046173e-21, + 5.5485291167031758e-21, 5.7676601252690476e-21, 5.9882061699178461e-21, 6.2101510795442221e-21, + 6.4334797782257209e-21, 6.6581781985713897e-21, 6.8842332045893181e-21, 7.1116325227957095e-21, + 7.3403646804903092e-21, 7.5704189502886418e-21, 7.8017853001379744e-21, 8.0344543481570017e-21, + 8.2684173217333118e-21, 8.5036660203915022e-21, 8.7401927820109521e-21, 8.9779904520281901e-21, + 9.2170523553061439e-21, 9.4573722703928820e-21, 9.6989444059269430e-21, 9.9417633789758424e-21, + 1.0185824195119818e-20, 1.0431122230114770e-20, 1.0677653212987396e-20, 1.0925413210432004e-20, + 1.1174398612392891e-20, 1.1424606118728715e-20, 1.1676032726866302e-20, 1.1928675720361027e-20, + 1.2182532658289373e-20, 1.2437601365406785e-20, 1.2693879923010674e-20, 1.2951366660454145e-20, + 1.3210060147261461e-20, 1.3469959185800733e-20, 1.3731062804473644e-20, 1.3993370251385596e-20, + 1.4256880988463136e-20, 1.4521594685988369e-20, 1.4787511217522902e-20, 1.5054630655196170e-20, + 1.5322953265335218e-20, 1.5592479504415048e-20, 1.5863210015310328e-20, 1.6135145623830982e-20, + 1.6408287335525592e-20, 1.6682636332737932e-20, 1.6958193971903124e-20, 1.7234961781071113e-20, + 1.7512941457646084e-20, 1.7792134866331487e-20, 1.8072544037271070e-20, 1.8354171164377277e-20, + 1.8637018603838945e-20, 1.8921088872801004e-20, 1.9206384648209468e-20, 1.9492908765815636e-20, + 1.9780664219333857e-20, 2.0069654159747839e-20, 2.0359881894760859e-20, 2.0651350888385696e-20, + 2.0944064760670539e-20, 2.1238027287557466e-20, 2.1533242400870487e-20, 2.1829714188430474e-20, + 2.2127446894294597e-20, 2.2426444919118270e-20, 2.2726712820637798e-20, 2.3028255314272276e-20, + 2.3331077273843558e-20, 2.3635183732413286e-20, 2.3940579883236352e-20, 2.4247271080830277e-20, + 2.4555262842160330e-20, 2.4864560847940368e-20, 2.5175170944049622e-20, 2.5487099143065929e-20, + 2.5800351625915997e-20, 2.6114934743643687e-20, 2.6430855019297323e-20, 2.6748119149937411e-20, + 2.7066734008766247e-20, 2.7386706647381193e-20, 2.7708044298153558e-20, 2.8030754376735269e-20, + 2.8354844484695747e-20, 2.8680322412291631e-20, 2.9007196141372126e-20, 2.9335473848423219e-20, + 2.9665163907753988e-20, 2.9996274894828624e-20, 3.0328815589748056e-20, 3.0662794980885287e-20, + 3.0998222268678760e-20, 3.1335106869588609e-20, 3.1673458420220558e-20, 3.2013286781622988e-20, + 3.2354602043762612e-20, 3.2697414530184806e-20, 3.3041734802864950e-20, 3.3387573667257349e-20, + 3.3734942177548938e-20, 3.4083851642125208e-20, 3.4434313629256243e-20, 3.4786339973011376e-20, + 3.5139942779411164e-20, 3.5495134432826171e-20, 3.5851927602632460e-20, 3.6210335250134172e-20, + 3.6570370635764384e-20, 3.6932047326575882e-20, 3.7295379204034252e-20, 3.7660380472126401e-20, + 3.8027065665798284e-20, 3.8395449659736649e-20, 3.8765547677510167e-20, 3.9137375301086406e-20, + 3.9510948480742172e-20, 3.9886283545385430e-20, 4.0263397213308566e-20, 4.0642306603393541e-20, + 4.1023029246790967e-20, 4.1405583099096438e-20, 4.1789986553048817e-20, 4.2176258451776819e-20, + 4.2564418102621759e-20, 4.2954485291566197e-20, 4.3346480298300118e-20, 4.3740423911958146e-20, + 4.4136337447563716e-20, 4.4534242763218286e-20, 4.4934162278076256e-20, 4.5336118991149025e-20, + 4.5740136500984466e-20, 4.6146239026271279e-20, 4.6554451427421133e-20, 4.6964799229185088e-20, + 4.7377308644364938e-20, 4.7792006598684169e-20, 4.8208920756888113e-20, 4.8628079550147814e-20, + 4.9049512204847653e-20, 4.9473248772842596e-20, 4.9899320163277674e-20, 5.0327758176068971e-20, + 5.0758595537153414e-20, 5.1191865935622696e-20, 5.1627604062866059e-20, 5.2065845653856416e-20, + 5.2506627530725194e-20, 5.2949987648783448e-20, 5.3395965145159426e-20, 5.3844600390237576e-20, + 5.4295935042099358e-20, 5.4750012104183868e-20, 5.5206875986405073e-20, 5.5666572569983821e-20, + 5.6129149276275792e-20, 5.6594655139902476e-20, 5.7063140886520563e-20, 5.7534659015596918e-20, + 5.8009263888591218e-20, 5.8487011822987583e-20, 5.8967961192659803e-20, 5.9452172535103471e-20, + 5.9939708666122605e-20, 6.0430634802618929e-20, 6.0925018694200531e-20, 6.1422930764402860e-20, + 6.1924444262401531e-20, 6.2429635426193939e-20, 6.2938583658336214e-20, 6.3451371715447563e-20, + 6.3968085912834963e-20, 6.4488816345752736e-20, 6.5013657128995346e-20, 6.5542706656731714e-20, + 6.6076067884730717e-20, 6.6613848637404196e-20, 6.7156161942412980e-20, 6.7703126395950580e-20, + 6.8254866562246408e-20, 6.8811513411327825e-20, 6.9373204799659681e-20, 6.9940085998959109e-20, + 7.0512310279279503e-20, 7.1090039553397167e-20, 7.1673445090644796e-20, 7.2262708309655784e-20, + 7.2858021661057338e-20, 7.3459589613035800e-20, 7.4067629754967553e-20, 7.4682374037052817e-20, + 7.5304070167226666e-20, 7.5932983190698547e-20, 7.6569397282483754e-20, 7.7213617789487678e-20, + 7.7865973566417016e-20, 7.8526819659456755e-20, 7.9196540403850560e-20, 7.9875553017037968e-20, + 8.0564311788901630e-20, 8.1263312996426176e-20, 8.1973100703706304e-20, 8.2694273652634034e-20, + 8.3427493508836792e-20, 8.4173494807453416e-20, 8.4933097052832066e-20, 8.5707219578230905e-20, + 8.6496899985930695e-20, 8.7303317295655327e-20, 8.8127821378859504e-20, 8.8971970928196666e-20, + 8.9837583239314064e-20, 9.0726800697869543e-20, 9.1642181484063544e-20, 9.2586826406702765e-20, + 9.3564561480278864e-20, 9.4580210012636175e-20, 9.5640015550850358e-20, 9.6752334770503130e-20, + 9.7928851697808831e-20, 9.9186905857531331e-20, 1.0055456271343397e-19, 1.0208407377305566e-19, + 1.0390360993240711e-19, 1.0842021724855044e-19 }; + + // alias_threshold[j] is a threshold for the probability mass function that has been + // scaled by (2**64 - 1), translated by -(2**63), and represented as a long value; + // in this way it can be directly compared to a randomly chosen long value. + static final long[] normalAliasThreshold = { // 256 entries + 9223372036854775732L, 1100243796470199922L, 7866600928967318259L, 6788754710669718688L, + 9022865200207136940L, 6522434035182564354L, 4723064097388367094L, 3360495653202227820L, + 2289663232347306830L, 1423968905585875379L, 708364817795238883L, 106102487338962592L, + -408333464668584328L, -853239722790494085L, -1242095211827090004L, -1585059631108655444L, + -1889943050267333598L, -2162852901996526266L, -2408637386596951353L, -2631196530256993348L, + -2833704942542501760L, -3018774289008775598L, -3188573753501888049L, -3344920681670389334L, + -3489349705095933019L, -3623166100045386711L, -3747487436861293578L, -3863276422709141026L, + -3971367044055496571L, -4072485557008423504L, -4167267476835653997L, -4256271432259158584L, + -4339990541931699221L, -4418861817116128356L, -4493273980399812066L, -4563574004455583972L, + -4630072609765608272L, -4693048910437239656L, -4752754358851355990L, -4809416110064308151L, + -4863239903553549801L, -4914412541525462120L, -4963104028438393907L, -5009469424783376781L, + -5053650458852410933L, -5095776932714599237L, -5135967952538787362L, -5174333008440005397L, + -5210972924976812191L, -5245980700089102084L, -5279442247516610920L, -5311437055455710870L, + -5342038772315685218L, -5371315728848281940L, -5399331404596850615L, -5426144845492958401L, + -5451811038482575296L, -5476381248268660540L, -5499903320574200237L, -5522421955754019296L, + -5543978956088644891L, -5564613449670076120L, -5584362093426489951L, -5603259257517942559L, + -5621337193067953247L, -5638626184957155131L, -5655154691206501482L, -5670949470299055313L, + -5686035697633988263L, -5700437072176015065L, -5714175914241450413L, -5727273255262198220L, + -5739748920276454057L, -5751621603817308582L, -5762908939796390234L, -5773627565922293024L, + -5783793183134813122L, -5793420610488485693L, -5802523835876777512L, -5811116062947540603L, + -5819209754528321254L, -5826816672847738703L, -5833947916812588598L, -5840613956576464230L, + -5846824665611918318L, -5852589350480860931L, -5857916778478181241L, -5862815203308620040L, + -5867292388942958035L, -5871355631785040459L, -5875011781271709877L, -5878267259014830525L, + -5881128076587168793L, -5883599852042383670L, -5885687825255517495L, -5887396872158140520L, + -5888731517940791413L, -5889695949285098191L, -5890294025685452079L, -5890529289913339019L, + -5890404977673728891L, -5889924026498433105L, -5889089083917111413L, -5887902514943630556L, + -5886366408911444323L, -5884482585689698188L, -5882252601307215732L, -5879677753010810505L, + -5876759083779777633L, -5873497386319005871L, -5869893206546653493L, -5865946846595933526L, + -5861658367342436656L, -5857027590471882377L, -5852054100098427498L, -5846737243942430862L, + -5841076134076202917L, -5835069647242632620L, -5828716424752710909L, -5822014871963881822L, + -5814963157341321336L, -5807559211102860368L, -5799800723445392235L, -5791685142351319976L, + -5783209670970726741L, -5774371264573181466L, -5765166627063894671L, -5755592207054728713L, + -5745644193480823967L, -5735318510752045177L, -5724610813425415465L, -5713516480385581414L, + -5702030608515423737L, -5690148005840583288L, -5677863184127162093L, -5665170350911168791L, + -5652063400935782694L, -5638535906971010691L, -5624581109986711207L, -5610191908648783765L, + -5595360848105231304L, -5580080108024969737L, -5564341489852042876L, -5548136403231016978L, + -5531455851558564459L, -5514290416611714856L, -5496630242199355791L, -5478465016777918644L, + -5459783954970839371L, -5440575777921757436L, -5420828692410297267L, -5400530368650229789L, + -5379667916685479525L, -5358227861290596404L, -5336196115276119372L, -5313557951090901350L, + -5290297970603367798L, -5266400072934326313L, -5241847420204395031L, -5216622401044877639L, + -5190706591710560934L, -5164080714616987256L, -5136724594109421094L, -5108617109256031912L, + -5079736143434386281L, -5050058530465123570L, -5019559997019987907L, -4988215101007960589L, + -4955997165616088151L, -4922878208649305943L, -4888828866781574127L, -4853818314291958392L, + -4817814175818125756L, -4780782432613346925L, -4742687321741700014L, -4703491227589533028L, + -4663154565006030194L, -4621635653315226847L, -4578890580363657638L, -4534873055674290590L, + -4489534251682380820L, -4442822631912146606L, -4394683764829968681L, -4345060121963632469L, + -4293890858720706245L, -4241111576152819891L, -4186654061709945180L, -4130446006793453666L, + -4072410698652140640L, -4012466683862855933L, -3950527400292573339L, -3886500774045756804L, + -3820288777448438119L, -3751786943603804843L, -3680883832458819395L, -3607460442634330728L, + -3531389562479403081L, -3452535052892669800L, -3370751053387208615L, -3285881101636362572L, + -3197757155290696249L, -3106198503163967069L, -3011010550898974052L, -2911983463889090176L, + -2808890647471134035L, -2701487041141521265L, -2589507199668960785L, -2472663129352313038L, + -2350641842148622058L, -2223102583752258356L, -2089673683718520949L, -1949948966041670625L, + -1803483646850545328L, -1649789631543398131L, -1488330106106063370L, -1318513295716695859L, + -1139685236949889721L, -951121376566993538L, -752016768187462359L, -541474585679321485L, + -318492605702529265L, -81947227237782935L, 169425512586600501L, 437052607251310002L, + 722551297576808029L, 1027761939321803391L, 1354787941562529921L, 1706044619231670700L, + 2084319374410687061L, 2492846399585974279L, 2935400169364870493L, 3416413484632185639L, + 3941127949845221101L, 4515787798750242711L, 5147892401460631081L, 5846529325404347588L, + 6622819682189677227L, 7490522659877439279L, 8466869998300400224L, 8216968526327386835L, + 4550693915429835301L, 7628019504075715697L, 6605080500885794707L, 7121156327618549405L, + 2484871780310660533L, 7179104797025802172L, 7066086283790288107L, 1516500120772178463L, + 216305945406470492L, 6295963418490399062L, 2889316805640753770L, -2712587580563247199L, + 6562498853480442900L, 7975754821117214681L, -9223372036854775807L, -9223372036854775807L }; + + static final byte[] normalAliasMap = { // 256 entries + (byte) 0, (byte) 0, (byte)239, (byte) 2, (byte) 0, (byte) 0, (byte) 0, (byte) 0, + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 1, (byte) 1, (byte) 1, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, + (byte)253, (byte)253, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, + (byte)252, (byte)252, (byte)252, (byte)252, (byte)251, (byte)251, (byte)251, (byte)251, + (byte)251, (byte)251, (byte)251, (byte)250, (byte)250, (byte)250, (byte)250, (byte)250, + (byte)249, (byte)249, (byte)249, (byte)248, (byte)248, (byte)248, (byte)247, (byte)247, + (byte)247, (byte)246, (byte)246, (byte)245, (byte)244, (byte)244, (byte)243, (byte)242, + (byte)240, (byte) 2, (byte) 2, (byte) 3, (byte) 3, (byte) 0, (byte) 0, (byte)240, + (byte)241, (byte)242, (byte)243, (byte)244, (byte)245, (byte)246, (byte)247, (byte)248, + (byte)249, (byte)250, (byte)251, (byte)252, (byte)253, (byte) 1, (byte) 0, (byte) 0 }; + +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/L128X1024MixRandom.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/L128X1024MixRandom.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.SplittableGenerator; +import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link L128X1024MixRandom} implements + * interfaces {@link RandomGenerator} and {@link SplittableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new split-off {@link L128X1024MixRandom} objects, + * with similar usages as for class {@link java.util.SplittableRandom}. + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + * (Most recently validated with + * version 1.2.3 of TestU01 + * and version 0.90 of PractRand. + * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()} + * method but also the result of bit-reversing each value produced by {@code nextLong()}.) + * These tests validate only the methods for certain + * types and ranges, but similar properties are expected to hold, at + * least approximately, for others as well. + *

+ * {@link L128X1024MixRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is + * an Xorshift generator. Each output of an LXM generator is the result of + * combining state from the LCG with state from the Xorshift generator by + * using a Mixing function (and then the state of the LCG and the state of the + * Xorshift generator are advanced). + *

+ * The LCG subgenerator for {@link L128X256MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all + * 128-bit integers; {@code s} is the mutable state, the multiplier {@code m} + * is fixed (the same for all instances of {@link L128X256MixRandom}) and the addend + * {@code a} is a parameter (a final field of the instance). The parameter + * {@code a} is required to be odd (this allows the LCG to have the maximal + * period, namely 2128); therefore there are 2127 distinct choices + * of parameter. + *

+ * The Xorshift subgenerator for {@link L128X1024MixRandom} is the {@code xoroshiro1024} + * algorithm (parameters 25, 27, and 36), without any final scrambler such as "+" or "**". + * Its state consists of an array {@code x} of sixteen {@code long} values, + * which can take on any values provided that they are not all zero. + * The period of this subgenerator is 21024-1. + *

+ * The mixing function for {@link L128X1024MixRandom} is {@link RandomSupport.mixLea64} + * applied to the argument {@code (sh + s0)}, where {@code sh} is the high half of {@code s} + * and {@code s0} is the most recently computed element of {@code x}. + *

+ * Because the periods 2128 and 21024-1 of the two subgenerators + * are relatively prime, the period of any single {@link L128X1024MixRandom} object + * (the length of the series of generated 64-bit values before it repeats) is the product + * of the periods of the subgenerators, that is, 2128(21024-1), + * which is just slightly smaller than 21152. Moreover, if two distinct + * {@link L128X1024MixRandom} objects have different {@code a} parameters, then their + * cycles of produced values will be different. + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L128X1024MixRandom}, over the course of its cycle each + * of the 264 possible {@code long} values will be produced + * 264(21024-1 times. The values produced by the {@code nextInt()}, + * {@code nextFloat()}, and {@code nextDouble()} methods are likewise exactly equidistributed. + *

+ * Moreover, 64-bit values produced by the {@code nextLong()} method are conjectured to be + * "very nearly" 16-equidistributed: all possible 16-tuples of 64-bit values are generated, + * and some pairs occur more often than others, but only very slightly more often. + * However, this conjecture has not yet been proven mathematically. + * If this conjecture is true, then the values produced by the {@code nextInt()}, {@code nextFloat()}, + * and {@code nextDouble()} methods are likewise approximately 16-equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L128X1024MixRandom} + * instance that shares no mutable state with the current instance. However, with + * very high probability, the values collectively generated by the two objects + * have the same statistical properties as if the same quantity of values were + * generated by a single thread using a single {@link L128X1024MixRandom} object. + * This is because, with high probability, distinct {@link L128X1024MixRandom} objects + * have distinct {@code a} parameters and therefore use distinct members of the + * algorithmic family; and even if their {@code a} parameters are the same, with + * very high probability they will traverse different parts of their common state + * cycle. + *

+ * As with {@link java.util.SplittableRandom}, instances of + * {@link L128X1024MixRandom} are not thread-safe. + * They are designed to be split, not shared, across threads. For + * example, a {@link java.util.concurrent.ForkJoinTask} fork/join-style + * computation using random numbers might include a construction + * of the form {@code new Subtask(someL128X1024MixRandom.split()).fork()}. + *

+ * This class provides additional methods for generating random + * streams, that employ the above techniques when used in + * {@code stream.parallel()} mode. + *

+ * Instances of {@link L128X1024MixRandom} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class L128X1024MixRandom extends AbstractSplittableWithBrineGenerator { + + /* + * Implementation Overview. + * + * The 128-bit parameter `a` is represented as two long fields `ah` and `al`. + * The 128-bit state variable `s` is represented as two long fields `sh` and `sl`. + * + * The split operation uses the current generator to choose 20 + * new 64-bit long values that are then used to initialize the + * parameters `ah` and `al`, the state variables `sh`, `sl`, + * and the array `x` for a newly constructed generator. + * + * With extremely high probability, no two generators so chosen + * will have the same `a` parameter, and testing has indicated + * that the values generated by two instances of {@link L128X1024MixRandom} + * will be (approximately) independent if have different values for `a`. + * + * The default (no-argument) constructor, in essence, uses + * "defaultGen" to generate 20 new 64-bit values for the same + * purpose. Multiple generators created in this way will certainly + * differ in their `a` parameters. The defaultGen state must be accessed + * in a thread-safe manner, so we use an AtomicLong to represent + * this state. To bootstrap the defaultGen, we start off using a + * seed based on current time unless the + * java.util.secureRandomSeed property is set. This serves as a + * slimmed-down (and insecure) variant of SecureRandom that also + * avoids stalls that may occur when using /dev/random. + * + * File organization: First static fields, then instance + * fields, then constructors, then instance methods. + */ + + /* ---------------- static fields ---------------- */ + + /* + * The length of the array x. + */ + + private static final int N = 16; + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is (2**1024 - 1) * 2**128. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(N*64).subtract(BigInteger.ONE).shiftLeft(128); + + /* + * Low half of multiplier used in the LCG portion of the algorithm; + * the overall multiplier is (2**64 + ML). + * Chosen based on research by Sebastiano Vigna and Guy Steele (2019). + * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL + * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493]. + */ + + private static final long ML = 0xd605bbb58c8abbfdL; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. + * Must be odd (therefore al must be odd). + */ + private final long ah, al; + + /** + * The per-instance state: sh and sl for the LCG; the array x for the xorshift; + * p is the rotating pointer into the array x. + * At least one of the 16 elements of the array x must be nonzero. + */ + private long sh, sl; + private final long[] x; + private int p = N - 1; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param ah high half of the additive parameter for the LCG + * @param al low half of the additive parameter for the LCG + * @param sh high half of the initial state for the LCG + * @param sl low half of the initial state for the LCG + * @param x0 first word of the initial state for the xorshift generator + * @param x1 second word of the initial state for the xorshift generator + * @param x2 third word of the initial state for the xorshift generator + * @param x3 fourth word of the initial state for the xorshift generator + * @param x4 fifth word of the initial state for the xorshift generator + * @param x5 sixth word of the initial state for the xorshift generator + * @param x6 seventh word of the initial state for the xorshift generator + * @param x7 eight word of the initial state for the xorshift generator + * @param x8 ninth word of the initial state for the xorshift generator + * @param x9 tenth word of the initial state for the xorshift generator + * @param x10 eleventh word of the initial state for the xorshift generator + * @param x11 twelfth word of the initial state for the xorshift generator + * @param x12 thirteenth word of the initial state for the xorshift generator + * @param x13 fourteenth word of the initial state for the xorshift generator + * @param x14 fifteenth word of the initial state for the xorshift generator + * @param x15 sixteenth word of the initial state for the xorshift generator + */ + public L128X1024MixRandom(long ah, long al, long sh, long sl, + long x0, long x1, long x2, long x3, + long x4, long x5, long x6, long x7, + long x8, long x9, long x10, long x11, + long x12, long x13, long x14, long x15) { + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x = new long[N]; + this.x[0] = x0; + this.x[1] = x1; + this.x[2] = x2; + this.x[3] = x3; + this.x[4] = x4; + this.x[5] = x5; + this.x[6] = x6; + this.x[7] = x7; + this.x[8] = x8; + this.x[9] = x9; + this.x[10] = x10; + this.x[11] = x11; + this.x[12] = x12; + this.x[13] = x13; + this.x[14] = x14; + this.x[15] = x15; + // If x0, x1, ..., x15 are all zero (very unlikely), we must choose nonzero values. + if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) { + long v = sh; + // At least fifteen of the sixteen values generated here will be nonzero. + for (int j = 0; j < N; j++) { + this.x[j] = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + } + } + } + + /** + * Creates a new instance of {@link L128X1024MixRandom} using the + * specified {@code long} value as the initial seed. Instances of + * {@link L128X1024MixRandom} created with the same seed in the same + * program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X1024MixRandom(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The seed is hashed by mixMurmur64 to produce the `a` parameter. + // The seed is hashed by mixStafford13 to produce the initial `x[0]`, + // which will then be used to produce the first generated value. + // The other x values are filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64), + 0, + 1, + RandomSupport.mixStafford13(seed), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X1024MixRandom} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public L128X1024MixRandom() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X1024MixRandom} using the specified array of + * initial seed bytes. Instances of {@link L128X1024MixRandom} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X1024MixRandom(byte[] seed) { + // Convert the seed to 20 long values, of which the last 16 are not all zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 20, 16); + long ah = data[0], al = data[1], sh = data[2], sl = data[3]; + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x = new long[N]; + for (int j = 0; j < N; j++) { + this.x[j] = data[4+j]; + } + } + + /* ---------------- public methods ---------------- */ + + /** + * Given 63 bits of "brine", constructs and returns a new instance of + * {@code L128X1024MixRandom} that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using + * a single {@code L128X1024MixRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @param brine a long value, of which the low 63 bits are used to choose + * the {@code a} parameter for the new instance. + * @return a new instance of {@code L128X1024MixRandom} + */ + public SplittableGenerator split(SplittableGenerator source, long brine) { + // Pick a new instance "at random", but use the brine for (the low half of) `a`. + return new L128X1024MixRandom(source.nextLong(), brine << 1, + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong()); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + // First part of xoroshiro1024: fetch array data + final int q = p; + final long s0 = x[p = (p + 1) & (N - 1)]; + long s15 = x[q]; + + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + final long result = RandomSupport.mixLea64(sh + s0); + + // Update the LCG subgenerator + // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic. + final long u = ML * sl; + // Note that Math.multiplyHigh computes the high half of the product of signed values, + // but what we need is the high half of the product of unsigned values; for this we use the + // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)"; + // in effect, each operand is added to the result iff the sign bit of the other operand is 1. + // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013), + // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.) + // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become: + // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; + // and this entire comment can be deleted. + sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah; + sl = u + al; + if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. + + // Second part of xoroshiro1024: update array data + s15 ^= s0; + x[q] = Long.rotateLeft(s0, 25) ^ s15 ^ (s15 << 27); + x[p] = Long.rotateLeft(s15, 36); + + return result; + } + + /** + * Returns the period of this random generator. + * + * @return a {@link BigInteger} whose value is the number of distinct possible states of this + * {@link RandomGenerator} object (2128(21024-1)). + */ + public BigInteger period() { + return PERIOD; + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/L128X128MixRandom.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/L128X128MixRandom.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.SplittableGenerator; +import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link L128X128MixRandom} implements + * interfaces {@link RandomGenerator} and {@link SplittableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new split-off {@link L128X128MixRandom} objects, + * with similar usages as for class {@link java.util.SplittableRandom}. + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + * (Most recently validated with + * version 1.2.3 of TestU01 + * and version 0.90 of PractRand. + * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()} + * method but also the result of bit-reversing each value produced by {@code nextLong()}.) + * These tests validate only the methods for certain + * types and ranges, but similar properties are expected to hold, at + * least approximately, for others as well. + *

+ * {@link L128X128MixRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is + * an Xorshift generator. Each output of an LXM generator is the result of + * combining state from the LCG with state from the Xorshift generator by + * using a Mixing function (and then the state of the LCG and the state of the + * Xorshift generator are advanced). + *

+ * The LCG subgenerator for {@link L128X256MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all + * 128-bit integers; {@code s} is the mutable state, the multiplier {@code m} + * is fixed (the same for all instances of {@link L128X256MixRandom}) and the addend + * {@code a} is a parameter (a final field of the instance). The parameter + * {@code a} is required to be odd (this allows the LCG to have the maximal + * period, namely 2128); therefore there are 2127 distinct choices + * of parameter. + *

+ * The Xorshift subgenerator for {@link L128X128MixRandom} is the {@code xoroshiro128} algorithm, + * version 1.0 (parameters 24, 16, 37), without any final scrambler such as "+" or "**". + * Its state consists of two {@code long} fields {@code x0} and {@code x1}, + * which can take on any values provided that they are not both zero. + * The period of this subgenerator is 2128-1. + *

+ * The mixing function for {@link L128X128MixRandom} is {@link RandomSupport.mixLea64} + * applied to the argument {@code (sh + x0)}, where {@code sh} is the high half of {@code s}. + *

+ * Because the periods 2128 and 2128-1 of the two subgenerators + * are relatively prime, the period of any single {@link L128X128MixRandom} object + * (the length of the series of generated 64-bit values before it repeats) is the product + * of the periods of the subgenerators, that is, 2128(2128-1), + * which is just slightly smaller than 2256. Moreover, if two distinct + * {@link L128X128MixRandom} objects have different {@code a} parameters, then their + * cycles of produced values will be different. + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L128X128MixRandom}, over the course of its cycle each + * of the 264 possible {@code long} values will be produced + * 264(2128-1) times. The values produced by the {@code nextInt()}, + * {@code nextFloat()}, and {@code nextDouble()} methods are likewise exactly equidistributed. + *

+ * Moreover, 64-bit values produced by the {@code nextLong()} method are conjectured to be + * "very nearly" 2-equidistributed: all possible pairs of 64-bit values are generated, + * and some pairs occur more often than others, but only very slightly more often. + * However, this conjecture has not yet been proven mathematically. + * If this conjecture is true, then the values produced by the {@code nextInt()}, {@code nextFloat()}, + * and {@code nextDouble()} methods are likewise approximately 2-equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L128X128MixRandom} + * instance that shares no mutable state with the current instance. However, with + * very high probability, the values collectively generated by the two objects + * have the same statistical properties as if the same quantity of values were + * generated by a single thread using a single {@link L128X128MixRandom} object. + * This is because, with high probability, distinct {@link L128X128MixRandom} objects + * have distinct {@code a} parameters and therefore use distinct members of the + * algorithmic family; and even if their {@code a} parameters are the same, with + * very high probability they will traverse different parts of their common state + * cycle. + *

+ * As with {@link java.util.SplittableRandom}, instances of + * {@link L128X128MixRandom} are not thread-safe. + * They are designed to be split, not shared, across threads. For + * example, a {@link java.util.concurrent.ForkJoinTask} fork/join-style + * computation using random numbers might include a construction + * of the form {@code new Subtask(someL128X128MixRandom.split()).fork()}. + *

+ * This class provides additional methods for generating random + * streams, that employ the above techniques when used in + * {@code stream.parallel()} mode. + *

+ * Instances of {@link L128X128MixRandom} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class L128X128MixRandom extends AbstractSplittableWithBrineGenerator { + + /* + * Implementation Overview. + * + * The split operation uses the current generator to choose four new 64-bit + * long values that are then used to initialize the parameter `a` and the + * state variables `s`, `x0`, and `x1` for a newly constructed generator. + * + * With extremely high probability, no two generators so chosen + * will have the same `a` parameter, and testing has indicated + * that the values generated by two instances of {@link L128X128MixRandom} + * will be (approximately) independent if have different values for `a`. + * + * The default (no-argument) constructor, in essence, uses + * "defaultGen" to generate four new 64-bit values for the same + * purpose. Multiple generators created in this way will certainly + * differ in their `a` parameters. The defaultGen state must be accessed + * in a thread-safe manner, so we use an AtomicLong to represent + * this state. To bootstrap the defaultGen, we start off using a + * seed based on current time unless the + * java.util.secureRandomSeed property is set. This serves as a + * slimmed-down (and insecure) variant of SecureRandom that also + * avoids stalls that may occur when using /dev/random. + * + * File organization: First static fields, then instance + * fields, then constructors, then instance methods. + */ + + /* ---------------- static fields ---------------- */ + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is (2**128 - 1) * 2**128. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(128); + + /* + * Low half of multiplier used in the LCG portion of the algorithm; + * the overall multiplier is (2**64 + ML). + * Chosen based on research by Sebastiano Vigna and Guy Steele (2019). + * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL + * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493]. + */ + + private static final long ML = 0xd605bbb58c8abbfdL; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. + * Must be odd (therefore al must be odd). + */ + private final long ah, al; + + /** + * The per-instance state: sh and sl for the LCG; x0 and x1 for the xorshift. + * At least one of x0 and x1 must be nonzero. + */ + private long sh, sl, x0, x1; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param ah high half of the additive parameter for the LCG + * @param al low half of the additive parameter for the LCG + * @param sh high half of the initial state for the LCG + * @param sl low half of the initial state for the LCG + * @param x0 first word of the initial state for the xorshift generator + * @param x1 second word of the initial state for the xorshift generator + */ + public L128X128MixRandom(long ah, long al, long sh, long sl, long x0, long x1) { + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x0 = x0; + this.x1 = x1; + // If x0 and x1 are both zero, we must choose nonzero values. + if ((x0 | x1) == 0) { + long v = sh; + // At least one of the two values generated here will be nonzero. + this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x1 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64); + } + } + + /** + * Creates a new instance of {@link L128X128MixRandom} using the + * specified {@code long} value as the initial seed. Instances of + * {@link L128X128MixRandom} created with the same seed in the same + * program generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X128MixRandom(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The seed is hashed by mixMurmur64 to produce the `a` parameter. + // The seed is hashed by mixStafford13 to produce the initial `x0`, + // which will then be used to produce the first generated value. + // Then x1 is filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64), + 0, + 1, + RandomSupport.mixStafford13(seed), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X128MixRandom} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public L128X128MixRandom() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X128MixRandom} using the specified array of + * initial seed bytes. Instances of {@link L128X128MixRandom} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X128MixRandom(byte[] seed) { + // Convert the seed to 6 long values, of which the last 2 are not all zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 2); + long ah = data[0], al = data[1], sh = data[2], sl = data[3], x0 = data[4], x1 = data[5]; + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x0 = x0; + this.x1 = x1; + } + + /* ---------------- public methods ---------------- */ + + /** + * Given 63 bits of "brine", constructs and returns a new instance of + * {@code L128X128MixRandom} that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using + * a single {@code L128X128MixRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @param brine a long value, of which the low 63 bits are used to choose + * the {@code a} parameter for the new instance. + * @return a new instance of {@code L128X128MixRandom} + */ + public SplittableGenerator split(SplittableGenerator source, long brine) { + // Pick a new instance "at random", but use the brine for (the low half of) `a`. + return new L128X128MixRandom(source.nextLong(), brine << 1, + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong()); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + final long result = RandomSupport.mixLea64(sh + x0); + + // Update the LCG subgenerator + // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic. + final long u = ML * sl; + // Note that Math.multiplyHigh computes the high half of the product of signed values, + // but what we need is the high half of the product of unsigned values; for this we use the + // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)"; + // in effect, each operand is added to the result iff the sign bit of the other operand is 1. + // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013), + // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.) + // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become: + // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; + // and this entire comment can be deleted. + sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah; + sl = u + al; + if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. + + long q0 = x0, q1 = x1; + // Update the Xorshift subgenerator + { // xoroshiro128v1_0 + q1 ^= q0; + q0 = Long.rotateLeft(q0, 24); + q0 = q0 ^ q1 ^ (q1 << 16); + q1 = Long.rotateLeft(q1, 37); + } + x0 = q0; x1 = q1; + return result; + } + + /** + * Returns the period of this random generator. + * + * @return a {@link BigInteger} whose value is the number of distinct possible states of this + * {@link RandomGenerator} object (2128(2128-1)). + */ + public BigInteger period() { + return PERIOD; + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/L128X128PlusPlusRandom.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/L128X128PlusPlusRandom.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.SplittableGenerator; +import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link L128X128PlusPlusRandom} implements + * interfaces {@link RandomGenerator} and {@link SplittableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new split-off {@link L128X128PlusPlusRandom} objects, + * with similar usages as for class {@link java.util.SplittableRandom}. + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + * (Most recently validated with + * version 1.2.3 of TestU01 + * and version 0.90 of PractRand. + * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()} + * method but also the result of bit-reversing each value produced by {@code nextLong()}.) + * These tests validate only the methods for certain + * types and ranges, but similar properties are expected to hold, at + * least approximately, for others as well. + *

+ * {@link L128X128PlusPlusRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is + * an Xorshift generator. Each output of an LXM generator is the result of + * combining state from the LCG with state from the Xorshift generator by + * using a Mixing function (and then the state of the LCG and the state of the + * Xorshift generator are advanced). + *

+ * The LCG subgenerator for {@link L128X256MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all + * 128-bit integers; {@code s} is the mutable state, the multiplier {@code m} + * is fixed (the same for all instances of {@link L128X256MixRandom}) and the addend + * {@code a} is a parameter (a final field of the instance). The parameter + * {@code a} is required to be odd (this allows the LCG to have the maximal + * period, namely 2128); therefore there are 2127 distinct choices + * of parameter. + *

+ * The Xorshift subgenerator for {@link L128X128PlusPlusRandom} is the {@code xoroshiro128} algorithm, + * version 1.0 (parameters 24, 16, 37), without any final scrambler such as "+" or "**". + * Its state consists of two {@code long} fields {@code x0} and {@code x1}, + * which can take on any values provided that they are not both zero. + * The period of this subgenerator is 2128-1. + *

+ * The mixing function for {@link L128X128PlusPlusRandom} is the 64-bit "plusplus(17)" + * scrambler that computes {@code Long.rotateLeft((sh + x0), 17) + x1}, where {@code sh} + * is the high half of {@code s}. + *

+ * Because the periods 2128 and 2128-1 of the two subgenerators + * are relatively prime, the period of any single {@link L128X128PlusPlusRandom} object + * (the length of the series of generated 64-bit values before it repeats) is the product + * of the periods of the subgenerators, that is, 2128(2128-1), + * which is just slightly smaller than 2256. Moreover, if two distinct + * {@link L128X128PlusPlusRandom} objects have different {@code a} parameters, then their + * cycles of produced values will be different. + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L128X128PlusPlusRandom}, over the course of its cycle each + * of the 264 possible {@code long} values will be produced + * 264(2128-1) times. The values produced by the {@code nextInt()}, + * {@code nextFloat()}, and {@code nextDouble()} methods are likewise exactly equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L128X128PlusPlusRandom} + * instance that shares no mutable state with the current instance. However, with + * very high probability, the values collectively generated by the two objects + * have the same statistical properties as if the same quantity of values were + * generated by a single thread using a single {@link L128X128PlusPlusRandom} object. + * This is because, with high probability, distinct {@link L128X128PlusPlusRandom} objects + * have distinct {@code a} parameters and therefore use distinct members of the + * algorithmic family; and even if their {@code a} parameters are the same, with + * very high probability they will traverse different parts of their common state + * cycle. + *

+ * As with {@link java.util.SplittableRandom}, instances of + * {@link L128X128PlusPlusRandom} are not thread-safe. + * They are designed to be split, not shared, across threads. For + * example, a {@link java.util.concurrent.ForkJoinTask} fork/join-style + * computation using random numbers might include a construction + * of the form {@code new Subtask(someL128X128PlusPlusRandom.split()).fork()}. + *

+ * This class provides additional methods for generating random + * streams, that employ the above techniques when used in + * {@code stream.parallel()} mode. + *

+ * Instances of {@link L128X128PlusPlusRandom} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class L128X128PlusPlusRandom extends AbstractSplittableWithBrineGenerator { + + /* + * Implementation Overview. + * + * The split operation uses the current generator to choose four new 64-bit + * long values that are then used to initialize the parameter `a` and the + * state variables `s`, `x0`, and `x1` for a newly constructed generator. + * + * With extremely high probability, no two generators so chosen + * will have the same `a` parameter, and testing has indicated + * that the values generated by two instances of {@link L128X128PlusPlusRandom} + * will be (approximately) independent if have different values for `a`. + * + * The default (no-argument) constructor, in essence, uses + * "defaultGen" to generate four new 64-bit values for the same + * purpose. Multiple generators created in this way will certainly + * differ in their `a` parameters. The defaultGen state must be accessed + * in a thread-safe manner, so we use an AtomicLong to represent + * this state. To bootstrap the defaultGen, we start off using a + * seed based on current time unless the + * java.util.secureRandomSeed property is set. This serves as a + * slimmed-down (and insecure) variant of SecureRandom that also + * avoids stalls that may occur when using /dev/random. + * + * File organization: First static fields, then instance + * fields, then constructors, then instance methods. + */ + + /* ---------------- static fields ---------------- */ + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is (2**128 - 1) * 2**128. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(128); + + /* + * Low half of multiplier used in the LCG portion of the algorithm; + * the overall multiplier is (2**64 + ML). + * Chosen based on research by Sebastiano Vigna and Guy Steele (2019). + * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL + * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493]. + */ + + private static final long ML = 0xd605bbb58c8abbfdL; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. + * Must be odd (therefore al must be odd). + */ + private final long ah, al; + + /** + * The per-instance state: sh and sl for the LCG; x0 and x1 for the xorshift. + * At least one of x0 and x1 must be nonzero. + */ + private long sh, sl, x0, x1; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param ah high half of the additive parameter for the LCG + * @param al low half of the additive parameter for the LCG + * @param sh high half of the initial state for the LCG + * @param sl low half of the initial state for the LCG + * @param x0 first word of the initial state for the xorshift generator + * @param x1 second word of the initial state for the xorshift generator + */ + public L128X128PlusPlusRandom(long ah, long al, long sh, long sl, long x0, long x1) { + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x0 = x0; + this.x1 = x1; + // If x0 and x1 are both zero, we must choose nonzero values. + if ((x0 | x1) == 0) { + long v = sh; + // At least one of the two values generated here will be nonzero. + this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x1 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64); + } + } + + /** + * Creates a new instance of {@link L128X128PlusPlusRandom} using the + * specified {@code long} value as the initial seed. Instances of + * {@link L128X128PlusPlusRandom} created with the same seed in the same + * program generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X128PlusPlusRandom(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The seed is hashed by mixMurmur64 to produce the `a` parameter. + // The seed is hashed by mixStafford13 to produce the initial `x0`, + // which will then be used to produce the first generated value. + // Then x1 is filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64), + 0, + 1, + RandomSupport.mixStafford13(seed), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X128PlusPlusRandom} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public L128X128PlusPlusRandom() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X128PlusPlusRandom} using the specified array of + * initial seed bytes. Instances of {@link L128X128PlusPlusRandom} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X128PlusPlusRandom(byte[] seed) { + // Convert the seed to 6 long values, of which the last 2 are not all zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 2); + long ah = data[0], al = data[1], sh = data[2], sl = data[3], x0 = data[4], x1 = data[5]; + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x0 = x0; + this.x1 = x1; + } + + /* ---------------- public methods ---------------- */ + + /** + * Given 63 bits of "brine", constructs and returns a new instance of + * {@code L128X128PlusPlusRandom} that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using + * a single {@code L128X128PlusPlusRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @param brine a long value, of which the low 63 bits are used to choose + * the {@code a} parameter for the new instance. + * @return a new instance of {@code L128X128PlusPlusRandom} + */ + public SplittableGenerator split(SplittableGenerator source, long brine) { + // Pick a new instance "at random", but use the brine for (the low half of) `a`. + return new L128X128PlusPlusRandom(source.nextLong(), brine << 1, + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong()); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + final long result = Long.rotateLeft((sh + x0), 17) + x1; // "plusplus" scrambler + + // Update the LCG subgenerator + // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic. + final long u = ML * sl; + // Note that Math.multiplyHigh computes the high half of the product of signed values, + // but what we need is the high half of the product of unsigned values; for this we use the + // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)"; + // in effect, each operand is added to the result iff the sign bit of the other operand is 1. + // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013), + // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.) + // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become: + // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; + // and this entire comment can be deleted. + sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah; + sl = u + al; + if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. + + long q0 = x0, q1 = x1; + // Update the Xorshift subgenerator + { // xoroshiro128v1_0 + q1 ^= q0; + q0 = Long.rotateLeft(q0, 24); + q0 = q0 ^ q1 ^ (q1 << 16); + q1 = Long.rotateLeft(q1, 37); + } + x0 = q0; x1 = q1; + return result; + } + + /** + * Returns the period of this random generator. + * + * @return a {@link BigInteger} whose value is the number of distinct possible states of this + * {@link RandomGenerator} object (2128(2128-1)). + */ + public BigInteger period() { + return PERIOD; + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/L128X128StarStarRandom.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/L128X128StarStarRandom.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.SplittableGenerator; +import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link L128X128StarStarRandom} implements + * interfaces {@link RandomGenerator} and {@link SplittableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new split-off {@link L128X128StarStarRandom} objects, + * with similar usages as for class {@link java.util.SplittableRandom}. + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + * (Most recently validated with + * version 1.2.3 of TestU01 + * and version 0.90 of PractRand. + * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()} + * method but also the result of bit-reversing each value produced by {@code nextLong()}.) + * These tests validate only the methods for certain + * types and ranges, but similar properties are expected to hold, at + * least approximately, for others as well. + *

+ * {@link L128X128StarStarRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is + * an Xorshift generator. Each output of an LXM generator is the result of + * combining state from the LCG with state from the Xorshift generator by + * using a Mixing function (and then the state of the LCG and the state of the + * Xorshift generator are advanced). + *

+ * The LCG subgenerator for {@link L128X256MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all + * 128-bit integers; {@code s} is the mutable state, the multiplier {@code m} + * is fixed (the same for all instances of {@link L128X256MixRandom}) and the addend + * {@code a} is a parameter (a final field of the instance). The parameter + * {@code a} is required to be odd (this allows the LCG to have the maximal + * period, namely 2128); therefore there are 2127 distinct choices + * of parameter. + *

+ * The Xorshift subgenerator for {@link L128X128StarStarRandom} is the {@code xoroshiro128} algorithm, + * version 1.0 (parameters 24, 16, 37), without any final scrambler such as "+" or "**". + * Its state consists of two {@code long} fields {@code x0} and {@code x1}, + * which can take on any values provided that they are not both zero. + * The period of this subgenerator is 2128-1. + *

+ * The mixing function for {@link L128X128StarStarRandom} is the 64-bit "starstar(5,7,9)" + * scrambler that computes {@code Long.rotateLeft((sh + x0) * 5, 7) * 9}, where {@code sh} + * is the high half of {@code s}. + *

+ * Because the periods 2128 and 2128-1 of the two subgenerators + * are relatively prime, the period of any single {@link L128X128StarStarRandom} object + * (the length of the series of generated 64-bit values before it repeats) is the product + * of the periods of the subgenerators, that is, 2128(2128-1), + * which is just slightly smaller than 2256. Moreover, if two distinct + * {@link L128X128StarStarRandom} objects have different {@code a} parameters, then their + * cycles of produced values will be different. + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L128X128StarStarRandom}, over the course of its cycle each + * of the 264 possible {@code long} values will be produced + * 264(2128-1) times. The values produced by the {@code nextInt()}, + * {@code nextFloat()}, and {@code nextDouble()} methods are likewise exactly equidistributed. + *

+ * Moreover, 64-bit values produced by the {@code nextLong()} method are conjectured to be + * "very nearly" 2-equidistributed: all possible pairs of 64-bit values are generated, + * and some pairs occur more often than others, but only very slightly more often. + * However, this conjecture has not yet been proven mathematically. + * If this conjecture is true, then the values produced by the {@code nextInt()}, {@code nextFloat()}, + * and {@code nextDouble()} methods are likewise approximately 2-equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L128X128StarStarRandom} + * instance that shares no mutable state with the current instance. However, with + * very high probability, the values collectively generated by the two objects + * have the same statistical properties as if the same quantity of values were + * generated by a single thread using a single {@link L128X128StarStarRandom} object. + * This is because, with high probability, distinct {@link L128X128StarStarRandom} objects + * have distinct {@code a} parameters and therefore use distinct members of the + * algorithmic family; and even if their {@code a} parameters are the same, with + * very high probability they will traverse different parts of their common state + * cycle. + *

+ * As with {@link java.util.SplittableRandom}, instances of + * {@link L128X128StarStarRandom} are not thread-safe. + * They are designed to be split, not shared, across threads. For + * example, a {@link java.util.concurrent.ForkJoinTask} fork/join-style + * computation using random numbers might include a construction + * of the form {@code new Subtask(someL128X128StarStarRandom.split()).fork()}. + *

+ * This class provides additional methods for generating random + * streams, that employ the above techniques when used in + * {@code stream.parallel()} mode. + *

+ * Instances of {@link L128X128StarStarRandom} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class L128X128StarStarRandom extends AbstractSplittableWithBrineGenerator { + + /* + * Implementation Overview. + * + * The split operation uses the current generator to choose four new 64-bit + * long values that are then used to initialize the parameter `a` and the + * state variables `s`, `x0`, and `x1` for a newly constructed generator. + * + * With extremely high probability, no two generators so chosen + * will have the same `a` parameter, and testing has indicated + * that the values generated by two instances of {@link L128X128StarStarRandom} + * will be (approximately) independent if have different values for `a`. + * + * The default (no-argument) constructor, in essence, uses + * "defaultGen" to generate four new 64-bit values for the same + * purpose. Multiple generators created in this way will certainly + * differ in their `a` parameters. The defaultGen state must be accessed + * in a thread-safe manner, so we use an AtomicLong to represent + * this state. To bootstrap the defaultGen, we start off using a + * seed based on current time unless the + * java.util.secureRandomSeed property is set. This serves as a + * slimmed-down (and insecure) variant of SecureRandom that also + * avoids stalls that may occur when using /dev/random. + * + * File organization: First static fields, then instance + * fields, then constructors, then instance methods. + */ + + /* ---------------- static fields ---------------- */ + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is (2**128 - 1) * 2**128. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(128); + + /* + * Low half of multiplier used in the LCG portion of the algorithm; + * the overall multiplier is (2**64 + ML). + * Chosen based on research by Sebastiano Vigna and Guy Steele (2019). + * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL + * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493]. + */ + + private static final long ML = 0xd605bbb58c8abbfdL; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. + * Must be odd (therefore al must be odd). + */ + private final long ah, al; + + /** + * The per-instance state: sh and sl for the LCG; x0 and x1 for the xorshift. + * At least one of x0 and x1 must be nonzero. + */ + private long sh, sl, x0, x1; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param ah high half of the additive parameter for the LCG + * @param al low half of the additive parameter for the LCG + * @param sh high half of the initial state for the LCG + * @param sl low half of the initial state for the LCG + * @param x0 first word of the initial state for the xorshift generator + * @param x1 second word of the initial state for the xorshift generator + */ + public L128X128StarStarRandom(long ah, long al, long sh, long sl, long x0, long x1) { + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x0 = x0; + this.x1 = x1; + // If x0 and x1 are both zero, we must choose nonzero values. + if ((x0 | x1) == 0) { + // At least one of the two values generated here will be nonzero. + long v = sh; + this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x1 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64); + } + } + + /** + * Creates a new instance of {@link L128X128StarStarRandom} using the + * specified {@code long} value as the initial seed. Instances of + * {@link L128X128StarStarRandom} created with the same seed in the same + * program generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X128StarStarRandom(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The seed is hashed by mixMurmur64 to produce the `a` parameter. + // The seed is hashed by mixStafford13 to produce the initial `x0`, + // which will then be used to produce the first generated value. + // Then x1 is filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64), + 0, + 1, + RandomSupport.mixStafford13(seed), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X128StarStarRandom} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public L128X128StarStarRandom() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X128StarStarRandom} using the specified array of + * initial seed bytes. Instances of {@link L128X128StarStarRandom} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X128StarStarRandom(byte[] seed) { + // Convert the seed to 6 long values, of which the last 2 are not all zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 2); + long ah = data[0], al = data[1], sh = data[2], sl = data[3], x0 = data[4], x1 = data[5]; + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x0 = x0; + this.x1 = x1; + } + + /* ---------------- public methods ---------------- */ + + /** + * Given 63 bits of "brine", constructs and returns a new instance of + * {@code L128X128StarStarRandom} that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using + * a single {@code L128X128StarStarRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @param brine a long value, of which the low 63 bits are used to choose + * the {@code a} parameter for the new instance. + * @return a new instance of {@code L128X128StarStarRandom} + */ + public SplittableGenerator split(SplittableGenerator source, long brine) { + // Pick a new instance "at random", but use the brine for (the low half of) `a`. + return new L128X128StarStarRandom(source.nextLong(), brine << 1, + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong()); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + final long result = Long.rotateLeft((sh + x0) * 5, 7) * 9; // "starstar" scrambler + + // Update the LCG subgenerator + // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic. + final long u = ML * sl; + // Note that Math.multiplyHigh computes the high half of the product of signed values, + // but what we need is the high half of the product of unsigned values; for this we use the + // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)"; + // in effect, each operand is added to the result iff the sign bit of the other operand is 1. + // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013), + // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.) + // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become: + // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; + // and this entire comment can be deleted. + sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah; + sl = u + al; + if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. + + long q0 = x0, q1 = x1; + // Update the Xorshift subgenerator + { // xoroshiro128v1_0 + q1 ^= q0; + q0 = Long.rotateLeft(q0, 24); + q0 = q0 ^ q1 ^ (q1 << 16); + q1 = Long.rotateLeft(q1, 37); + } + x0 = q0; x1 = q1; + return result; + } + + /** + * Returns the period of this random generator. + * + * @return a {@link BigInteger} whose value is the number of distinct possible states of this + * {@link RandomGenerator} object (2128(2128-1)). + */ + public BigInteger period() { + return PERIOD; + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/L128X256MixRandom.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/L128X256MixRandom.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.SplittableGenerator; +import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator; + + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link L128X256MixRandom} implements + * interfaces {@link RandomGenerator} and {@link SplittableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new split-off {@link L128X256MixRandom} objects, + * with similar usages as for class {@link java.util.SplittableRandom}. + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + * (Most recently validated with + * version 1.2.3 of TestU01 + * and version 0.90 of PractRand. + * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()} + * method but also the result of bit-reversing each value produced by {@code nextLong()}.) + * These tests validate only the methods for certain + * types and ranges, but similar properties are expected to hold, at + * least approximately, for others as well. + *

+ * {@link L128X256MixRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is + * an Xorshift generator. Each output of an LXM generator is the result of + * combining state from the LCG with state from the Xorshift generator by + * using a Mixing function (and then the state of the LCG and the state of the + * Xorshift generator are advanced). + *

+ * The LCG subgenerator for {@link L128X256MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all + * 128-bit integers; {@code s} is the mutable state, the multiplier {@code m} + * is fixed (the same for all instances of {@link L128X256MixRandom}) and the addend + * {@code a} is a parameter (a final field of the instance). The parameter + * {@code a} is required to be odd (this allows the LCG to have the maximal + * period, namely 2128); therefore there are 2127 distinct choices + * of parameter. + *

+ * The Xorshift subgenerator for {@link L128X256MixRandom} is the {@code xoshiro256} algorithm, + * version 1.0 (parameters 17, 45), without any final scrambler such as "+" or "**". + * Its state consists of four {@code long} fields {@code x0}, {@code x1}, {@code x2}, + * and {@code x3}, which can take on any values provided that they are not all zero. + * The period of this subgenerator is 2256-1. + *

+ * The mixing function for {@link L128X256MixRandom} is {@link RandomSupport.mixLea64} + * applied to the argument {@code (sh + x0)}, where {@code sh} is the high half of {@code s}. + *

+ * Because the periods 2128 and 2256-1 of the two subgenerators + * are relatively prime, the period of any single {@link L128X256MixRandom} object + * (the length of the series of generated 64-bit values before it repeats) is the product + * of the periods of the subgenerators, that is, 2128(2256-1), + * which is just slightly smaller than 2384. Moreover, if two distinct + * {@link L128X256MixRandom} objects have different {@code a} parameters, then their + * cycles of produced values will be different. + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L128X256MixRandom}, over the course of its cycle each + * of the 264 possible {@code long} values will be produced + * 264(2256-1) times. The values produced by the {@code nextInt()}, + * {@code nextFloat()}, and {@code nextDouble()} methods are likewise exactly equidistributed. + *

+ * Moreover, 64-bit values produced by the {@code nextLong()} method are conjectured to be + * "very nearly" 4-equidistributed: all possible quadruples of 64-bit values are generated, + * and some pairs occur more often than others, but only very slightly more often. + * However, this conjecture has not yet been proven mathematically. + * If this conjecture is true, then the values produced by the {@code nextInt()}, {@code nextFloat()}, + * and {@code nextDouble()} methods are likewise approximately 4-equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L128X256MixRandom} + * instance that shares no mutable state with the current instance. However, with + * very high probability, the values collectively generated by the two objects + * have the same statistical properties as if the same quantity of values were + * generated by a single thread using a single {@link L128X256MixRandom} object. + * This is because, with high probability, distinct {@link L128X256MixRandom} objects + * have distinct {@code a} parameters and therefore use distinct members of the + * algorithmic family; and even if their {@code a} parameters are the same, with + * very high probability they will traverse different parts of their common state + * cycle. + *

+ * As with {@link java.util.SplittableRandom}, instances of + * {@link L128X256MixRandom} are not thread-safe. + * They are designed to be split, not shared, across threads. For + * example, a {@link java.util.concurrent.ForkJoinTask} fork/join-style + * computation using random numbers might include a construction + * of the form {@code new Subtask(someL128X256MixRandom.split()).fork()}. + *

+ * This class provides additional methods for generating random + * streams, that employ the above techniques when used in + * {@code stream.parallel()} mode. + *

+ * Instances of {@link L128X256MixRandom} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class L128X256MixRandom extends AbstractSplittableWithBrineGenerator { + + /* + * Implementation Overview. + * + * The 128-bit parameter `a` is represented as two long fields `ah` and `al`. + * The 128-bit state variable `s` is represented as two long fields `sh` and `sl`. + * + * The split operation uses the current generator to choose eight + * new 64-bit long values that are then used to initialize the + * parameters `ah` and `al` and the state variables `sh`, `sl`, + * `x0`, `x1`, `x2`, and `x3` for a newly constructed generator. + * + * With extremely high probability, no two generators so chosen + * will have the same `a` parameter, and testing has indicated + * that the values generated by two instances of {@link L128X256MixRandom} + * will be (approximately) independent if have different values for `a`. + * + * The default (no-argument) constructor, in essence, uses + * "defaultGen" to generate eight new 64-bit values for the same + * purpose. Multiple generators created in this way will certainly + * differ in their `a` parameters. The defaultGen state must be accessed + * in a thread-safe manner, so we use an AtomicLong to represent + * this state. To bootstrap the defaultGen, we start off using a + * seed based on current time unless the + * java.util.secureRandomSeed property is set. This serves as a + * slimmed-down (and insecure) variant of SecureRandom that also + * avoids stalls that may occur when using /dev/random. + * + * File organization: First static fields, then instance + * fields, then constructors, then instance methods. + */ + + /* ---------------- static fields ---------------- */ + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is (2**256 - 1) * 2**128. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(128); + + /* + * Low half of multiplier used in the LCG portion of the algorithm; + * the overall multiplier is (2**64 + ML). + * Chosen based on research by Sebastiano Vigna and Guy Steele (2019). + * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL + * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493]. + */ + + private static final long ML = 0xd605bbb58c8abbfdL; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. + * Must be odd (therefore al must be odd). + */ + private final long ah, al; + + /** + * The per-instance state: sh and sl for the LCG; x0, x1, x2, and x3 for the xorshift. + * At least one of the four fields x0, x1, x2, and x3 must be nonzero. + */ + private long sh, sl, x0, x1, x2, x3; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param ah high half of the additive parameter for the LCG + * @param al low half of the additive parameter for the LCG + * @param sh high half of the initial state for the LCG + * @param sl low half of the initial state for the LCG + * @param x0 first word of the initial state for the xorshift generator + * @param x1 second word of the initial state for the xorshift generator + * @param x2 third word of the initial state for the xorshift generator + * @param x3 fourth word of the initial state for the xorshift generator + */ + public L128X256MixRandom(long ah, long al, long sh, long sl, long x0, long x1, long x2, long x3) { + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x0 = x0; + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + // If x0, x1, x2, and x3 are all zero, we must choose nonzero values. + if ((x0 | x1 | x2 | x3) == 0) { + long v = sh; + // At least three of the four values generated here will be nonzero. + this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x1 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x2 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x3 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64); + } + } + + /** + * Creates a new instance of {@link L128X256MixRandom} using the + * specified {@code long} value as the initial seed. Instances of + * {@link L128X256MixRandom} created with the same seed in the same + * program generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X256MixRandom(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The seed is hashed by mixMurmur64 to produce the `a` parameter. + // The seed is hashed by mixStafford13 to produce the initial `x0`, + // which will then be used to produce the first generated value. + // The other x values are filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64), + 0, + 1, + RandomSupport.mixStafford13(seed), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X256MixRandom} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public L128X256MixRandom() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L128X256MixRandom} using the specified array of + * initial seed bytes. Instances of {@link L128X256MixRandom} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L128X256MixRandom(byte[] seed) { + // Convert the seed to 6 long values, of which the last 4 are not all zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 4); + long ah = data[0], al = data[1], sh = data[2], sl = data[3], + x0 = data[4], x1 = data[5], x2 = data[6], x3 = data[7]; + // Force a to be odd. + this.ah = ah; + this.al = al | 1; + this.sh = sh; + this.sl = sl; + this.x0 = x0; + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + } + + /* ---------------- public methods ---------------- */ + + /** + * Given 63 bits of "brine", constructs and returns a new instance of + * {@code L128X256MixRandom} that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using + * a single {@code L128X256MixRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @param brine a long value, of which the low 63 bits are used to choose + * the {@code a} parameter for the new instance. + * @return a new instance of {@code L128X256MixRandom} + */ + public SplittableGenerator split(SplittableGenerator source, long brine) { + // Pick a new instance "at random", but use the brine for (the low half of) `a`. + return new L128X256MixRandom(source.nextLong(), brine << 1, + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong()); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + final long result = RandomSupport.mixLea64(sh + x0); + + // Update the LCG subgenerator + // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic. + final long u = ML * sl; + // Note that Math.multiplyHigh computes the high half of the product of signed values, + // but what we need is the high half of the product of unsigned values; for this we use the + // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)"; + // in effect, each operand is added to the result iff the sign bit of the other operand is 1. + // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013), + // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.) + // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become: + // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; + // and this entire comment can be deleted. + sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah; + sl = u + al; + if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. + + // Update the Xorshift subgenerator + long q0 = x0, q1 = x1, q2 = x2, q3 = x3; + { // xoshiro256 1.0 + long t = q1 << 17; + q2 ^= q0; + q3 ^= q1; + q1 ^= q2; + q0 ^= q3; + q2 ^= t; + q3 = Long.rotateLeft(q3, 45); + } + x0 = q0; x1 = q1; x2 = q2; x3 = q3; + return result; + } + + /** + * Returns the period of this random generator. + * + * @return a {@link BigInteger} whose value is the number of distinct possible states of this + * {@link RandomGenerator} object (2128(2256-1)). + */ + public BigInteger period() { + return PERIOD; + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/L128X256MixRandom.java.rej --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/L128X256MixRandom.java.rej Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,353 @@ +*************** +*** 28,34 **** + import java.math.BigInteger; + import java.util.concurrent.atomic.AtomicLong; + import java.util.random.RandomGenerator.SplittableGenerator; +- import java.util.random.RandomSupport.AbstractSplittableGenerator; + + + /** +--- 28,34 ---- + import java.math.BigInteger; + import java.util.concurrent.atomic.AtomicLong; + import java.util.random.RandomGenerator.SplittableGenerator; ++ import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator; + + + /** +*************** +*** 55,63 **** + * {@link L128X256MixRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is +- * an Xorshift generator. Each output of an LXM generator is the sum of one +- * output from each subgenerator, possibly processed by a final mixing function +- * (and {@link L128X256MixRandom} does use a mixing function). + *

+ * The LCG subgenerator for {@link L128X256MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all +--- 55,64 ---- + * {@link L128X256MixRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is ++ * an Xorshift generator. Each output of an LXM generator is the result of ++ * combining state from the LCG with state from the Xorshift generator by ++ * using a Mixing function (and then the state of the LCG and the state of the ++ * Xorshift generator are advanced). + *

+ * The LCG subgenerator for {@link L128X256MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all +*************** +*** 74,80 **** + * and {@code x3}, which can take on any values provided that they are not all zero. + * The period of this subgenerator is 2256-1. + *

+- * The mixing function for {@link L128X256MixRandom} is the 64-bit MurmurHash3 finalizer. + *

+ * Because the periods 2128 and 2256-1 of the two subgenerators + * are relatively prime, the period of any single {@link L128X256MixRandom} object +--- 75,82 ---- + * and {@code x3}, which can take on any values provided that they are not all zero. + * The period of this subgenerator is 2256-1. + *

++ * The mixing function for {@link L128X256MixRandom} is {@link RandomSupport.mixLea64} ++ * applied to the argument {@code (sh + x0)}, where {@code sh} is the high half of {@code s}. + *

+ * Because the periods 2128 and 2256-1 of the two subgenerators + * are relatively prime, the period of any single {@link L128X256MixRandom} object +*************** +*** 86,119 **** + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L128X256MixRandom}, over the course of its cycle each +- * of the 264 possible {@code long} values will be produced 2256-1 times. +- * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()} +- * methods are likewise exactly equidistributed. +- *

+- * In fact, the 64-bit values produced by the {@code nextLong()} method are exactly +- * 2-equidistributed. For any specific instance of {@link L128X256MixRandom}, consider +- * the (overlapping) length-2 subsequences of the cycle of 64-bit values produced by +- * {@code nextLong()} (assuming no other methods are called that would affect the state). +- * There are 2128(2256-1) such subsequences, and each subsequence, +- * which consists of 2 64-bit values, can have one of 2128 values, and each +- * such value occurs 2256-1 times. The values produced by the {@code nextInt()}, +- * {@code nextFloat()}, and {@code nextDouble()} methods are likewise exactly 2-equidistributed. + *

+- * Moreover, the 64-bit values produced by the {@code nextLong()} method are 4-equidistributed. +- * To be precise: for any specific instance of {@link L128X256MixRandom}, consider +- * the (overlapping) length-4 subsequences of the cycle of 64-bit values produced by +- * {@code nextLong()} (assuming no other methods are called that would affect the state). +- * There are 128(2256-1) such subsequences, and each subsequence, +- * which consists of 4 64-bit values, can have one of 2256 values. Of those +- * 2256 subsequence values, nearly all of them (2256-2128) +- * occur 2128 times over the course of the entire cycle, and the other +- * 2128 subsequence values occur only 2128-1 times. So the ratio +- * of the probability of getting one of the less common subsequence values and the +- * probability of getting one of the more common subsequence values is 1-2-128. +- * (Note that the set of 2128 less-common subsequence values will differ from +- * one instance of {@link L128X256MixRandom} to another, as a function of the additive +- * parameter of the LCG.) The values produced by the {@code nextInt()}, {@code nextFloat()}, +- * and {@code nextDouble()} methods are likewise 4-equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L128X256MixRandom} + * instance that shares no mutable state with the current instance. However, with +--- 88,103 ---- + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L128X256MixRandom}, over the course of its cycle each ++ * of the 264 possible {@code long} values will be produced ++ * 264(2256-1) times. The values produced by the {@code nextInt()}, ++ * {@code nextFloat()}, and {@code nextDouble()} methods are likewise exactly equidistributed. + *

++ * Moreover, 64-bit values produced by the {@code nextLong()} method are conjectured to be ++ * "very nearly" 4-equidistributed: all possible quadruples of 64-bit values are generated, ++ * and some pairs occur more often than others, but only very slightly more often. ++ * However, this conjecture has not yet been proven mathematically. ++ * If this conjecture is true, then the values produced by the {@code nextInt()}, {@code nextFloat()}, ++ * and {@code nextDouble()} methods are likewise approximately 4-equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L128X256MixRandom} + * instance that shares no mutable state with the current instance. However, with +*************** +*** 146,152 **** + * + * @since 14 + */ +- public final class L128X256MixRandom extends AbstractSplittableGenerator { + + /* + * Implementation Overview. +--- 130,136 ---- + * + * @since 14 + */ ++ public final class L128X256MixRandom extends AbstractSplittableWithBrineGenerator { + + /* + * Implementation Overview. +*************** +*** 193,220 **** + BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(128); + + /* +- * The multiplier used in the LCG portion of the algorithm is 2**64 + m; +- * where m is taken from +- * Pierre L'Ecuyer, Tables of linear congruential generators of +- * different sizes and good lattice structure, Mathematics of +- * Computation 68, 225 (January 1999), pages 249-260, +- * Table 4 (first multiplier for size 264). +- * +- * This is almost certainly not the best possible 128-bit multiplier +- * for an LCG, but it is sufficient for our purposes here; because +- * is is larger than 2**64, the 64-bit values produced by nextLong() +- * are exactly 2-equidistributed, and the fact that it is of the +- * form (2**64 + m) simplifies the code, given that we have only +- * 64-bit arithmetic to work with. + */ + +- private static final long M = 2862933555777941757L; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. +- * Must be odd. + */ + private final long ah, al; + +--- 177,196 ---- + BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(128); + + /* ++ * Low half of multiplier used in the LCG portion of the algorithm; ++ * the overall multiplier is (2**64 + ML). ++ * Chosen based on research by Sebastiano Vigna and Guy Steele (2019). ++ * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL ++ * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493]. + */ + ++ private static final long ML = 0xd605bbb58c8abbfdL; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. ++ * Must be odd (therefore al must be odd). + */ + private final long ah, al; + +*************** +*** 252,262 **** + this.x3 = x3; + // If x0, x1, x2, and x3 are all zero, we must choose nonzero values. + if ((x0 | x1 | x2 | x3) == 0) { + // At least three of the four values generated here will be nonzero. +- this.x0 = RandomSupport.mixStafford13(sh += RandomSupport.GOLDEN_RATIO_64); +- this.x1 = RandomSupport.mixStafford13(sh += RandomSupport.GOLDEN_RATIO_64); +- this.x2 = RandomSupport.mixStafford13(sh += RandomSupport.GOLDEN_RATIO_64); +- this.x3 = RandomSupport.mixStafford13(sh + RandomSupport.GOLDEN_RATIO_64); + } + } + +--- 228,239 ---- + this.x3 = x3; + // If x0, x1, x2, and x3 are all zero, we must choose nonzero values. + if ((x0 | x1 | x2 | x3) == 0) { ++ long v = sh; + // At least three of the four values generated here will be nonzero. ++ this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); ++ this.x1 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); ++ this.x2 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); ++ this.x3 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64); + } + } + +*************** +*** 277,283 **** + // The seed is hashed by mixStafford13 to produce the initial `x0`, + // which will then be used to produce the first generated value. + // The other x values are filled in as if by a SplitMix PRNG with +- // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64), + 0, +--- 254,260 ---- + // The seed is hashed by mixStafford13 to produce the initial `x0`, + // which will then be used to produce the first generated value. + // The other x values are filled in as if by a SplitMix PRNG with ++ // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64), + 0, +*************** +*** 323,351 **** + } + + /* ---------------- public methods ---------------- */ +- + /** +- * Constructs and returns a new instance of {@link L128X256MixRandom} +- * that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using +- * a single {@link L128X256MixRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * +- * @param source a {@link SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. +- * @return a new instance of {@link L128X256MixRandom} + */ +- public L128X256MixRandom split(SplittableGenerator source) { +- // Literally pick a new instance "at random". +- return new L128X256MixRandom(source.nextLong(), source.nextLong(), +- source.nextLong(), source.nextLong(), +- source.nextLong(), source.nextLong(), +- source.nextLong(), source.nextLong()); + } + + /** +--- 300,330 ---- + } + + /* ---------------- public methods ---------------- */ ++ + /** ++ * Given 63 bits of "brine", constructs and returns a new instance of ++ * {@code L128X256MixRandom} that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using ++ * a single {@code L128X256MixRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * ++ * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. ++ * @param brine a long value, of which the low 63 bits are used to choose ++ * the {@code a} parameter for the new instance. ++ * @return a new instance of {@code L128X256MixRandom} + */ ++ public SplittableGenerator split(SplittableGenerator source, long brine) { ++ // Pick a new instance "at random", but use the brine for (the low half of) `a`. ++ return new L128X256MixRandom(source.nextLong(), brine << 1, ++ source.nextLong(), source.nextLong(), ++ source.nextLong(), source.nextLong(), ++ source.nextLong(), source.nextLong()); + } + + /** +*************** +*** 354,365 **** + * @return a pseudorandom {@code long} value + */ + public long nextLong() { +- final long z = sh + x0; +- // The LCG: in effect, s = ((1LL << 64) + M) * s + a, if only we had 128-bit arithmetic. +- final long u = M * sl; +- sh = (M * sh) + Math.multiplyHigh(M, sl) + sl + ah; + sl = u + al; + if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. + long q0 = x0, q1 = x1, q2 = x2, q3 = x3; + { // xoshiro256 1.0 + long t = q1 << 17; +--- 333,359 ---- + * @return a pseudorandom {@code long} value + */ + public long nextLong() { ++ // Compute the result based on current state information ++ // (this allows the computation to be overlapped with state update). ++ final long result = RandomSupport.mixLea64(sh + x0); ++ ++ // Update the LCG subgenerator ++ // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic. ++ final long u = ML * sl; ++ // Note that Math.multiplyHigh computes the high half of the product of signed values, ++ // but what we need is the high half of the product of unsigned values; for this we use the ++ // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)"; ++ // in effect, each operand is added to the result iff the sign bit of the other operand is 1. ++ // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013), ++ // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.) ++ // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become: ++ // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah; ++ // and this entire comment can be deleted. ++ sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah; + sl = u + al; + if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half. ++ ++ // Update the Xorshift subgenerator + long q0 = x0, q1 = x1, q2 = x2, q3 = x3; + { // xoshiro256 1.0 + long t = q1 << 17; +*************** +*** 371,379 **** + q3 = Long.rotateLeft(q3, 45); + } + x0 = q0; x1 = q1; x2 = q2; x3 = q3; +- return RandomSupport.mixLea64(z); // mixing function + } + + public BigInteger period() { + return PERIOD; + } +--- 365,379 ---- + q3 = Long.rotateLeft(q3, 45); + } + x0 = q0; x1 = q1; x2 = q2; x3 = q3; ++ return result; + } + ++ /** ++ * Returns the period of this random generator. ++ * ++ * @return a {@link BigInteger} whose value is the number of distinct possible states of this ++ * {@link RandomGenerator} object (2128(2256-1)). ++ */ + public BigInteger period() { + return PERIOD; + } diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/L64X1024MixRandom.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/L64X1024MixRandom.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.SplittableGenerator; +import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link L64X1024MixRandom} implements + * interfaces {@link RandomGenerator} and {@link SplittableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new split-off {@link L64X1024MixRandom} objects, + * with similar usages as for class {@link java.util.SplittableRandom}. + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + * (Most recently validated with + * version 1.2.3 of TestU01 + * and version 0.90 of PractRand. + * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()} + * method but also the result of bit-reversing each value produced by {@code nextLong()}.) + * These tests validate only the methods for certain + * types and ranges, but similar properties are expected to hold, at + * least approximately, for others as well. + *

+ * {@link L64X1024MixRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is + * an Xorshift generator. Each output of an LXM generator is the result of + * combining state from the LCG with state from the Xorshift generator by + * using a Mixing function (and then the state of the LCG and the state of the + * Xorshift generator are advanced). + *

+ * The LCG subgenerator for {@link L64X1024MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all + * of type {@code long}; {@code s} is the mutable state, the multiplier {@code m} + * is fixed (the same for all instances of {@link L64X1024MixRandom}) and the addend + * {@code a} is a parameter (a final field of the instance). The parameter + * {@code a} is required to be odd (this allows the LCG to have the maximal + * period, namely 264); therefore there are 263 distinct choices + * of parameter. + *

+ * The Xorshift subgenerator for {@link L64X1024MixRandom} is the {@code xoroshiro1024} + * algorithm (parameters 25, 27, and 36), without any final scrambler such as "+" or "**". + * Its state consists of an array {@code x} of sixteen {@code long} values, + * which can take on any values provided that they are not all zero. + * The period of this subgenerator is 21024-1. + *

+ * The mixing function for {@link L64X1024MixRandom} is {@link RandomSupport.mixLea64} + * applied to the argument {@code (s + s0)}, where {@code s0} is the most recently computed + * element of {@code x}. + *

+ * Because the periods 264 and 21024-1 of the two subgenerators + * are relatively prime, the period of any single {@link L64X1024MixRandom} object + * (the length of the series of generated 64-bit values before it repeats) is the product + * of the periods of the subgenerators, that is, 264(21024-1), + * which is just slightly smaller than 21088. Moreover, if two distinct + * {@link L64X1024MixRandom} objects have different {@code a} parameters, then their + * cycles of produced values will be different. + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L64X1024MixRandom}, over the course of its cycle each + * of the 264 possible {@code long} values will be produced 21024-1 times. + * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()} + * methods are likewise exactly equidistributed. + *

+ * In fact, the 64-bit values produced by the {@code nextLong()} method are 16-equidistributed. + * To be precise: for any specific instance of {@link L64X1024MixRandom}, consider + * the (overlapping) length-16 subsequences of the cycle of 64-bit values produced by + * {@code nextLong()} (assuming no other methods are called that would affect the state). + * There are 264(21024-1) such subsequences, and each subsequence, + * which consists of 16 64-bit values, can have one of 21024 values. Of those + * 21024 subsequence values, nearly all of them (21024-264) + * occur 264 times over the course of the entire cycle, and the other + * 264 subsequence values occur only 264-1 times. So the ratio + * of the probability of getting any specific one of the less common subsequence values and the + * probability of getting any specific one of the more common subsequence values is 1-2-64. + * (Note that the set of 264 less-common subsequence values will differ from + * one instance of {@link L64X1024MixRandom} to another, as a function of the additive + * parameter of the LCG.) The values produced by the {@code nextInt()}, {@code nextFloat()}, + * and {@code nextDouble()} methods are likewise 16-equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L64X1024MixRandom} + * instance that shares no mutable state with the current instance. However, with + * very high probability, the values collectively generated by the two objects + * have the same statistical properties as if the same quantity of values were + * generated by a single thread using a single {@link L64X1024MixRandom} object. + * This is because, with high probability, distinct {@link L64X1024MixRandom} objects + * have distinct {@code a} parameters and therefore use distinct members of the + * algorithmic family; and even if their {@code a} parameters are the same, with + * very high probability they will traverse different parts of their common state + * cycle. + *

+ * As with {@link java.util.SplittableRandom}, instances of + * {@link L64X1024MixRandom} are not thread-safe. + * They are designed to be split, not shared, across threads. For + * example, a {@link java.util.concurrent.ForkJoinTask} fork/join-style + * computation using random numbers might include a construction + * of the form {@code new Subtask(someL64X1024MixRandom.split()).fork()}. + *

+ * This class provides additional methods for generating random + * streams, that employ the above techniques when used in + * {@code stream.parallel()} mode. + *

+ * Instances of {@link L64X1024MixRandom} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class L64X1024MixRandom extends AbstractSplittableWithBrineGenerator { + + /* + * Implementation Overview. + * + * The split() operation uses the current generator to choose 18 new 64-bit + * long values that are then used to initialize the parameter `a`, the + * state variable `s`, and the array `x` for a newly constructed generator. + * + * With extremely high probability, no two generators so chosen + * will have the same `a` parameter, and testing has indicated + * that the values generated by two instances of {@link L64X1024MixRandom} + * will be (approximately) independent if have different values for `a`. + * + * The default (no-argument) constructor, in essence, uses + * "defaultGen" to generate 18 new 64-bit values for the same + * purpose. Multiple generators created in this way will certainly + * differ in their `a` parameters. The defaultGen state must be accessed + * in a thread-safe manner, so we use an AtomicLong to represent + * this state. To bootstrap the defaultGen, we start off using a + * seed based on current time unless the + * java.util.secureRandomSeed property is set. This serves as a + * slimmed-down (and insecure) variant of SecureRandom that also + * avoids stalls that may occur when using /dev/random. + * + * File organization: First static fields, then instance + * fields, then constructors, then instance methods. + */ + + /* ---------------- static fields ---------------- */ + + /* + * The length of the array x. + */ + + private static final int N = 16; + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is (2**1024 - 1) * 2**64. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(N*64).subtract(BigInteger.ONE).shiftLeft(64); + + /* + * Multiplier used in the LCG portion of the algorithm. + * Chosen based on research by Sebastiano Vigna and Guy Steele (2019). + * The spectral scores for dimensions 2 through 8 for the multiplier 0xd1342543de82ef95 + * are [0.958602, 0.937479, 0.870757, 0.822326, 0.820405, 0.813065, 0.760215]. + */ + + private static final long M = 0xd1342543de82ef95L; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. + * Must be odd. + */ + private final long a; + + /** + * The per-instance state: s for the LCG; the array x for the xorshift; + * p is the rotating pointer into the array x. + * At least one of the 16 elements of the array x must be nonzero. + */ + private long s; + private final long[] x; + private int p = N - 1; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param a additive parameter for the LCG + * @param s initial state for the LCG + * @param x0 first word of the initial state for the xorshift generator + * @param x1 second word of the initial state for the xorshift generator + * @param x2 third word of the initial state for the xorshift generator + * @param x3 fourth word of the initial state for the xorshift generator + * @param x4 fifth word of the initial state for the xorshift generator + * @param x5 sixth word of the initial state for the xorshift generator + * @param x6 seventh word of the initial state for the xorshift generator + * @param x7 eight word of the initial state for the xorshift generator + * @param x8 ninth word of the initial state for the xorshift generator + * @param x9 tenth word of the initial state for the xorshift generator + * @param x10 eleventh word of the initial state for the xorshift generator + * @param x11 twelfth word of the initial state for the xorshift generator + * @param x12 thirteenth word of the initial state for the xorshift generator + * @param x13 fourteenth word of the initial state for the xorshift generator + * @param x14 fifteenth word of the initial state for the xorshift generator + * @param x15 sixteenth word of the initial state for the xorshift generator + */ + public L64X1024MixRandom(long a, long s, + long x0, long x1, long x2, long x3, + long x4, long x5, long x6, long x7, + long x8, long x9, long x10, long x11, + long x12, long x13, long x14, long x15) { + // Force a to be odd. + this.a = a | 1; + this.s = s; + this.x = new long[N]; + this.x[0] = x0; + this.x[1] = x1; + this.x[2] = x2; + this.x[3] = x3; + this.x[4] = x4; + this.x[5] = x5; + this.x[6] = x6; + this.x[7] = x7; + this.x[8] = x8; + this.x[9] = x9; + this.x[10] = x10; + this.x[11] = x11; + this.x[12] = x12; + this.x[13] = x13; + this.x[14] = x14; + this.x[15] = x15; + // If x0, x1, ..., x15 are all zero (very unlikely), we must choose nonzero values. + if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) { + long v = s; + // At least fifteen of the sixteen values generated here will be nonzero. + for (int j = 0; j < N; j++) { + this.x[j] = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + } + } + } + + /** + * Creates a new instance of {@link L64X1024MixRandom} using the + * specified {@code long} value as the initial seed. Instances of + * {@link L64X1024MixRandom} created with the same seed in the same + * program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L64X1024MixRandom(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The seed is hashed by mixMurmur64 to produce the `a` parameter. + // The seed is hashed by mixStafford13 to produce the initial `x[0]`, + // which will then be used to produce the first generated value. + // The other x values are filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + 1, + RandomSupport.mixStafford13(seed), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L64X1024MixRandom} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public L64X1024MixRandom() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L64X1024MixRandom} using the specified array of + * initial seed bytes. Instances of {@link L64X1024MixRandom} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L64X1024MixRandom(byte[] seed) { + // Convert the seed to 18 long values, of which the last 16 are not all zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 18, 16); + long a = data[0], s = data[1]; + // Force a to be odd. + this.a = a | 1; + this.s = s; + this.x = new long[N]; + for (int j = 0; j < N; j++) { + this.x[j] = data[2+j]; + } + } + + /* ---------------- public methods ---------------- */ + /** + * Given 63 bits of "brine", constructs and returns a new instance of + * {@code L64X1024MixRandom} that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using + * a single {@code L64X1024MixRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @param brine a long value, of which the low 63 bits are used to choose + * the {@code a} parameter for the new instance. + * @return a new instance of {@code L64X1024MixRandom} + */ + public SplittableGenerator split(SplittableGenerator source, long brine) { + // Pick a new instance "at random", but use the brine for `a`. + return new L64X1024MixRandom(brine << 1, source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong()); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + // First part of xoroshiro1024: fetch array data + final int q = p; + final long s0 = x[p = (p + 1) & (N - 1)]; + long s15 = x[q]; + + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + + final long result = RandomSupport.mixLea64(s + s0); + + // Update the LCG subgenerator + s = M * s + a; // LCG + + // Second part of xoroshiro1024: update array data + s15 ^= s0; + x[q] = Long.rotateLeft(s0, 25) ^ s15 ^ (s15 << 27); + x[p] = Long.rotateLeft(s15, 36); + + return result; + } + + /** + * Returns the period of this random generator. + * + * @return a {@link BigInteger} whose value is the number of distinct possible states of this + * {@link RandomGenerator} object (264(21024-1)). + */ + public BigInteger period() { + return PERIOD; + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/L64X128MixRandom.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/L64X128MixRandom.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.SplittableGenerator; +import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link L64X128MixRandom} implements + * interfaces {@link RandomGenerator} and {@link SplittableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new split-off {@link L64X128MixRandom} objects, + * with similar usages as for class {@link java.util.SplittableRandom}. + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + * (Most recently validated with + * version 1.2.3 of TestU01 + * and version 0.90 of PractRand. + * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()} + * method but also the result of bit-reversing each value produced by {@code nextLong()}.) + * These tests validate only the methods for certain + * types and ranges, but similar properties are expected to hold, at + * least approximately, for others as well. + *

+ * {@link L64X128MixRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is + * an Xorshift generator. Each output of an LXM generator is the result of + * combining state from the LCG with state from the Xorshift generator by + * using a Mixing function (and then the state of the LCG and the state of the + * Xorshift generator are advanced). + *

+ * The LCG subgenerator for {@link L64X128MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all + * of type {@code long}; {@code s} is the mutable state, the multiplier {@code m} + * is fixed (the same for all instances of {@link L64X128MixRandom}}) and the addend + * {@code a} is a parameter (a final field of the instance). The parameter + * {@code a} is required to be odd (this allows the LCG to have the maximal + * period, namely 264); therefore there are 263 distinct choices + * of parameter. + *

+ * The Xorshift subgenerator for {@link L64X128MixRandom} is the {@code xoroshiro128} algorithm, + * version 1.0 (parameters 24, 16, 37), without any final scrambler such as "+" or "**". + * Its state consists of two {@code long} fields {@code x0} and {@code x1}, + * which can take on any values provided that they are not both zero. + * The period of this subgenerator is 2128-1. + *

+ * The mixing function for {@link L64X128MixRandom} is {@link RandomSupport.mixLea64} + * applied to the argument {@code (s + x0)}. + *

+ * Because the periods 264 and 2128-1 of the two subgenerators + * are relatively prime, the period of any single {@link L64X128MixRandom} object + * (the length of the series of generated 64-bit values before it repeats) is the product + * of the periods of the subgenerators, that is, 264(2128-1), + * which is just slightly smaller than 2192. Moreover, if two distinct + * {@link L64X128MixRandom} objects have different {@code a} parameters, then their + * cycles of produced values will be different. + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L64X128MixRandom}, over the course of its cycle each + * of the 264 possible {@code long} values will be produced 2128-1 times. + * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()} + * methods are likewise exactly equidistributed. + *

+ * In fact, the 64-bit values produced by the {@code nextLong()} method are 2-equidistributed. + * To be precise: for any specific instance of {@link L64X128MixRandom}, consider + * the (overlapping) length-2 subsequences of the cycle of 64-bit values produced by + * {@code nextLong()} (assuming no other methods are called that would affect the state). + * There are 264(2128-1) such subsequences, and each subsequence, + * which consists of 2 64-bit values, can have one of 2128 values. Of those + * 2128 subsequence values, nearly all of them (2128-264) + * occur 264 times over the course of the entire cycle, and the other + * 264 subsequence values occur only 264-1 times. So the ratio + * of the probability of getting any specific one of the less common subsequence values and the + * probability of getting any specific one of the more common subsequence values is 1-2-64. + * (Note that the set of 264 less-common subsequence values will differ from + * one instance of {@link L64X128MixRandom} to another, as a function of the additive + * parameter of the LCG.) The values produced by the {@code nextInt()}, {@code nextFloat()}, + * and {@code nextDouble()} methods are likewise 2-equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L64X128MixRandom} + * instance that shares no mutable state with the current instance. However, with + * very high probability, the values collectively generated by the two objects + * have the same statistical properties as if the same quantity of values were + * generated by a single thread using a single {@link L64X128MixRandom} object. + * This is because, with high probability, distinct {@link L64X128MixRandom} objects + * have distinct {@code a} parameters and therefore use distinct members of the + * algorithmic family; and even if their {@code a} parameters are the same, with + * very high probability they will traverse different parts of their common state + * cycle. + *

+ * As with {@link java.util.SplittableRandom}, instances of + * {@link L64X128MixRandom} are not thread-safe. + * They are designed to be split, not shared, across threads. For + * example, a {@link java.util.concurrent.ForkJoinTask} fork/join-style + * computation using random numbers might include a construction + * of the form {@code new Subtask(someL64X128MixRandom.split()).fork()}. + *

+ * This class provides additional methods for generating random + * streams, that employ the above techniques when used in + * {@code stream.parallel()} mode. + *

+ * Instances of {@link L64X128MixRandom} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class L64X128MixRandom extends AbstractSplittableWithBrineGenerator { + + /* + * Implementation Overview. + * + * The split operation uses the current generator to choose four new 64-bit + * long values that are then used to initialize the parameter `a` and the + * state variables `s`, `x0`, and `x1` for a newly constructed generator. + * + * With extremely high probability, no two generators so chosen + * will have the same `a` parameter, and testing has indicated + * that the values generated by two instances of {@link L64X128MixRandom} + * will be (approximately) independent if have different values for `a`. + * + * The default (no-argument) constructor, in essence, uses + * "defaultGen" to generate four new 64-bit values for the same + * purpose. Multiple generators created in this way will certainly + * differ in their `a` parameters. The defaultGen state must be accessed + * in a thread-safe manner, so we use an AtomicLong to represent + * this state. To bootstrap the defaultGen, we start off using a + * seed based on current time unless the + * java.util.secureRandomSeed property is set. This serves as a + * slimmed-down (and insecure) variant of SecureRandom that also + * avoids stalls that may occur when using /dev/random. + * + * File organization: First static fields, then instance + * fields, then constructors, then instance methods. + */ + + /* ---------------- static fields ---------------- */ + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is (2**128 - 1) * 2**64. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(64); + + /* + * Multiplier used in the LCG portion of the algorithm. + * Chosen based on research by Sebastiano Vigna and Guy Steele (2019). + * The spectral scores for dimensions 2 through 8 for the multiplier 0xd1342543de82ef95 + * are [0.958602, 0.937479, 0.870757, 0.822326, 0.820405, 0.813065, 0.760215]. + */ + + private static final long M = 0xd1342543de82ef95L; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. + * Must be odd. + */ + private final long a; + + /** + * The per-instance state: s for the LCG; x0 and x1 for the xorshift. + * At least one of x0 and x1 must be nonzero. + */ + private long s, x0, x1; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param a additive parameter for the LCG + * @param s initial state for the LCG + * @param x0 first word of the initial state for the xorshift generator + * @param x1 second word of the initial state for the xorshift generator + */ + public L64X128MixRandom(long a, long s, long x0, long x1) { + // Force a to be odd. + this.a = a | 1; + this.s = s; + this.x0 = x0; + this.x1 = x1; + // If x0 and x1 are both zero, we must choose nonzero values. + if ((x0 | x1) == 0) { + long v = s; + // At least one of the two values generated here will be nonzero. + this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x1 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64); + } + } + + /** + * Creates a new instance of {@link L64X128MixRandom} using the + * specified {@code long} value as the initial seed. Instances of + * {@link L64X128MixRandom} created with the same seed in the same + * program generate identical sequences of values. + * + * @param seed the initial seed + */ + public L64X128MixRandom(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The seed is hashed by mixMurmur64 to produce the `a` parameter. + // The seed is hashed by mixStafford13 to produce the initial `x0`, + // which will then be used to produce the first generated value. + // Then x1 is filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + 1, + RandomSupport.mixStafford13(seed), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L64X128MixRandom} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public L64X128MixRandom() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L64X128MixRandom} using the specified array of + * initial seed bytes. Instances of {@link L64X128MixRandom} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L64X128MixRandom(byte[] seed) { + // Convert the seed to 4 long values, of which the last 2 are not all zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 4, 2); + long a = data[0], s = data[1], x0 = data[2], x1 = data[3]; + // Force a to be odd. + this.a = a | 1; + this.s = s; + this.x0 = x0; + this.x1 = x1; + } + + /* ---------------- public methods ---------------- */ + + /** + * Given 63 bits of "brine", constructs and returns a new instance of + * {@code L64X128MixRandom} that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using + * a single {@code L64X128MixRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @param brine a long value, of which the low 63 bits are used to choose + * the {@code a} parameter for the new instance. + * @return a new instance of {@code L64X128MixRandom} + */ + public SplittableGenerator split(SplittableGenerator source, long brine) { + // Pick a new instance "at random", but use the brine for `a`. + return new L64X128MixRandom(brine << 1, source.nextLong(), + source.nextLong(), source.nextLong()); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + final long result = RandomSupport.mixLea64(s + x0); + // Update the LCG subgenerator + s = M * s + a; + // Update the Xorshift subgenerator + long q0 = x0, q1 = x1; + { // xoroshiro128v1_0 + q1 ^= q0; + q0 = Long.rotateLeft(q0, 24); + q0 = q0 ^ q1 ^ (q1 << 16); + q1 = Long.rotateLeft(q1, 37); + } + x0 = q0; x1 = q1; + return result; + } + + /** + * Returns the period of this random generator. + * + * @return a {@link BigInteger} whose value is the number of distinct possible states of this + * {@link RandomGenerator} object (264(2128-1)). + */ + public BigInteger period() { + return PERIOD; + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/L64X256MixRandom.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/L64X256MixRandom.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.SplittableGenerator; +import java.util.random.RandomSupport.AbstractSplittableWithBrineGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link L64X256MixRandom} implements + * interfaces {@link RandomGenerator} and {@link SplittableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new split-off {@link L64X256MixRandom} objects, + * with similar usages as for class {@link java.util.SplittableRandom}. + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + * (Most recently validated with + * version 1.2.3 of TestU01 + * and version 0.90 of PractRand. + * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()} + * method but also the result of bit-reversing each value produced by {@code nextLong()}.) + * These tests validate only the methods for certain + * types and ranges, but similar properties are expected to hold, at + * least approximately, for others as well. + *

+ * {@link L64X256MixRandom} is a specific member of the LXM family of algorithms + * for pseudorandom number generators. Every LXM generator consists of two + * subgenerators; one is an LCG (Linear Congruential Generator) and the other is + * an Xorshift generator. Each output of an LXM generator is the result of + * combining state from the LCG with state from the Xorshift generator by + * using a Mixing function (and then the state of the LCG and the state of the + * Xorshift generator are advanced). + *

+ * The LCG subgenerator for {@link L64X256MixRandom} has an update step of the + * form {@code s = m * s + a}, where {@code s}, {@code m}, and {@code a} are all + * of type {@code long}; {@code s} is the mutable state, the multiplier {@code m} + * is fixed (the same for all instances of {@link L64X256MixRandom}) and the addend + * {@code a} is a parameter (a final field of the instance). The parameter + * {@code a} is required to be odd (this allows the LCG to have the maximal + * period, namely 264); therefore there are 263 distinct choices + * of parameter. + *

+ * The Xorshift subgenerator for {@link L64X256MixRandom} is the {@code xoshiro256} algorithm, + * version 1.0 (parameters 17, 45), without any final scrambler such as "+" or "**". + * Its state consists of four {@code long} fields {@code x0}, {@code x1}, {@code x2}, + * and {@code x3}, which can take on any values provided that they are not all zero. + * The period of this subgenerator is 2256-1. + *

+ * The mixing function for {@link L64X256MixRandom} is {@link RandomSupport.mixLea64} + * applied to the argument {@code (s + x0)}. + *

+ * Because the periods 264 and 2256-1 of the two subgenerators + * are relatively prime, the period of any single {@link L64X256MixRandom} object + * (the length of the series of generated 64-bit values before it repeats) is the product + * of the periods of the subgenerators, that is, 264(2256-1), + * which is just slightly smaller than 2320. Moreover, if two distinct + * {@link L64X256MixRandom} objects have different {@code a} parameters, then their + * cycles of produced values will be different. + *

+ * The 64-bit values produced by the {@code nextLong()} method are exactly equidistributed. + * For any specific instance of {@link L64X256MixRandom}, over the course of its cycle each + * of the 264 possible {@code long} values will be produced 2256-1 times. + * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()} + * methods are likewise exactly equidistributed. + *

+ * In fact, the 64-bit values produced by the {@code nextLong()} method are 4-equidistributed. + * To be precise: for any specific instance of {@link L64X256MixRandom}, consider + * the (overlapping) length-4 subsequences of the cycle of 64-bit values produced by + * {@code nextLong()} (assuming no other methods are called that would affect the state). + * There are 264(2256-1) such subsequences, and each subsequence, + * which consists of 4 64-bit values, can have one of 2256 values. Of those + * 2256 subsequence values, nearly all of them (2256-264) + * occur 264 times over the course of the entire cycle, and the other + * 264 subsequence values occur only 264-1 times. So the ratio + * of the probability of getting any specific one of the less common subsequence values and the + * probability of getting any specific one of the more common subsequence values is 1-2-64. + * (Note that the set of 264 less-common subsequence values will differ from + * one instance of {@link L64X256MixRandom} to another, as a function of the additive + * parameter of the LCG.) The values produced by the {@code nextInt()}, {@code nextFloat()}, + * and {@code nextDouble()} methods are likewise 4-equidistributed. + *

+ * Method {@link #split} constructs and returns a new {@link L64X256MixRandom} + * instance that shares no mutable state with the current instance. However, with + * very high probability, the values collectively generated by the two objects + * have the same statistical properties as if the same quantity of values were + * generated by a single thread using a single {@link L64X256MixRandom} object. + * This is because, with high probability, distinct {@link L64X256MixRandom} objects + * have distinct {@code a} parameters and therefore use distinct members of the + * algorithmic family; and even if their {@code a} parameters are the same, with + * very high probability they will traverse different parts of their common state + * cycle. + *

+ * As with {@link java.util.SplittableRandom}, instances of + * {@link L64X256MixRandom} are not thread-safe. + * They are designed to be split, not shared, across threads. For + * example, a {@link java.util.concurrent.ForkJoinTask} fork/join-style + * computation using random numbers might include a construction + * of the form {@code new Subtask(someL64X256MixRandom.split()).fork()}. + *

+ * This class provides additional methods for generating random + * streams, that employ the above techniques when used in + * {@code stream.parallel()} mode. + *

+ * Instances of {@link L64X256MixRandom} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class L64X256MixRandom extends AbstractSplittableWithBrineGenerator { + + /* + * Implementation Overview. + * + * The split operation uses the current generator to choose six new 64-bit + * long values that are then used to initialize the parameter `a` and the + * state variables `s`, `x0`, `x1`, `x2`, and `x3` for a newly constructed + * generator. + * + * With extremely high probability, no two generators so chosen + * will have the same `a` parameter, and testing has indicated + * that the values generated by two instances of {@link L64X256MixRandom} + * will be (approximately) independent if have different values for `a`. + * + * The default (no-argument) constructor, in essence, uses + * "defaultGen" to generate six new 64-bit values for the same + * purpose. Multiple generators created in this way will certainly + * differ in their `a` parameters. The defaultGen state must be accessed + * in a thread-safe manner, so we use an AtomicLong to represent + * this state. To bootstrap the defaultGen, we start off using a + * seed based on current time unless the + * java.util.secureRandomSeed property is set. This serves as a + * slimmed-down (and insecure) variant of SecureRandom that also + * avoids stalls that may occur when using /dev/random. + * + * File organization: First static fields, then instance + * fields, then constructors, then instance methods. + */ + + /* ---------------- static fields ---------------- */ + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is (2**256 - 1) * 2**64. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(64); + + /* + * Multiplier used in the LCG portion of the algorithm. + * Chosen based on research by Sebastiano Vigna and Guy Steele (2019). + * The spectral scores for dimensions 2 through 8 for the multiplier 0xd1342543de82ef95 + * are [0.958602, 0.937479, 0.870757, 0.822326, 0.820405, 0.813065, 0.760215]. + */ + + private static final long M = 0xd1342543de82ef95L; + + /* ---------------- instance fields ---------------- */ + + /** + * The parameter that is used as an additive constant for the LCG. + * Must be odd. + */ + private final long a; + + /** + * The per-instance state: s for the LCG; x0, x1, x2, and x3 for the xorshift. + * At least one of the four fields x0, x1, x2, and x3 must be nonzero. + */ + private long s, x0, x1, x2, x3; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param a additive parameter for the LCG + * @param s initial state for the LCG + * @param x0 first word of the initial state for the xorshift generator + * @param x1 second word of the initial state for the xorshift generator + * @param x2 third word of the initial state for the xorshift generator + * @param x3 fourth word of the initial state for the xorshift generator + */ + public L64X256MixRandom(long a, long s, long x0, long x1, long x2, long x3) { + // Force a to be odd. + this.a = a | 1; + this.s = s; + this.x0 = x0; + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + // If x0, x1, x2, and x3 are all zero, we must choose nonzero values. + if ((x0 | x1 | x2 | x3) == 0) { + long v = s; + // At least three of the four values generated here will be nonzero. + this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x1 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x2 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64); + this.x3 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64); + } + } + + /** + * Creates a new instance of {@link L64X256MixRandom} using the + * specified {@code long} value as the initial seed. Instances of + * {@link L64X256MixRandom} created with the same seed in the same + * program generate identical sequences of values. + * + * @param seed the initial seed + */ + public L64X256MixRandom(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The seed is hashed by mixMurmur64 to produce the `a` parameter. + // The seed is hashed by mixStafford13 to produce the initial `x0`, + // which will then be used to produce the first generated value. + // The other x values are filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and mixStafford13 as the mixer. + this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64), + 1, + RandomSupport.mixStafford13(seed), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L64X256MixRandom} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public L64X256MixRandom() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link L64X256MixRandom} using the specified array of + * initial seed bytes. Instances of {@link L64X256MixRandom} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public L64X256MixRandom(byte[] seed) { + // Convert the seed to 6 long values, of which the last 4 are not all zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 4); + long a = data[0], s = data[1], x0 = data[2], x1 = data[3], x2 = data[4], x3 = data[5]; + // Force a to be odd. + this.a = a | 1; + this.s = s; + this.x0 = x0; + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + } + + /* ---------------- public methods ---------------- */ + + /** + * Given 63 bits of "brine", constructs and returns a new instance of + * {@code L64X256MixRandom} that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using + * a single {@code L64X256MixRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @param brine a long value, of which the low 63 bits are used to choose + * the {@code a} parameter for the new instance. + * @return a new instance of {@code L64X256MixRandom} + */ + public SplittableGenerator split(SplittableGenerator source, long brine) { + // Pick a new instance "at random", but use the brine for `a`. + return new L64X256MixRandom(brine << 1, source.nextLong(), + source.nextLong(), source.nextLong(), + source.nextLong(), source.nextLong()); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + final long result = RandomSupport.mixLea64(s + x0); + // Update the LCG subgenerator + s = M * s + a; + // Update the Xorshift subgenerator + long q0 = x0, q1 = x1, q2 = x2, q3 = x3; + { // xoshiro256 1.0 + long t = q1 << 17; + q2 ^= q0; + q3 ^= q1; + q1 ^= q2; + q0 ^= q3; + q2 ^= t; + q3 = Long.rotateLeft(q3, 45); + } + x0 = q0; x1 = q1; x2 = q2; x3 = q3; + return result; + } + + /** + * Returns the period of this random generator. + * + * @return a {@link BigInteger} whose value is the number of distinct possible states of this + * {@link RandomGenerator} object (264(2256-1)). + */ + public BigInteger period() { + return PERIOD; + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/MRG32k3a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/MRG32k3a.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.LeapableGenerator; +import java.util.random.RandomSupport.AbstractArbitrarilyJumpableGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link MRG32k3a} implements + * interfaces {@link RandomGenerator} and {@link AbstractArbitrarilyJumpableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new {@link Xoroshiro128PlusMRG32k3a} objects + * by "jumping" or "leaping". + *

+ * Instances {@link Xoroshiro128Plus} are not thread-safe. + * They are designed to be used so that each thread as its own instance. + * The methods {@link #jump} and {@link #leap} and {@link #jumps} and {@link #leaps} + * can be used to construct new instances of {@link Xoroshiro128Plus} that traverse + * other parts of the state cycle. + *

+ * Instances of {@link MRG32k3a} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class MRG32k3a extends AbstractArbitrarilyJumpableGenerator { + + /* + * Implementation Overview. + * + * See http://simul.iro.umontreal.ca/rng/MRG32k3a.c . + * + * File organization: First the non-public methods that constitute + * the main algorithm, then the main public methods, followed by + * some custom spliterator classes needed for stream methods. + */ + + private final static double NORM1 = 2.328306549295728e-10; + private final static double NORM2 = 2.328318824698632e-10; + private final static double M1 = 4294967087.0; + private final static double M2 = 4294944443.0; + private final static double A12 = 1403580.0; + private final static double A13N = 810728.0; + private final static double A21 = 527612.0; + private final static double A23N = 1370589.0; + private final static int M1_DEFICIT = 209; + + /** + * The per-instance state. + The seeds for s10, s11, s12 must be integers in [0, m1 - 1] and not all 0. + The seeds for s20, s21, s22 must be integers in [0, m2 - 1] and not all 0. + */ + private double s10, s11, s12, + s20, s21, s22; + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong DEFAULT_GEN = + new AtomicLong(RandomSupport.initialSeed()); + + /* + 32-bits Random number generator U(0,1): MRG32k3a + Author: Pierre L'Ecuyer, + Source: Good Parameter Sets for Combined Multiple Recursive Random + Number Generators, + Shorter version in Operations Research, + 47, 1 (1999), 159--164. + --------------------------------------------------------- + */ + + private void nextState() { + /* Component 1 */ + double p1 = A12 * s11 - A13N * s10; + double k1 = p1 / M1; p1 -= k1 * M1; if (p1 < 0.0) p1 += M1; + s10 = s11; s11 = s12; s12 = p1; + /* Component 2 */ + double p2 = A21 * s22 - A23N * s20; + double k2 = p2 / M2; p2 -= k2 * M2; if (p2 < 0.0) p2 += M2; + s20 = s21; s21 = s22; s22 = p2; + } + + + /** + * The form of nextInt used by IntStream Spliterators. + * Exactly the same as long version, except for types. + * + * @param origin the least value, unless greater than bound + * @param bound the upper bound (exclusive), must not equal origin + * + * @return a pseudorandom value + */ + private int internalNextInt(int origin, int bound) { + if (origin < bound) { + final int n = bound - origin; + final int m = n - 1; + if (n > 0) { + int r; + for (int u = (int)nextDouble() >>> 1; + u + m + ((M1_DEFICIT + 1) >>> 1) - (r = u % n) < 0; + u = (int)nextDouble() >>> 1) + ; + return (r + origin); + } else { + return RandomSupport.boundedNextInt(this, origin, bound); + } + } else { + return nextInt(); + } + } + + private int internalNextInt(int bound) { + // Specialize internalNextInt for origin == 0, bound > 0 + final int n = bound; + final int m = n - 1; + int r; + for (int u = (int)nextDouble() >>> 1; + u + m + ((M1_DEFICIT + 1) >>> 1) - (r = u % n) < 0; + u = (int)nextDouble() >>> 1) + ; + return r; + } + + /** + * All arguments must be known to be nonnegative integral values + * less than the appropriate modulus. + */ + private MRG32k3a(double s10, double s11, double s12, + double s20, double s21, double s22) { + this.s10 = s10; this.s11 = s11; this.s12 = s12; + this.s20 = s20; this.s21 = s21; this.s22 = s22; + if ((s10 == 0.0) && (s11 == 0.0) && (s12 == 0.0)) { + this.s10 = this.s11 = this.s12 = 12345.0; + } + if ((s20 == 0.0) && (s21 == 0.0) && (s22 == 0.0)) { + this.s20 = this.s21 = this.s21 = 12345.0; + } + } + + /* ---------------- public methods ---------------- */ + + /** + * Creates a new MRG32k3a instance using six specified {@code int} + * initial seed values. MRG32k3a instances created with the same + * seeds in the same program generate identical sequences of values. + * If all six seed values are zero, the generator is seeded to a + * widely used initialization of MRG32k3a: all six state variables + * are set to 12345. + * + * @param s10 the first seed value for the first subgenerator + * @param s11 the second seed value for the first subgenerator + * @param s12 the third seed value for the first subgenerator + * @param s20 the first seed value for the second subgenerator + * @param s21 the second seed value for the second subgenerator + * @param s22 the third seed value for the second subgenerator + */ + public MRG32k3a(int s10, int s11, int s12, + int s20, int s21, int s22) { + this(((double)(((long)s10) & 0x00000000ffffffffL)) % M1, + ((double)(((long)s11) & 0x00000000ffffffffL)) % M1, + ((double)(((long)s12) & 0x00000000ffffffffL)) % M1, + ((double)(((long)s20) & 0x00000000ffffffffL)) % M2, + ((double)(((long)s21) & 0x00000000ffffffffL)) % M2, + ((double)(((long)s22) & 0x00000000ffffffffL)) % M2); + } + + /** + * Creates a new MRG32k3a instance using the specified + * initial seed. MRG32k3a instances created with the same + * seed in the same program generate identical sequences of values. + * An argument of 0 seeds the generator to a widely used initialization + * of MRG32k3a: all six state variables are set to 12345. + * + * @param seed the initial seed + */ + public MRG32k3a(long seed) { + this((double)((seed & 0x7FF) + 12345), + (double)(((seed >>> 11) & 0x7FF) + 12345), + (double)(((seed >>> 22) & 0x7FF) + 12345), + (double)(((seed >>> 33) & 0x7FF) + 12345), + (double)(((seed >>> 44) & 0x7FF) + 12345), + (double)((seed >>> 55) + 12345)); + } + + /** + * Creates a new MRG32k3a instance that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program; and + * may, and typically does, vary across program invocations. + */ + public MRG32k3a() { + this(DEFAULT_GEN.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link Xoshiro256StarStar} using the specified array of + * initial seed bytes. Instances of {@link Xoshiro256StarStar} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public MRG32k3a(byte[] seed) { + // Convert the seed to 6 int values. + int[] data = RandomSupport.convertSeedBytesToInts(seed, 6, 0); + int s10 = data[0], s11 = data[1], s12 = data[2]; + int s20 = data[3], s21 = data[4], s22 = data[5]; + this.s10 = ((double)(((long)s10) & 0x00000000ffffffffL)) % M1; + this.s11 = ((double)(((long)s11) & 0x00000000ffffffffL)) % M1; + this.s12 = ((double)(((long)s12) & 0x00000000ffffffffL)) % M1; + this.s20 = ((double)(((long)s20) & 0x00000000ffffffffL)) % M2; + this.s21 = ((double)(((long)s21) & 0x00000000ffffffffL)) % M2; + this.s22 = ((double)(((long)s22) & 0x00000000ffffffffL)) % M2; + if ((s10 == 0.0) && (s11 == 0.0) && (s12 == 0.0)) { + this.s10 = this.s11 = this.s12 = 12345.0; + } + if ((s20 == 0.0) && (s21 == 0.0) && (s22 == 0.0)) { + this.s20 = this.s21 = this.s21 = 12345.0; + } + } + + public MRG32k3a copy() { + return new MRG32k3a(s10, s11, s12, s20, s21, s22); + } + + /** + * Returns a pseudorandom {@code double} value between zero + * (exclusive) and one (exclusive). + * + * @return a pseudorandom {@code double} value between zero + * (exclusive) and one (exclusive) + */ + public double nextOpenDouble() { + nextState(); + double p1 = s12, p2 = s22; + if (p1 <= p2) + return ((p1 - p2 + M1) * NORM1); + else + return ((p1 - p2) * NORM1); + } + + /** + * Returns a pseudorandom {@code double} value between zero + * (inclusive) and one (exclusive). + * + * @return a pseudorandom {@code double} value between zero + * (inclusive) and one (exclusive) + */ + public double nextDouble() { + nextState(); + double p1 = s12, p2 = s22; + final double p = p1 * NORM1 - p2 * NORM2; + if (p < 0.0) return (p + 1.0); + else return p; + } + + + /** + * Returns a pseudorandom {@code float} value between zero + * (inclusive) and one (exclusive). + * + * @return a pseudorandom {@code float} value between zero + * (inclusive) and one (exclusive) + */ + public float nextFloat() { + return (float)nextDouble(); + } + + /** + * Returns a pseudorandom {@code int} value. + * + * @return a pseudorandom {@code int} value + */ + public int nextInt() { + return (internalNextInt(0x10000) << 16) | internalNextInt(0x10000); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + + public long nextLong() { + return (((long)internalNextInt(0x200000) << 43) | + ((long)internalNextInt(0x200000) << 22) | + ((long)internalNextInt(0x400000))); + } + + // Period is (m1**3 - 1)(m2**3 - 1)/2, or approximately 2**191. + static BigInteger calculateThePeriod() { + BigInteger bigm1 = BigInteger.valueOf((long)M1); + BigInteger bigm2 = BigInteger.valueOf((long)M2); + BigInteger t1 = bigm1.multiply(bigm1).multiply(bigm1).subtract(BigInteger.ONE); + BigInteger t2 = bigm2.multiply(bigm2).multiply(bigm2).subtract(BigInteger.ONE); + return t1.shiftRight(1).multiply(t2); + } + + static final BigInteger PERIOD = calculateThePeriod(); + + public BigInteger period() { + return PERIOD; + } + + // Jump and leap distances recommended in Section 1.3 of this paper: + // Pierre L'Ecuyer, Richard Simard, E. Jack Chen, and W. David Kelton. + // An Object-Oriented Random-Number Package with Many Long Streams and Substreams. + // Operations Research 50, 6 (Nov--Dec 2002), 1073--1075. + + public double defaultJumpDistance() { + return 0x1.0p76; // 2**76 + } + + public double defaultLeapDistance() { + return 0x1.0p127; // 2**127 + } + + public void jump(double distance) { + if (distance < 0.0 || Double.isInfinite(distance) || distance != Math.floor(distance)) + throw new IllegalArgumentException("jump distance must be a nonnegative finite integer"); + // We will compute a jump transformation (s => M s) for each LCG. + // We initialize each transformation to the identity transformation. + // Each will be turned into the d'th power of the corresponding base transformation. + long m1_00 = 1, m1_01 = 0, m1_02 = 0, + m1_10 = 0, m1_11 = 1, m1_12 = 0, + m1_20 = 0, m1_21 = 0, m1_22 = 1; + long m2_00 = 1, m2_01 = 0, m2_02 = 0, + m2_10 = 0, m2_11 = 1, m2_12 = 0, + m2_20 = 0, m2_21 = 0, m2_22 = 1; + // These are the base transformations, which will be repeatedly squared, + // and composed with the computed transformations for each 1-bit in distance. + long t1_00 = 0, t1_01 = 1, t1_02 = 0, + t1_10 = 0, t1_11 = 0, t1_12 = 1, + t1_20 = -(long)A13N, t1_21 = (long)A12, t1_22 = 0; + long t2_00 = 0, t2_01 = 1, t2_02 = 0, + t2_10 = 0, t2_11 = 0, t2_12 = 1, + t2_20 = -(long)A23N, t2_21 = (long)A21, t2_22 = 0; + while (distance > 0.0) { + final double dhalf = 0.5 * distance; + if (Math.floor(dhalf) != dhalf) { + // distance is odd: accumulate current squaring + final long n1_00 = m1_00 * t1_00 + m1_01 * t1_10 + m1_02 * t1_20; + final long n1_01 = m1_00 * t1_01 + m1_01 * t1_11 + m1_02 * t1_21; + final long n1_02 = m1_00 * t1_02 + m1_01 * t1_12 + m1_02 * t1_22; + final long n1_10 = m1_10 * t1_00 + m1_11 * t1_10 + m1_12 * t1_20; + final long n1_11 = m1_10 * t1_01 + m1_11 * t1_11 + m1_12 * t1_21; + final long n1_12 = m1_10 * t1_02 + m1_11 * t1_12 + m1_12 * t1_22; + final long n1_20 = m1_20 * t1_00 + m1_21 * t1_10 + m1_22 * t1_20; + final long n1_21 = m1_20 * t1_01 + m1_21 * t1_11 + m1_22 * t1_21; + final long n1_22 = m1_20 * t1_02 + m1_21 * t1_12 + m1_22 * t1_22; + m1_00 = Math.floorMod(n1_00, (long)M1); + m1_01 = Math.floorMod(n1_01, (long)M1); + m1_02 = Math.floorMod(n1_02, (long)M1); + m1_10 = Math.floorMod(n1_10, (long)M1); + m1_11 = Math.floorMod(n1_11, (long)M1); + m1_12 = Math.floorMod(n1_12, (long)M1); + m1_20 = Math.floorMod(n1_20, (long)M1); + m1_21 = Math.floorMod(n1_21, (long)M1); + m1_22 = Math.floorMod(n1_22, (long)M1); + final long n2_00 = m2_00 * t2_00 + m2_01 * t2_10 + m2_02 * t2_20; + final long n2_01 = m2_00 * t2_01 + m2_01 * t2_11 + m2_02 * t2_21; + final long n2_02 = m2_00 * t2_02 + m2_01 * t2_12 + m2_02 * t2_22; + final long n2_10 = m2_10 * t2_00 + m2_11 * t2_10 + m2_12 * t2_20; + final long n2_11 = m2_10 * t2_01 + m2_11 * t2_11 + m2_12 * t2_21; + final long n2_12 = m2_10 * t2_02 + m2_11 * t2_12 + m2_12 * t2_22; + final long n2_20 = m2_20 * t2_00 + m2_21 * t2_10 + m2_22 * t2_20; + final long n2_21 = m2_20 * t2_01 + m2_21 * t2_11 + m2_22 * t2_21; + final long n2_22 = m2_20 * t2_02 + m2_21 * t2_12 + m2_22 * t2_22; + m2_00 = Math.floorMod(n2_00, (long)M2); + m2_01 = Math.floorMod(n2_01, (long)M2); + m2_02 = Math.floorMod(n2_02, (long)M2); + m2_10 = Math.floorMod(n2_10, (long)M2); + m2_11 = Math.floorMod(n2_11, (long)M2); + m2_12 = Math.floorMod(n2_12, (long)M2); + m2_20 = Math.floorMod(n2_20, (long)M2); + m2_21 = Math.floorMod(n2_21, (long)M2); + m2_22 = Math.floorMod(n2_22, (long)M2); + } + // Square the base transformations. + { + final long z1_00 = m1_00 * m1_00 + m1_01 * m1_10 + m1_02 * m1_20; + final long z1_01 = m1_00 * m1_01 + m1_01 * m1_11 + m1_02 * m1_21; + final long z1_02 = m1_00 * m1_02 + m1_01 * m1_12 + m1_02 * m1_22; + final long z1_10 = m1_10 * m1_00 + m1_11 * m1_10 + m1_12 * m1_20; + final long z1_11 = m1_10 * m1_01 + m1_11 * m1_11 + m1_12 * m1_21; + final long z1_12 = m1_10 * m1_02 + m1_11 * m1_12 + m1_12 * m1_22; + final long z1_20 = m1_20 * m1_00 + m1_21 * m1_10 + m1_22 * m1_20; + final long z1_21 = m1_20 * m1_01 + m1_21 * m1_11 + m1_22 * m1_21; + final long z1_22 = m1_20 * m1_02 + m1_21 * m1_12 + m1_22 * m1_22; + m1_00 = Math.floorMod(z1_00, (long)M1); + m1_01 = Math.floorMod(z1_01, (long)M1); + m1_02 = Math.floorMod(z1_02, (long)M1); + m1_10 = Math.floorMod(z1_10, (long)M1); + m1_11 = Math.floorMod(z1_11, (long)M1); + m1_12 = Math.floorMod(z1_12, (long)M1); + m1_20 = Math.floorMod(z1_20, (long)M1); + m1_21 = Math.floorMod(z1_21, (long)M1); + m1_22 = Math.floorMod(z1_22, (long)M1); + final long z2_00 = m2_00 * m2_00 + m2_01 * m2_10 + m2_02 * m2_20; + final long z2_01 = m2_00 * m2_01 + m2_01 * m2_11 + m2_02 * m2_21; + final long z2_02 = m2_00 * m2_02 + m2_01 * m2_12 + m2_02 * m2_22; + final long z2_10 = m2_10 * m2_00 + m2_11 * m2_10 + m2_12 * m2_20; + final long z2_11 = m2_10 * m2_01 + m2_11 * m2_11 + m2_12 * m2_21; + final long z2_12 = m2_10 * m2_02 + m2_11 * m2_12 + m2_12 * m2_22; + final long z2_20 = m2_20 * m2_00 + m2_21 * m2_10 + m2_22 * m2_20; + final long z2_21 = m2_20 * m2_01 + m2_21 * m2_11 + m2_22 * m2_21; + final long z2_22 = m2_20 * m2_02 + m2_21 * m2_12 + m2_22 * m2_22; + m2_00 = Math.floorMod(z2_00, (long)M2); + m2_01 = Math.floorMod(z2_01, (long)M2); + m2_02 = Math.floorMod(z2_02, (long)M2); + m2_10 = Math.floorMod(z2_10, (long)M2); + m2_11 = Math.floorMod(z2_11, (long)M2); + m2_12 = Math.floorMod(z2_12, (long)M2); + m2_20 = Math.floorMod(z2_20, (long)M2); + m2_21 = Math.floorMod(z2_21, (long)M2); + m2_22 = Math.floorMod(z2_22, (long)M2); + } + // Divide distance by 2. + distance = dhalf; + } + final long w10 = m1_00 * (long)s10 + m1_01 * (long)s11 + m1_02 * (long)s12; + final long w11 = m1_10 * (long)s10 + m1_11 * (long)s11 + m1_12 * (long)s12; + final long w12 = m1_20 * (long)s10 + m1_21 * (long)s11 + m1_22 * (long)s12; + s10 = Math.floorMod(w10, (long)M1); + s11 = Math.floorMod(w11, (long)M1); + s12 = Math.floorMod(w12, (long)M1); + final long w20 = m2_00 * (long)s20 + m2_01 * (long)s21 + m2_02 * (long)s22; + final long w21 = m2_10 * (long)s20 + m2_11 * (long)s21 + m2_12 * (long)s22; + final long w22 = m2_20 * (long)s20 + m2_21 * (long)s21 + m2_22 * (long)s22; + s20 = Math.floorMod(w20, (long)M2); + s21 = Math.floorMod(w21, (long)M2); + s22 = Math.floorMod(w22, (long)M2); + } + + /** + * Alter the state of this pseudorandom number generator so as to + * jump forward a distance equal to 2{@code logDistance} + * within its state cycle. + * + * @param logDistance the base-2 logarithm of the distance to jump + * forward within the state cycle. Must be non-negative and + * not greater than 192. + * + * @throws IllegalArgumentException if {@code logDistance} is + * less than zero or 2{@code logDistance} is + * greater than the period of this generator + */ + public void jumpPowerOfTwo(int logDistance) { + if (logDistance < 0 || logDistance > 192) + throw new IllegalArgumentException("logDistance must be non-negative and not greater than 192"); + jump(Math.scalb(1.0, logDistance)); + } + +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/RandomGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/RandomGenerator.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,1651 @@ +/* + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.Objects; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.Stream; + +/** + * The {@link RandomGenerator} interface is designed to provide a common protocol for objects that + * generate random or (more typically) pseudorandom sequences of numbers (or Boolean values). + * Such a sequence may be obtained by either repeatedly invoking a method that returns a single + * (pseudo)randomly chosen value, or by invoking a method that returns a stream of (pseudo)randomly + * chosen values. + *

+ * Ideally, given an implicitly or explicitly specified range of values, each value would be chosen + * independently and uniformly from that range. In practice, one may have to settle for some + * approximation to independence and uniformity. + *

+ * In the case of {@code int}, {@code long}, and {@link Boolean} values, if there is no explicit + * specification of range, then the range includes all possible values of the type. In the case of + * {@code float} and {@code double} values, a value is always chosen from the set of + * 2w values between 0.0 (inclusive) and 1.0 (exclusive), where w is 23 for + * {@code float} values and 52 for {@code double} values, such that adjacent values differ by + * 2w; if an explicit range is specified, then the chosen number is + * computationally scaled and translated so as to appear to have been chosen from that range. + *

+ * Each method that returns a stream produces a stream of values each of which is chosen in the same + * manner as for a method that returns a single (pseudo)randomly chosen value. For example, if + * {@code r} implements {@link RandomGenerator}, then the method call {@code r.ints(100)} returns a + * stream of 100 {@code int} values. These are not necessarily the exact same values that would + * have been returned if instead {@code r.nextInt()} had been called 100 times; all that is + * guaranteed is that each value in the stream is chosen in a similar (pseudo)random manner from the + * same range. + *

+ * Every object that implements the {@link RandomNumberGenerator} interface by using a + * pseudorandom algorithm is assumed to contain a finite amount of state. Using such an object to + * generate a pseudorandomly chosen value alters its state by computing a new state as a function + * of the current state, without reference to any information other than the current state. + * The number of distinct possible states of such an object is called its period. + * (Some implementations of the {@link RandomNumberGenerator} interface may be truly random + * rather than pseudorandom, for example relying on the statistical behavior of a physical + * object to derive chosen values. Such implementations do not have a fixed period.) + *

+ * As a rule, objects that implement the {@link RandomGenerator} interface need not be thread-safe. + * It is recommended that multithreaded applications use either {@link ThreadLocalRandom} or + * (preferably) pseudorandom number generators that implement the {@link SplittableGenerator} or + * {@link JumpableGenerator} interface. + *

+ * To implement this interface, a class only needs to provide concrete definitions for the methods + * {@code nextLong()} and {@code period()}. Default implementations are provided for all other + * methods (but it may be desirable to override some of them, especially {@code nextInt()} if the + * underlying algorithm is {@code int}-based). Moreover, it may be preferable instead to implement + * a more specialized interface such as {@link JumpableGenerator} or {@link LeapableGenerator}, + * or to extend an abstract implementation-support class such as {@link AbstractSplittableGenerator} + * or {@link AbstractArbitrarilyJumpableGenerator}. + *

+ * Objects that implement {@link RandomGenerator} are typically not cryptographically secure. + * Consider instead using {@link java.security.SecureRandom} to get a cryptographically secure + * pseudorandom number generator for use by security-sensitive applications. Note, however, that + * {@code java.security.SecureRandom} does implement the {@link RandomGenerator} interface, so that + * instances of {@code java.security.SecureRandom} may be used interchangeably with other types of + * pseudorandom generators in applications that do not require a secure generator. + * + * @since 14 + */ +public interface RandomGenerator { + + /** + * Supported random number Algorithms. + */ + public enum Algorithm { + /** + * L64X128MixRandom algorithm + */ + L64X128MixRandom("L64X128MixRandom"), + /** + * L64X256MixRandom algorithm + */ + L64X256MixRandom("L64X256MixRandom"), + /** + * L64X1024MixRandom algorithm + */ + L64X1024MixRandom("L64X1024MixRandom"), + /** + * L128X256MixRandom algorithm + */ + L128X256MixRandom("L128X256MixRandom"), + /** + * MRG32k3a algorithm + */ + MRG32k3a("MRG32k3a"), + /** + * Legacy Random algorithm + */ + @Deprecated + Random("Random"), + /** + * Legacy SecureRandom algorithm + */ + @Deprecated + SecureRandom("SecureRandom"), + /** + * Xoroshiro128StarStar algorithm + */ + Xoroshiro128StarStar("Xoroshiro128StarStar"), + /** + * Xoshiro256StarStar algorithm + */ + Xoshiro256StarStar("Xoshiro256StarStar"); + + private String name; + + private Algorithm(String name) { + this.name = name; + } + + public String toString() { + return name; + } + + /** + * Returns an instance of {@link RandomGenerator} that utilizes this algorithm. + * + * @return An instance of {@link RandomGenerator} + */ + public RandomGenerator instance() { + return RandomGeneratorFactory.of(name, RandomGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link RandomGenerator} that utilizes this algorithm. + * + * @return {@link RandomGeneratorFactory} of {@link RandomGenerator} + */ + public RandomGeneratorFactory factory() { + return RandomGeneratorFactory.factoryOf(name, RandomGenerator.class); + } + } + + /** + * Returns an instance of {@link RandomGenerator} that utilizes the + * {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return An instance of {@link RandomGenerator} + */ + public static RandomGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, RandomGenerator.class); + } + + /** + * Returns an instance of {@link RandomGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link RandomGenerator} + */ + public static RandomGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), RandomGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link RandomGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link RandomGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, RandomGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link RandomGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link RandomGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), RandomGenerator.class); + } + + /** + * Returns an effectively unlimited stream of pseudorandomly chosen + * {@code double} values. + * + * @return a stream of pseudorandomly chosen {@code double} values + * + * @implNote It is permitted to implement this method in a manner + * equivalent to {@code doubles(Long.MAX_VALUE)}. + * + * @implNote The default implementation produces a sequential stream + * that repeatedly calls {@code nextDouble()}. + */ + default DoubleStream doubles() { + return DoubleStream.generate(this::nextDouble).sequential(); + } + + /** + * Returns an effectively unlimited stream of pseudorandomly chosen + * {@code double} values, where each value is between the specified + * origin (inclusive) and the specified bound (exclusive). + * + * @param randomNumberOrigin the least value that can be produced + * @param randomNumberBound the upper bound (exclusive) for each value produced + * + * @return a stream of pseudorandomly chosen {@code double} values, each between + * the specified origin (inclusive) and the specified bound (exclusive) + * + * @throws IllegalArgumentException if {@code randomNumberOrigin} is not finite, + * or {@code randomNumberBound} is not finite, or {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * + * @implNote It is permitted to implement this method in a manner equivalent to + * {@code doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code nextDouble(randomNumberOrigin, randomNumberBound)}. + */ + default DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) { + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return DoubleStream.generate(() -> nextDouble(randomNumberOrigin, randomNumberBound)).sequential(); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandomly chosen {@code double} values. + * + * @param streamSize the number of values to generate + * + * @return a stream of pseudorandomly chosen {@code double} values + * + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * + * @implNote The default implementation produces a sequential stream + * that repeatedly calls {@code nextDouble()}. + */ + default DoubleStream doubles(long streamSize) { + RandomSupport.checkStreamSize(streamSize); + return doubles().limit(streamSize); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandomly chosen {@code double} values, where each value is between + * the specified origin (inclusive) and the specified bound (exclusive). + * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the least value that can be produced + * @param randomNumberBound the upper bound (exclusive) for each value produced + * + * @return a stream of pseudorandomly chosen {@code double} values, each between + * the specified origin (inclusive) and the specified bound (exclusive) + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero, + * or {@code randomNumberOrigin} is not finite, + * or {@code randomNumberBound} is not finite, or {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code nextDouble(randomNumberOrigin, randomNumberBound)}. + */ + default DoubleStream doubles(long streamSize, double randomNumberOrigin, + double randomNumberBound) { + RandomSupport.checkStreamSize(streamSize); + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return doubles(randomNumberOrigin, randomNumberBound).limit(streamSize); + } + + /** + * Returns an effectively unlimited stream of pseudorandomly chosen + * {@code int} values. + * + * @return a stream of pseudorandomly chosen {@code int} values + * + * @implNote It is permitted to implement this method in a manner + * equivalent to {@code ints(Long.MAX_VALUE)}. + * @implNote The default implementation produces a sequential stream + * that repeatedly calls {@code nextInt()}. + */ + default IntStream ints() { + return IntStream.generate(this::nextInt).sequential(); + } + + /** + * Returns an effectively unlimited stream of pseudorandomly chosen + * {@code int} values, where each value is between the specified + * origin (inclusive) and the specified bound (exclusive). + * + * @param randomNumberOrigin the least value that can be produced + * @param randomNumberBound the upper bound (exclusive) for each value produced + * + * @return a stream of pseudorandomly chosen {@code int} values, each between + * the specified origin (inclusive) and the specified bound (exclusive) + * + * @throws IllegalArgumentException if {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * + * @implNote It is permitted to implement this method in a manner equivalent to + * {@code ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code nextInt(randomNumberOrigin, randomNumberBound)}. + */ + default IntStream ints(int randomNumberOrigin, int randomNumberBound) { + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return IntStream.generate(() -> nextInt(randomNumberOrigin, randomNumberBound)).sequential(); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandomly chosen {@code int} values. + * + * @param streamSize the number of values to generate + * + * @return a stream of pseudorandomly chosen {@code int} values + * + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * + * @implNote The default implementation produces a sequential stream + * that repeatedly calls {@code nextInt()}. + */ + default IntStream ints(long streamSize) { + RandomSupport.checkStreamSize(streamSize); + return ints().limit(streamSize); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandomly chosen {@code int} values, where each value is between + * the specified origin (inclusive) and the specified bound (exclusive). + * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the least value that can be produced + * @param randomNumberBound the upper bound (exclusive) for each value produced + * + * @return a stream of pseudorandomly chosen {@code int} values, each between + * the specified origin (inclusive) and the specified bound (exclusive) + * + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero, or {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code nextInt(randomNumberOrigin, randomNumberBound)}. + */ + default IntStream ints(long streamSize, int randomNumberOrigin, + int randomNumberBound) { + RandomSupport.checkStreamSize(streamSize); + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return ints(randomNumberOrigin, randomNumberBound).limit(streamSize); + } + + /** + * Returns an effectively unlimited stream of pseudorandomly chosen + * {@code long} values. + * + * @return a stream of pseudorandomly chosen {@code long} values + * + * @implNote It is permitted to implement this method in a manner + * equivalent to {@code longs(Long.MAX_VALUE)}. + * @implNote The default implementation produces a sequential stream + * that repeatedly calls {@code nextLong()}. + */ + default LongStream longs() { + return LongStream.generate(this::nextLong).sequential(); + } + + /** + * Returns an effectively unlimited stream of pseudorandomly chosen + * {@code long} values, where each value is between the specified + * origin (inclusive) and the specified bound (exclusive). + * + * @param randomNumberOrigin the least value that can be produced + * @param randomNumberBound the upper bound (exclusive) for each value produced + * + * @return a stream of pseudorandomly chosen {@code long} values, each between + * the specified origin (inclusive) and the specified bound (exclusive) + * + * @throws IllegalArgumentException if {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * + * @implNote It is permitted to implement this method in a manner equivalent to + * {@code longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code nextLong(randomNumberOrigin, randomNumberBound)}. + */ + default LongStream longs(long randomNumberOrigin, long randomNumberBound) { + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return LongStream.generate(() -> nextLong(randomNumberOrigin, randomNumberBound)).sequential(); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandomly chosen {@code long} values. + * + * @param streamSize the number of values to generate + * + * @return a stream of pseudorandomly chosen {@code long} values + * + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * + * @implNote The default implementation produces a sequential stream + * that repeatedly calls {@code nextLong()}. + */ + default LongStream longs(long streamSize) { + RandomSupport.checkStreamSize(streamSize); + return longs().limit(streamSize); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandomly chosen {@code long} values, where each value is between + * the specified origin (inclusive) and the specified bound (exclusive). + * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the least value that can be produced + * @param randomNumberBound the upper bound (exclusive) for each value produced + * + * @return a stream of pseudorandomly chosen {@code long} values, each between + * the specified origin (inclusive) and the specified bound (exclusive) + * + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero, or {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code nextLong(randomNumberOrigin, randomNumberBound)}. + */ + default LongStream longs(long streamSize, long randomNumberOrigin, + long randomNumberBound) { + RandomSupport.checkStreamSize(streamSize); + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return longs(randomNumberOrigin, randomNumberBound).limit(streamSize); + } + + /** + * Returns a pseudorandomly chosen {@code boolean} value. + *

+ * The default implementation tests the high-order bit (sign bit) of a value produced by + * {@code nextInt()}, on the grounds that some algorithms for pseudorandom number generation + * produce values whose high-order bits have better statistical quality than the low-order bits. + * + * @return a pseudorandomly chosen {@code boolean} value + */ + default boolean nextBoolean() { + return nextInt() < 0; + } + + /** + * Returns a pseudorandom {@code float} value between zero (inclusive) and one (exclusive). + *

+ * The default implementation uses the 24 high-order bits from a call to {@code nextInt()}. + * + * @return a pseudorandom {@code float} value between zero (inclusive) and one (exclusive) + */ + default float nextFloat() { + return (nextInt() >>> 8) * 0x1.0p-24f; + } + + /** + * Returns a pseudorandomly chosen {@code float} value between zero + * (inclusive) and the specified bound (exclusive). + * + * @param bound the upper bound (exclusive) for the returned value. + * Must be positive and finite + * + * @return a pseudorandomly chosen {@code float} value between + * zero (inclusive) and the bound (exclusive) + * + * @throws IllegalArgumentException if {@code bound} is not + * both positive and finite + * + * @implNote The default implementation simply calls + * {@code RandomSupport.checkBound(bound)} and then + * {@code RandomSupport.boundedNextFloat(this, bound)}. + */ + default float nextFloat(float bound) { + RandomSupport.checkBound(bound); + return RandomSupport.boundedNextFloat(this, bound); + } + + /** + * Returns a pseudorandomly chosen {@code float} value between the + * specified origin (inclusive) and the specified bound (exclusive). + * + * @param origin the least value that can be returned + * @param bound the upper bound (exclusive) + * + * @return a pseudorandomly chosen {@code float} value between the + * origin (inclusive) and the bound (exclusive) + * + * @throws IllegalArgumentException if {@code origin} is not finite, + * or {@code bound} is not finite, or {@code origin} + * is greater than or equal to {@code bound} + * + * @implNote The default implementation simply calls + * {@code RandomSupport.checkRange(origin, bound)} and then + * {@code RandomSupport.boundedNextFloat(this, origin, bound)}. + */ + default float nextFloat(float origin, float bound) { + RandomSupport.checkRange(origin, bound); + return RandomSupport.boundedNextFloat(this, origin, bound); + } + + /** + * Returns a pseudorandom {@code double} value between zero (inclusive) and one (exclusive). + *

+ * The default implementation uses the 53 high-order bits from a call to {@code nextLong()}. + * + * @return a pseudorandom {@code double} value between zero (inclusive) and one (exclusive) + */ + default double nextDouble() { + return (nextLong() >>> 11) * 0x1.0p-53; + } + + /** + * Returns a pseudorandomly chosen {@code double} value between zero + * (inclusive) and the specified bound (exclusive). + * + * @param bound the upper bound (exclusive) for the returned value. + * Must be positive and finite + * + * @return a pseudorandomly chosen {@code double} value between + * zero (inclusive) and the bound (exclusive) + * + * @throws IllegalArgumentException if {@code bound} is not + * both positive and finite + * + * @implNote The default implementation simply calls + * {@code RandomSupport.checkBound(bound)} and then + * {@code RandomSupport.boundedNextDouble(this, bound)}. + */ + default double nextDouble(double bound) { + RandomSupport.checkBound(bound); + return RandomSupport.boundedNextDouble(this, bound); + } + + /** + * Returns a pseudorandomly chosen {@code double} value between the + * specified origin (inclusive) and the specified bound (exclusive). + * + * @param origin the least value that can be returned + * @param bound the upper bound (exclusive) for the returned value + * + * @return a pseudorandomly chosen {@code double} value between the + * origin (inclusive) and the bound (exclusive) + * + * @throws IllegalArgumentException if {@code origin} is not finite, + * or {@code bound} is not finite, or {@code origin} + * is greater than or equal to {@code bound} + * + * @implNote The default implementation simply calls + * {@code RandomSupport.checkRange(origin, bound)} and then + * {@code RandomSupport.boundedNextDouble(this, origin, bound)}. + */ + default double nextDouble(double origin, double bound) { + RandomSupport.checkRange(origin, bound); + return RandomSupport.boundedNextDouble(this, origin, bound); + } + + /** + * Returns a pseudorandomly chosen {@code int} value. + *

+ * The default implementation uses the 32 high-order bits from a call to {@code nextLong()}. + * + * @return a pseudorandomly chosen {@code int} value + */ + default public int nextInt() { + return (int)(nextLong() >>> 32); + } + + /** + * Returns a pseudorandomly chosen {@code int} value between + * zero (inclusive) and the specified bound (exclusive). + * + * @param bound the upper bound (exclusive) for the returned value. Must be positive. + * + * @return a pseudorandomly chosen {@code int} value between + * zero (inclusive) and the bound (exclusive) + * + * @throws IllegalArgumentException if {@code bound} is not positive + * + * @implNote The default implementation simply calls + * {@code RandomSupport.checkBound(bound)} and then + * {@code RandomSupport.boundedNextInt(this, bound)}. + */ + default int nextInt(int bound) { + RandomSupport.checkBound(bound); + return RandomSupport.boundedNextInt(this, bound); + } + + /** + * Returns a pseudorandomly chosen {@code int} value between the + * specified origin (inclusive) and the specified bound (exclusive). + * + * @param origin the least value that can be returned + * @param bound the upper bound (exclusive) for the returned value + * + * @return a pseudorandomly chosen {@code int} value between the + * origin (inclusive) and the bound (exclusive) + * + * @throws IllegalArgumentException if {@code origin} is greater than + * or equal to {@code bound} + * + * @implNote The default implementation simply calls + * {@code RandomSupport.checkRange(origin, bound)} and then + * {@code RandomSupport.boundedNextInt(this, origin, bound)}. + */ + default int nextInt(int origin, int bound) { + RandomSupport.checkRange(origin, bound); + return RandomSupport.boundedNextInt(this, origin, bound); + } + + /** + * Returns a pseudorandomly chosen {@code long} value. + * + * @return a pseudorandomly chosen {@code long} value + */ + long nextLong(); + + /** + * Returns a pseudorandomly chosen {@code long} value between + * zero (inclusive) and the specified bound (exclusive). + * + * @param bound the upper bound (exclusive) for the returned value. Must be positive. + * + * @return a pseudorandomly chosen {@code long} value between + * zero (inclusive) and the bound (exclusive) + * + * @throws IllegalArgumentException if {@code bound} is not positive + * + * @implNote The default implementation simply calls + * {@code RandomSupport.checkBound(bound)} and then + * {@code RandomSupport.boundedNextLong(this, bound)}. + */ + default long nextLong(long bound) { + RandomSupport.checkBound(bound); + return RandomSupport.boundedNextLong(this, bound); + } + + /** + * Returns a pseudorandomly chosen {@code long} value between the + * specified origin (inclusive) and the specified bound (exclusive). + * + * @param origin the least value that can be returned + * @param bound the upper bound (exclusive) for the returned value + * + * @return a pseudorandomly chosen {@code long} value between the + * origin (inclusive) and the bound (exclusive) + * + * @throws IllegalArgumentException if {@code origin} is greater than + * or equal to {@code bound} + * + * @implNote The default implementation simply calls + * {@code RandomSupport.checkRange(origin, bound)} and then + * {@code RandomSupport.boundedNextInt(this, origin, bound)}. + * + */ + default long nextLong(long origin, long bound) { + RandomSupport.checkRange(origin, bound); + return RandomSupport.boundedNextLong(this, origin, bound); + } + + /** + * Returns a {@code double} value pseudorandomly chosen from + * a Gaussian (normal) distribution whose mean is 0 and whose + * standard deviation is 1. + * + * @return a {@code double} value pseudorandomly chosen from a + * Gaussian distribution + */ + default double nextGaussian() { + return RandomSupport.computeNextGaussian(this); + } + + /** + * Returns a {@code double} value pseudorandomly chosen from + * a Gaussian (normal) distribution with a mean and + * standard deviation specified by the arguments. + * + * @param mean the mean of the Gaussian distribution to be drawn from + * @param stddev the standard deviation (square root of the variance) + * of the Gaussian distribution to be drawn from + * + * @return a {@code double} value pseudorandomly chosen from the + * specified Gaussian distribution + * + * @throws IllegalArgumentException if {@code stddev} is negative + */ + default double nextGaussian(double mean, double stddev) { + if (stddev < 0.0) throw new IllegalArgumentException("standard deviation must be non-negative"); + return mean + stddev * RandomSupport.computeNextGaussian(this); + } + + /** + * Returns a nonnegative {@code double} value pseudorandomly chosen + * from an exponential distribution whose mean is 1. + * + * @return a nonnegative {@code double} value pseudorandomly chosen from an + * exponential distribution + */ + default double nextExponential() { + return RandomSupport.computeNextExponential(this); + } + + /** + * Returns the period of this {@link RandomGenerator} object. + * + * @return a {@link BigInteger} whose value is the number of distinct possible states of this + * {@link RandomGenerator} object, or 0 if unknown, or negative if extremely + * large. + */ + BigInteger period(); + + /** + * The value (0) returned by the {@code period()} method if the period is unknown. + */ + static final BigInteger UNKNOWN_PERIOD = BigInteger.ZERO; + + /** + * The (negative) value returned by the {@code period()} method if this generator + * has no period because it is truly random rather than just pseudorandom. + */ + static final BigInteger TRULY_RANDOM = BigInteger.valueOf(-1); + + /** + * The (negative) value that may be returned by the {@code period()} method + * if this generator has a huge period (larger than 2**(2**16)). + */ + static final BigInteger HUGE_PERIOD = BigInteger.valueOf(-2); + + /** + * The {@link StreamableGenerator} interface augments the {@link RandomGenerator} interface + * to provide methods that return streams of {@link RandomGenerator} objects. + * Ideally, such a stream of objects would have the property that the + * behavior of each object is statistically independent of all the others. + * In practice, one may have to settle for some approximation to this property. + * + * A generator that implements interface {@link SplittableGenerator} + * may choose to use its {@code splits} method to implement the {@code rngs} + * method required by this interface. + * + * A generator that implements interface {@link JumpableGenerator} + * may choose to use its {@code jumps} method to implement the {@code rngs} + * method required by this interface. + * + * A generator that implements interface {@link LeapableGenerator} + * may choose to use its {@code leaps} method to implement the {@code rngs} + * method required by this interface. + *

+ * An implementation of the {@link StreamableGenerator} interface must provide + * concrete definitions for the methods {@code nextInt()}, {@code nextLong}, + * {@code period()}, and {@code rngs()}. + * Default implementations are provided for all other methods. + *

+ * Objects that implement {@link StreamableGenerator} are typically + * not cryptographically secure. Consider instead using + * {@link java.security.SecureRandom} to get a cryptographically + * secure pseudo-random number generator for use by + * security-sensitive applications. + * + * @since 14 + */ + public interface StreamableGenerator extends RandomGenerator { + + /** + * Returns an instance of {@link StreamableGenerator} that utilizes the + * {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return An instance of {@link StreamableGenerator} + */ + public static StreamableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, StreamableGenerator.class); + } + + /** + * Returns an instance of {@link StreamableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link StreamableGenerator} + */ + public static StreamableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), StreamableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link StreamableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link StreamableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, StreamableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link StreamableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link StreamableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), StreamableGenerator.class); + } + + /** + * Returns an effectively unlimited stream of objects, each of + * which implements the {@link RandomGenerator} interface. Ideally the + * generators in the stream will appear to be statistically + * independent. The new generators should be of the same kind + * as this generator. + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @implNote It is permitted to implement this method in a manner + * equivalent to {@code rngs(Long.MAX_VALUE)}. + */ + Stream rngs(); + + /** + * Returns an effectively unlimited stream of objects, each of + * which implements the {@link RandomGenerator} interface. Ideally the + * generators in the stream will appear to be statistically + * independent. The new generators should be of the same kind + * as this generator. + * + * @param streamSize the number of generators to generate + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * + * @implNote The default implementation calls {@code rngs()} and + * then limits its length to {@code streamSize}. + */ + default Stream rngs(long streamSize) { + RandomSupport.checkStreamSize(streamSize); + return rngs().limit(streamSize); + } + } + + /** + * This interface is designed to provide a common protocol for objects + * that generate sequences of pseudorandom numbers (or Boolean values) + * and furthermore can be split into two objects (the original + * one and a new one) each of which obey that same protocol (and therefore + * can be recursively split indefinitely). + *

+ * Ideally, all {@link SplittableGenerator} objects produced by recursive + * splitting from a single original {@link SplittableGenerator} object are + * statistically independent of one another and individually uniform. + * Therefore we would expect the set of values collectively generated + * by a set of such objects to have the same statistical properties as + * if the same quantity of values were generated by a single thread + * using a single {@link SplittableGenerator} object. In practice, one must + * settle for some approximation to independence and uniformity. + *

+ * Methods are provided to perform a single splitting operation and + * also to produce a stream of generators split off from the original + * (by either iterative or recursive splitting, or a combination). + *

+ * An implementation of the {@link SplittableGenerator} interface must provide + * concrete definitions for the methods {@code nextInt()}, {@code nextLong}, + * {@code period()}, {@code split()}, {@code split(SplittableGenerator)}, + * {@code splits()}, {@code splits(long)}, {@code splits(SplittableGenerator)}, + * and {@code splits(long, SplittableGenerator)}. Perhaps the most convenient + * way to implement this interface is to extend the abstract class + * {@link AbstractSplittableGenerator}. + *

+ * Objects that implement {@link SplittableGenerator} are + * typically not cryptographically secure. Consider instead using + * {@link java.security.SecureRandom} to get a cryptographically + * secure pseudo-random number generator for use by + * security-sensitive applications. + * + * @since 14 + */ + public interface SplittableGenerator extends StreamableGenerator { + + /** + * Returns an instance of {@link SplittableGenerator} that utilizes the + * {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return An instance of {@link SplittableGenerator} + */ + public static SplittableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, SplittableGenerator.class); + } + + /** + * Returns an instance of {@link SplittableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link SplittableGenerator} + */ + public static SplittableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), SplittableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link SplittableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link SplittableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, SplittableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link SplittableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link SplittableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), SplittableGenerator.class); + } + + /** + * Returns a new pseudorandom number generator, split off from + * this one, that implements the {@link RandomGenerator} and {@link SplittableGenerator} + * interfaces. + * + * This pseudorandom number generator may be used as a source of + * pseudorandom bits used to initialize the state the new one. + * + * @return a new object that implements the {@link RandomGenerator} and + * {@link SplittableGenerator} interfaces + */ + SplittableGenerator split(); + + /** + * Returns a new pseudorandom number generator, split off from + * this one, that implements the {@link RandomGenerator} and {@link SplittableGenerator} + * interfaces. + * + * @param source a {@link SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * + * @return an object that implements the {@link RandomGenerator} and + * {@link SplittableGenerator} interfaces + */ + SplittableGenerator split(SplittableGenerator source); + + /** + * Returns an effectively unlimited stream of new pseudorandom + * number generators, each of which implements the {@link SplittableGenerator} + * interface. + * + * This pseudorandom number generator may be used as a source of + * pseudorandom bits used to initialize the state the new ones. + * + * @implNote It is permitted to implement this method in a manner + * equivalent to {@code splits(Long.MAX_VALUE)}. + * + * @return a stream of {@link SplittableGenerator} objects + */ + default Stream splits() { + return this.splits(this); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * new pseudorandom number generators, each of which implements the + * {@link SplittableGenerator} interface. + * + * This pseudorandom number generator may be used as a source of + * pseudorandom bits used to initialize the state the new ones. + * + * @param streamSize the number of values to generate + * + * @return a stream of {@link SplittableGenerator} objects + * + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + */ + Stream splits(long streamSize); + + /** + * Returns an effectively unlimited stream of new pseudorandom + * number generators, each of which implements the {@link SplittableGenerator} + * interface. + * + * @param source a {@link SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * + * @return a stream of {@link SplittableGenerator} objects + * + * @implNote It is permitted to implement this method in a manner + * equivalent to {@code splits(Long.MAX_VALUE, source)}. + */ + Stream splits(SplittableGenerator source); + + /** + * Returns a stream producing the given {@code streamSize} number of + * new pseudorandom number generators, each of which implements the + * {@link SplittableGenerator} interface. + * + * @param streamSize the number of values to generate + * @param source a {@link SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * + * @return a stream of {@link SplittableGenerator} objects + * + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + */ + Stream splits(long streamSize, SplittableGenerator source); + + /** + * Returns an effectively unlimited stream of new pseudorandom + * number generators, each of which implements the {@link RandomGenerator} + * interface. Ideally the generators in the stream will appear + * to be statistically independent. + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @implNote The default implementation calls {@code splits()}. + */ + default Stream rngs() { + return this.splits().map(x -> (RandomGenerator)x); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * new pseudorandom number generators, each of which implements the + * {@link RandomGenerator} interface. Ideally the generators in the stream will + * appear to be statistically independent. + * + * @param streamSize the number of generators to generate + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * + * @implNote The default implementation calls {@code splits(streamSize)}. + */ + default Stream rngs(long streamSize) { + return this.splits(streamSize).map(x -> (RandomGenerator)x); + } + } + + /** + * This interface is designed to provide a common protocol for objects that generate + * pseudorandom sequences of numbers (or Boolean values) and furthermore can easily jump + * forward (by a fixed amount) to a distant point in the state cycle. + *

+ * Ideally, all {@link JumpableGenerator} objects produced by iterative jumping from a single + * original {@link JumpableGenerator} object are statistically independent of one another and + * individually uniform. In practice, one must settle for some approximation to independence and + * uniformity. In particular, a specific implementation may assume that each generator in a + * stream produced by the {@code jumps} method is used to produce a number of values no larger + * than either 264 or the square root of its period. Implementors are advised to use + * algorithms whose period is at least 2127. + *

+ * Methods are provided to perform a single jump operation and also to produce a stream of + * generators produced from the original by iterative copying and jumping of internal state. A + * typical strategy for a multithreaded application is to create a single {@link + * JumpableGenerator} object, calls its {@code jumps} method exactly once, and then parcel out + * generators from the resulting stream, one to each thread. It is generally not a good idea to + * call {@code jump} on a generator that was itself produced by the {@code jumps} method, + * because the result may be a generator identical to another generator already produce by that + * call to the {@code jumps} method. For this reason, the return type of the {@code jumps} + * method is {@code Stream} rather than {@code Stream}, even + * though the actual generator objects in that stream likely do also implement the {@link + * JumpableGenerator} interface. + *

+ * An implementation of the {@link JumpableGenerator} interface must provide concrete + * definitions for the methods {@code nextInt()}, {@code nextLong}, {@code period()}, {@code + * copy()}, {@code jump()}, and {@code defaultJumpDistance()}. Default implementations are + * provided for all other methods. + *

+ * Objects that implement {@link JumpableGenerator} are typically not cryptographically secure. + * Consider instead using {@link java.security.SecureRandom} to get a cryptographically secure + * pseudo-random number generator for use by security-sensitive applications. + * + * @since 14 + */ + public interface JumpableGenerator extends StreamableGenerator { + + /** + * Returns an instance of {@link JumpableGenerator} that utilizes the + * {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return An instance of {@link JumpableGenerator} + */ + public static JumpableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, JumpableGenerator.class); + } + + /** + * Returns an instance of {@link JumpableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link JumpableGenerator} + */ + public static JumpableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), JumpableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link JumpableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link JumpableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, JumpableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link JumpableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link JumpableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), JumpableGenerator.class); + } + + /** + * Returns a new generator whose internal state is an exact copy of this generator (therefore + * their future behavior should be identical if subjected to the same series of operations). + * + * @return a new object that is a copy of this generator + */ + JumpableGenerator copy(); + + /** + * Alter the state of this pseudorandom number generator so as to jump forward a large, fixed + * distance (typically 264 or more) within its state cycle. + */ + void jump(); + + /** + * Returns the distance by which the {@code jump()} method will jump forward within the state + * cycle of this generator object. + * + * @return the default jump distance (as a {@code double} value) + */ + double defaultJumpDistance(); + + /** + * Returns an effectively unlimited stream of new pseudorandom number generators, each of which + * implements the {@link RandomGenerator} interface. + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @implNote It is permitted to implement this method in a manner equivalent to + * {@code jumps(Long.MAX_VALUE)}. + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code copy()} and {@code jump()} on this generator, and the copies become the + * generators produced by the stream. + */ + default Stream jumps() { + return Stream.generate(this::copyAndJump).sequential(); + } + + /** + * Returns a stream producing the given {@code streamSize} number of new pseudorandom number + * generators, each of which implements the {@link RandomGenerator} interface. + * + * @param streamSize the number of generators to generate + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code copy()} and {@code jump()} on this generator, and the copies become the + * generators produced by the stream. + */ + default Stream jumps(long streamSize) { + return jumps().limit(streamSize); + } + + /** + * Returns an effectively unlimited stream of new pseudorandom number generators, each of which + * implements the {@link RandomGenerator} interface. Ideally the generators in the stream + * will appear to be statistically independent. + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @implNote The default implementation calls {@code jumps()}. + */ + default Stream rngs() { + return this.jumps(); + } + + /** + * Returns a stream producing the given {@code streamSize} number of new pseudorandom number + * generators, each of which implements the {@link RandomGenerator} interface. Ideally + * the generators in the stream will appear to be statistically independent. + * + * @param streamSize the number of generators to generate + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + * @implNote The default implementation calls {@code jumps(streamSize)}. + */ + default Stream rngs(long streamSize) { + return this.jumps(streamSize); + } + + /** + * Copy this generator, jump this generator forward, then return the copy. + * + * @return a copy of this generator object before the jump occurred + */ + default RandomGenerator copyAndJump() { + RandomGenerator result = copy(); + jump(); + return result; + } + + } + + /** + * This interface is designed to provide a common protocol for objects that generate sequences + * of pseudorandom numbers (or Boolean values) and furthermore can easily not only jump but + * also + * leap to a very distant point in the state cycle. + *

+ * Typically one will construct a series of {@link LeapableGenerator} objects by iterative + * leaping from a single original {@link LeapableGenerator} object, and then for each such + * object produce a subseries of objects by iterative jumping. There is little conceptual + * difference between leaping and jumping, but typically a leap will be a very long jump in the + * state cycle (perhaps distance 2128 or so). + *

+ * Ideally, all {@link LeapableGenerator} objects produced by iterative leaping and jumping from + * a single original {@link LeapableGenerator} object are statistically independent of one + * another and individually uniform. In practice, one must settle for some approximation to + * independence and uniformity. In particular, a specific implementation may assume that each + * generator in a stream produced by the {@code leaps} method is used to produce (by jumping) a + * number of objects no larger than 264. Implementors are advised to use algorithms + * whose period is at least 2191. + *

+ * Methods are provided to perform a single leap operation and also to produce a stream of + * generators produced from the original by iterative copying and leaping of internal state. + * The generators produced must implement the {@link JumpableGenerator} interface but need not + * also implement the {@link LeapableGenerator} interface. A typical strategy for a + * multithreaded application is to create a single {@link LeapableGenerator} object, calls its + * {@code leaps} method exactly once, and then parcel out generators from the resulting stream, + * one to each thread. Then the {@code jumps} method of each such generator be called to + * produce a substream of generator objects. + *

+ * An implementation of the {@link LeapableGenerator} interface must provide concrete + * definitions for the methods {@code nextInt()}, {@code nextLong}, {@code period()}, + * {@code copy()}, {@code jump()}, {@code defaultJumpDistance()}, {@code leap()}, + * and {@code defaultLeapDistance()}. Default implementations are provided for all other + * methods. + *

+ * Objects that implement {@link LeapableGenerator} are typically not cryptographically secure. + * Consider instead using {@link java.security.SecureRandom} to get a cryptographically secure + * pseudo-random number generator for use by security-sensitive applications. + * + * @since 14 + */ + public interface LeapableGenerator extends JumpableGenerator { + + /** + * Returns an instance of {@link LeapableGenerator} that utilizes the + * {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return An instance of {@link LeapableGenerator} + */ + public static LeapableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, LeapableGenerator.class); + } + + /** + * Returns an instance of {@link LeapableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link LeapableGenerator} + */ + public static LeapableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), LeapableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link LeapableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link LeapableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, LeapableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link LeapableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link LeapableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), LeapableGenerator.class); + } + + /** + * Returns a new generator whose internal state is an exact copy of this generator (therefore + * their future behavior should be identical if subjected to the same series of operations). + * + * @return a new object that is a copy of this generator + */ + LeapableGenerator copy(); + + /** + * Alter the state of this pseudorandom number generator so as to leap forward a large, fixed + * distance (typically 296 or more) within its state cycle. + */ + void leap(); + + /** + * Returns the distance by which the {@code leap()} method will leap forward within the state + * cycle of this generator object. + * + * @return the default leap distance (as a {@code double} value) + */ + double defaultLeapDistance(); + + /** + * Returns an effectively unlimited stream of new pseudorandom number generators, each of which + * implements the {@link JumpableGenerator} interface. + * + * @return a stream of objects that implement the {@link JumpableGenerator} interface + * + * @implNote It is permitted to implement this method in a manner equivalent to {@code + * leaps(Long.MAX_VALUE)}. + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code copy()} and {@code leap()} on this generator, and the copies become the + * generators produced by the stream. + */ + default Stream leaps() { + return Stream.generate(this::copyAndLeap).sequential(); + } + + /** + * Returns a stream producing the given {@code streamSize} number of new pseudorandom number + * generators, each of which implements the {@link JumpableGenerator} interface. + * + * @param streamSize the number of generators to generate + * + * @return a stream of objects that implement the {@link JumpableGenerator} interface + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + * @implNote The default implementation produces a sequential stream that repeatedly + * calls {@code copy()} and {@code leap()} on this generator, and the copies become the + * generators produced by the stream. + */ + default Stream leaps(long streamSize) { + return leaps().limit(streamSize); + } + + /** + * Copy this generator, leap this generator forward, then return the copy. + * + * @return a copy of this generator object before the leap occurred + */ + default JumpableGenerator copyAndLeap() { + JumpableGenerator result = copy(); + leap(); + return result; + } + + } + + /** + * This interface is designed to provide a common protocol for objects that generate sequences + * of pseudorandom numbers (or Boolean values) and furthermore can easily jump to an + * arbitrarily specified distant point in the state cycle. + *

+ * Ideally, all {@link ArbitrarilyJumpableGenerator} objects produced by iterative jumping from + * a single original {@link ArbitrarilyJumpableGenerator} object are statistically independent + * of one another and individually uniform, provided that they do not traverse overlapping + * portions of the state cycle. In practice, one must settle for some approximation to + * independence and uniformity. In particular, a specific implementation may assume that each + * generator in a stream produced by the {@code jumps} method is used to produce a number of + * values no larger than the jump distance specified. Implementors are advised to use + * algorithms whose period is at least 2127. + *

+ * For many applications, it suffices to jump forward by a power of two or some small multiple + * of a power of two, but this power of two may not be representable as a {@code long} value. + * To avoid the use of {@link java.math.BigInteger} values as jump distances, {@code double} + * values are used instead. + *

+ * Methods are provided to perform a single jump operation and also to produce a stream of + * generators produced from the original by iterative copying and jumping of internal state. A + * typical strategy for a multithreaded application is to create a single + * {@link ArbitrarilyJumpableGenerator} object, call its {@code jumps} method exactly once, and + * then parcel out generators from the resulting stream, one to each thread. However, each + * generator produced also has type {@link ArbitrarilyJumpableGenerator}; with care, different + * jump distances can be used to traverse the entire state cycle in various ways. + *

+ * An implementation of the {@link ArbitrarilyJumpableGenerator} interface must provide concrete + * definitions for the methods {@code nextInt()}, {@code nextLong}, {@code period()}, + * {@code copy()}, {@code jump(double)}, {@code defaultJumpDistance()}, and + * {@code defaultLeapDistance()}. Default implementations are provided for all other methods. + * Perhaps the most convenient way to implement this interface is to extend the abstract class + * {@link ArbitrarilyJumpableGenerator}, which provides spliterator-based implementations of the + * methods {@code ints}, {@code longs}, {@code doubles}, {@code rngs}, {@code jumps}, and + * {@code leaps}. + *

+ * Objects that implement {@link ArbitrarilyJumpableGenerator} are typically not + * cryptographically secure. Consider instead using {@link java.security.SecureRandom} to get a + * cryptographically secure pseudo-random number generator for use by security-sensitive + * applications. + * + * @since 14 + */ + public interface ArbitrarilyJumpableGenerator extends LeapableGenerator { + + /** + * Returns an instance of {@link ArbitrarilyJumpableGenerator} that utilizes the + * {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return An instance of {@link ArbitrarilyJumpableGenerator} + */ + public static ArbitrarilyJumpableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, ArbitrarilyJumpableGenerator.class); + } + + /** + * Returns an instance of {@link ArbitrarilyJumpableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link ArbitrarilyJumpableGenerator} + */ + public static ArbitrarilyJumpableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), ArbitrarilyJumpableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link ArbitrarilyJumpableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link ArbitrarilyJumpableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, ArbitrarilyJumpableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link ArbitrarilyJumpableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return {@link RandomGeneratorFactory} of {@link ArbitrarilyJumpableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), ArbitrarilyJumpableGenerator.class); + } + + /** + * Returns a new generator whose internal state is an exact copy of this generator (therefore + * their future behavior should be identical if subjected to the same series of operations). + * + * @return a new object that is a copy of this generator + */ + ArbitrarilyJumpableGenerator copy(); + + /** + * Alter the state of this pseudorandom number generator so as to jump forward a distance equal + * to 2{@code logDistance} within its state cycle. + * + * @param logDistance the base-2 logarithm of the distance to jump forward within the state + * cycle + * + * @throws IllegalArgumentException if {@code logDistance} is NaN or negative, or if + * 2{@code logDistance} is greater than the period + * of this generator + */ + void jumpPowerOfTwo(int logDistance); + + /** + * Alter the state of this pseudorandom number generator so as to jump forward a specified + * distance within its state cycle. + * + * @param distance the distance to jump forward within the state cycle + * + * @throws IllegalArgumentException if {@code distance} is Nan, negative, or greater than the + * period of this generator + */ + void jump(double distance); + + /** + * Alter the state of this pseudorandom number generator so as to jump forward a large, fixed + * distance (typically 264 or more) within its state cycle. The distance used is + * that returned by method {@code defaultJumpDistance()}. + */ + default void jump() { jump(defaultJumpDistance()); } + + /** + * Returns an effectively unlimited stream of new pseudorandom number generators, each of + * which implements the {@link ArbitrarilyJumpableGenerator} interface, produced by jumping + * copies of this generator by different integer multiples of the specified jump distance. + * + * @param distance a distance to jump forward within the state cycle + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @implNote This method is implemented to be equivalent to {@code jumps(Long.MAX_VALUE)}. + */ + default Stream jumps(double distance) { + return Stream.generate(() -> copyAndJump(distance)).sequential(); + } + + /** + * Returns a stream producing the given {@code streamSize} number of new pseudorandom number + * generators, each of which implements the {@link ArbitrarilyJumpableGenerator} interface, + * produced by jumping copies of this generator by different integer multiples of the + * specified jump distance. + * + * @param streamSize the number of generators to generate + * @param distance a distance to jump forward within the state cycle + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + */ + default Stream jumps(long streamSize, double distance) { + return jumps(distance).limit(streamSize); + } + + /** + * Alter the state of this pseudorandom number generator so as to jump forward a very large, + * fixed distance (typically 2128 or more) within its state cycle. The distance + * used is that returned by method {@code defaultJLeapDistance()}. + */ + default void leap() { jump(defaultLeapDistance()); } + + /** + * Copy this generator, jump this generator forward, then return the copy. + * + * @param distance a distance to jump forward within the state cycle + * + * @return a copy of this generator object before the jump occurred + */ + default ArbitrarilyJumpableGenerator copyAndJump(double distance) { + ArbitrarilyJumpableGenerator result = copy(); + jump(distance); + return result; + } + + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.util.function.Function; +import java.util.Map; +import java.util.Objects; +import java.util.ServiceLoader; +import java.util.ServiceLoader.Provider; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * This is a factory class for generating random number generators of a specific + * catagory and algorithm. + */ +public class RandomGeneratorFactory { + /** + * Instance provider class of random number algorithm. + */ + private final Provider provider; + + /** + * Map of provider classes. + */ + private static Map> providerMap; + + /** + * Private constructor. + * + * @param provider Provider class to wrap. + */ + private RandomGeneratorFactory(Provider provider) { + this.provider = provider; + } + + /** + * Returns the provider map, lazily constructing map on first call. + * + * @return Map of provider classes. + */ + private static Map> getProviderMap() { + if (providerMap == null) { + synchronized (RandomGeneratorFactory.class) { + if (providerMap == null) { + providerMap = + ServiceLoader + .load(RandomGenerator.class) + .stream() + .filter(p -> !p.type().isInterface()) + .collect(Collectors.toMap(p -> p.type().getSimpleName().toUpperCase(), + Function.identity())); + } + } + } + return providerMap; + } + + private static Provider findProvider(String name, Class category) + throws IllegalArgumentException { + Map> pm = getProviderMap(); + Provider provider = pm.get(name.toUpperCase()); + if (provider == null || provider.type().isAssignableFrom(category)) { + throw new IllegalArgumentException(name + " is an unknown random number generator"); + } + return provider; + } + + /** + * Returns a {@link RandomGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number algorithm to use + * @param category Sub-interface of {@link RandomGenerator} to type check + * @param Sub-interface of {@link RandomGenerator} to produce + * @return An instance of {@link RandomGenerator} + * @throws IllegalArgumentException when either the name or category is null + */ + static T of(String name, Class category) + throws IllegalArgumentException { + @SuppressWarnings("unchecked") + T uncheckedRandomGenerator = (T)findProvider(name, category).get(); + return uncheckedRandomGenerator; + } + + /** + * Returns a {@link RandomGeneratorFactory} that will produce instances + * of {@link RandomGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number algorithm to use + * @param category Sub-interface of {@link RandomGenerator} to type check + * @param Sub-interface of {@link RandomGenerator} to produce + * @return Factory of {@link RandomGenerator} + * @throws IllegalArgumentException when either the name or category is null + */ + static RandomGeneratorFactory factoryOf(String name, Class category) + throws IllegalArgumentException { + @SuppressWarnings("unchecked") + Provider uncheckedProvider = (Provider)findProvider(name, category); + return new RandomGeneratorFactory(uncheckedProvider); + } + + /** + * Create an instance of {@link RandomGenerator}. + * + * @return Instance of {@link RandomGenerator}. + */ + public T create() { + return provider.get(); + } +} + + diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/RandomSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/RandomSupport.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,2482 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.random.RandomGenerator.SplittableGenerator; +import java.util.Spliterator; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * Low-level utility methods helpful for implementing pseudorandom number generators. + * + * This class is mostly for library writers creating specific implementations of the + * interface {@link RandomGenerator}. + * + * @since 14 + */ +public class RandomSupport { + + /* + * Implementation Overview. + * + * This class provides utility methods and constants frequently + * useful in the implementation of pseudorandom number generators + * that satisfy the interface {@link RandomGenerator}. + * + * File organization: First some message strings, then the main + * public methods, followed by a non-public base spliterator class. + */ + + // IllegalArgumentException messages + static final String BAD_SIZE = "size must be non-negative"; + static final String BAD_DISTANCE = "jump distance must be finite, positive, and an exact integer"; + static final String BAD_BOUND = "bound must be positive"; + static final String BAD_FLOATING_BOUND = "bound must be finite and positive"; + static final String BAD_RANGE = "bound must be greater than origin"; + + /* ---------------- public methods ---------------- */ + + /** + * Check a {@code long} proposed stream size for validity. + * + * @param streamSize the proposed stream size + * + * @throws IllegalArgumentException if {@code streamSize} is negative + */ + public static void checkStreamSize(long streamSize) { + if (streamSize < 0L) + throw new IllegalArgumentException(BAD_SIZE); + } + + /** + * Check a {@code double} proposed jump distance for validity. + * + * @param distance the proposed jump distance + * + * @throws IllegalArgumentException if {@code size} fails to be positive, finite, and an exact integer + */ + public static void checkJumpDistance(double distance) { + if (!(distance > 0.0 && distance < Float.POSITIVE_INFINITY + && distance == Math.floor(distance))) { + throw new IllegalArgumentException(BAD_DISTANCE); + } + } + + /** + * Checks a {@code float} upper bound value for validity. + * + * @param bound the upper bound (exclusive) + * + * @throws IllegalArgumentException if {@code bound} fails to be positive and finite + */ + public static void checkBound(float bound) { + if (!(bound > 0.0 && bound < Float.POSITIVE_INFINITY)) { + throw new IllegalArgumentException(BAD_FLOATING_BOUND); + } + } + + /** + * Checks a {@code double} upper bound value for validity. + * + * @param bound the upper bound (exclusive) + * + * @throws IllegalArgumentException if {@code bound} fails to be positive and finite + */ + public static void checkBound(double bound) { + if (!(bound > 0.0 && bound < Double.POSITIVE_INFINITY)) { + throw new IllegalArgumentException(BAD_FLOATING_BOUND); + } + } + + /** + * Checks an {@code int} upper bound value for validity. + * + * @param bound the upper bound (exclusive) + * + * @throws IllegalArgumentException if {@code bound} is not positive + */ + public static void checkBound(int bound) { + if (bound <= 0) { + throw new IllegalArgumentException(BAD_BOUND); + } + } + + /** + * Checks a {@code long} upper bound value for validity. + * + * @param bound the upper bound (exclusive) + * + * @throws IllegalArgumentException if {@code bound} is not positive + */ + public static void checkBound(long bound) { + if (bound <= 0) { + throw new IllegalArgumentException(BAD_BOUND); + } + } + + /** + * Checks a {@code float} range for validity. + * + * @param origin the least value (inclusive) in the range + * @param bound the upper bound (exclusive) of the range + * + * @throws IllegalArgumentException if {@code origin} is not finite, {@code bound} is not finite, + * or {@code bound - origin} is not finite + */ + public static void checkRange(float origin, float bound) { + if (!(origin < bound && (bound - origin) < Float.POSITIVE_INFINITY)) { + throw new IllegalArgumentException(BAD_RANGE); + } + } + + /** + * Checks a {@code double} range for validity. + * + * @param origin the least value (inclusive) in the range + * @param bound the upper bound (exclusive) of the range + * + * @throws IllegalArgumentException if {@code origin} is not finite, {@code bound} is not finite, + * or {@code bound - origin} is not finite + */ + public static void checkRange(double origin, double bound) { + if (!(origin < bound && (bound - origin) < Double.POSITIVE_INFINITY)) { + throw new IllegalArgumentException(BAD_RANGE); + } + } + + /** + * Checks an {@code int} range for validity. + * + * @param origin the least value that can be returned + * @param bound the upper bound (exclusive) for the returned value + * + * @throws IllegalArgumentException if {@code origin} is greater than or equal to {@code bound} + */ + public static void checkRange(int origin, int bound) { + if (origin >= bound) { + throw new IllegalArgumentException(BAD_RANGE); + } + } + + /** + * Checks a {@code long} range for validity. + * + * @param origin the least value that can be returned + * @param bound the upper bound (exclusive) for the returned value + * + * @throws IllegalArgumentException if {@code origin} is greater than or equal to {@code bound} + */ + public static void checkRange(long origin, long bound) { + if (origin >= bound) { + throw new IllegalArgumentException(BAD_RANGE); + } + } + + /** + * Given an array of seed bytes of any length, construct an array + * of {@code long} seed values of length {@code n}, such that the + * last {@code z} values are not all zero. + * + * @param seed an array of {@code byte} values + * @param n the length of the result array (should be nonnegative) + * @param z the number of trailing result elements that are required + * to be not all zero (should be nonnegative but not larger + * than {@code n}) + * + * @return an array of length {@code n} containing {@code long} seed values + */ + public static long[] convertSeedBytesToLongs(byte[] seed, int n, int z) { + final long[] result = new long[n]; + final int m = Math.min(seed.length, n << 3); + // Distribute seed bytes into the words to be formed. + for (int j = 0; j < m; j++) { + result[j>>3] = (result[j>>3] << 8) | seed[j]; + } + // If there aren't enough seed bytes for all the words we need, + // use a SplitMix-style PRNG to fill in the rest. + long v = result[0]; + for (int j = (m + 7) >> 3; j < n; j++) { + result[j] = mixMurmur64(v += SILVER_RATIO_64); + } + // Finally, we need to make sure the last z words are not all zero. + search: { + for (int j = n - z; j < n; j++) { + if (result[j] != 0) break search; + } + // If they are, fill in using a SplitMix-style PRNG. + // Using "& ~1L" in the next line defends against the case z==1 + // by guaranteeing that the first generated value will be nonzero. + long w = result[0] & ~1L; + for (int j = n - z; j < n; j++) { + result[j] = mixMurmur64(w += SILVER_RATIO_64); + } + } + return result; + } + + /** + * Given an array of seed bytes of any length, construct an array + * of {@code int} seed values of length {@code n}, such that the + * last {@code z} values are not all zero. + * + * @param seed an array of {@code byte} values + * @param n the length of the result array (should be nonnegative) + * @param z the number of trailing result elements that are required + * to be not all zero (should be nonnegative but not larger + * than {@code n}) + * + * @return an array of length {@code n} containing {@code int} seed values + */ + public static int[] convertSeedBytesToInts(byte[] seed, int n, int z) { + final int[] result = new int[n]; + final int m = Math.min(seed.length, n << 2); + // Distribute seed bytes into the words to be formed. + for (int j = 0; j < m; j++) { + result[j>>2] = (result[j>>2] << 8) | seed[j]; + } + // If there aren't enough seed bytes for all the words we need, + // use a SplitMix-style PRNG to fill in the rest. + int v = result[0]; + for (int j = (m + 3) >> 2; j < n; j++) { + result[j] = mixMurmur32(v += SILVER_RATIO_32); + } + // Finally, we need to make sure the last z words are not all zero. + search: { + for (int j = n - z; j < n; j++) { + if (result[j] != 0) break search; + } + // If they are, fill in using a SplitMix-style PRNG. + // Using "& ~1" in the next line defends against the case z==1 + // by guaranteeing that the first generated value will be nonzero. + int w = result[0] & ~1; + for (int j = n - z; j < n; j++) { + result[j] = mixMurmur32(w += SILVER_RATIO_32); + } + } + return result; + } + + /* + * Bounded versions of nextX methods used by streams, as well as + * the public nextX(origin, bound) methods. These exist mainly to + * avoid the need for multiple versions of stream spliterators + * across the different exported forms of streams. + */ + + /** + * This is the form of {@code nextLong} used by a {@link LongStream} + * {@link Spliterator} and by the public method + * {@code nextLong(origin, bound)}. If {@code origin} is greater + * than {@code bound}, then this method simply calls the unbounded + * version of {@code nextLong()}, choosing pseudorandomly from + * among all 264 possible {@code long} values}, and + * otherwise uses one or more calls to {@code nextLong()} to + * choose a value pseudorandomly from the possible values + * between {@code origin} (inclusive) and {@code bound} (exclusive). + * + * @implNote This method first calls {@code nextLong()} to obtain + * a {@code long} value that is assumed to be pseudorandomly + * chosen uniformly and independently from the 264 + * possible {@code long} values (that is, each of the 264 + * possible long values is equally likely to be chosen). + * Under some circumstances (when the specified range is not + * a power of 2), {@code nextLong()} may be called additional times + * to ensure that that the values in the specified range are + * equally likely to be chosen (provided the assumption holds). + *

+ * The implementation considers four cases: + *

    + * + *
  1. If the {@code} bound} is less than or equal to the {@code origin} + * (indicated an unbounded form), the 64-bit {@code long} value + * obtained from {@code nextLong()} is returned directly. + * + *
  2. Otherwise, if the length n of the specified range is an + * exact power of two 2m for some integer + * m, then return the sum of {@code origin} and the + * m lowest-order bits of the value from {@code nextLong()}. + * + *
  3. Otherwise, if the length n of the specified range + * is less than 263, then the basic idea is to use the + * remainder modulo n of the value from {@code nextLong()}, + * but with this approach some values will be over-represented. + * Therefore a loop is used to avoid potential bias by rejecting + * candidates that are too large. Assuming that the results from + * {@code nextLong()} are truly chosen uniformly and independently, + * the expected number of iterations will be somewhere between + * 1 and 2, depending on the precise value of n. + * + *
  4. Otherwise, the length n of the specified range + * cannot be represented as a positive {@code long} value. + * A loop repeatedly calls {@code nextlong()} until obtaining + * a suitable candidate, Again, the expected number of iterations + * is less than 2. + * + *
+ * + * @param rng a random number generator to be used as a + * source of pseudorandom {@code long} values + * @param origin the least value that can be produced, + * unless greater than or equal to {@code bound} + * @param bound the upper bound (exclusive), unless {@code origin} + * is greater than or equal to {@code bound} + * + * @return a pseudorandomly chosen {@code long} value, + * which will be between {@code origin} (inclusive) and + * {@code bound} exclusive unless {@code origin} + * is greater than or equal to {@code bound} + */ + public static long boundedNextLong(RandomGenerator rng, long origin, long bound) { + long r = rng.nextLong(); + if (origin < bound) { + // It's not case (1). + final long n = bound - origin; + final long m = n - 1; + if ((n & m) == 0L) { + // It is case (2): length of range is a power of 2. + r = (r & m) + origin; + } else if (n > 0L) { + // It is case (3): need to reject over-represented candidates. + /* This loop takes an unlovable form (but it works): + because the first candidate is already available, + we need a break-in-the-middle construction, + which is concisely but cryptically performed + within the while-condition of a body-less for loop. */ + for (long u = r >>> 1; // ensure nonnegative + u + m - (r = u % n) < 0L; // rejection check + u = rng.nextLong() >>> 1) // retry + ; + r += origin; + } + else { + // It is case (4): length of range not representable as long. + while (r < origin || r >= bound) + r = rng.nextLong(); + } + } + return r; + } + + /** + * This is the form of {@code nextLong} used by the public method + * {@code nextLong(bound)}. This is essentially a version of + * {@code boundedNextLong(origin, bound)} that has been + * specialized for the case where the {@code origin} is zero + * and the {@code bound} is greater than zero. The value + * returned is chosen pseudorandomly from nonnegative integer + * values less than {@code bound}. + * + * @implNote This method first calls {@code nextLong()} to obtain + * a {@code long} value that is assumed to be pseudorandomly + * chosen uniformly and independently from the 264 + * possible {@code long} values (that is, each of the 264 + * possible long values is equally likely to be chosen). + * Under some circumstances (when the specified range is not + * a power of 2), {@code nextLong()} may be called additional times + * to ensure that that the values in the specified range are + * equally likely to be chosen (provided the assumption holds). + *

+ * The implementation considers two cases: + *

    + * + *
  1. If {@code bound} is an exact power of two 2m + * for some integer m, then return the sum of {@code origin} + * and the m lowest-order bits of the value from + * {@code nextLong()}. + * + *
  2. Otherwise, the basic idea is to use the remainder modulo + * bound of the value from {@code nextLong()}, + * but with this approach some values will be over-represented. + * Therefore a loop is used to avoid potential bias by rejecting + * candidates that vare too large. Assuming that the results from + * {@code nextLong()} are truly chosen uniformly and independently, + * the expected number of iterations will be somewhere between + * 1 and 2, depending on the precise value of bound. + * + *
+ * + * @param rng a random number generator to be used as a + * source of pseudorandom {@code long} values + * @param bound the upper bound (exclusive); must be greater than zero + * + * @return a pseudorandomly chosen {@code long} value + */ + public static long boundedNextLong(RandomGenerator rng, long bound) { + // Specialize boundedNextLong for origin == 0, bound > 0 + final long m = bound - 1; + long r = rng.nextLong(); + if ((bound & m) == 0L) { + // The bound is a power of 2. + r &= m; + } else { + // Must reject over-represented candidates + /* This loop takes an unlovable form (but it works): + because the first candidate is already available, + we need a break-in-the-middle construction, + which is concisely but cryptically performed + within the while-condition of a body-less for loop. */ + for (long u = r >>> 1; + u + m - (r = u % bound) < 0L; + u = rng.nextLong() >>> 1) + ; + } + return r; + } + + /** + * This is the form of {@code nextInt} used by an {@link IntStream} + * {@link Spliterator} and by the public method + * {@code nextInt(origin, bound)}. If {@code origin} is greater + * than {@code bound}, then this method simply calls the unbounded + * version of {@code nextInt()}, choosing pseudorandomly from + * among all 264 possible {@code int} values}, and + * otherwise uses one or more calls to {@code nextInt()} to + * choose a value pseudorandomly from the possible values + * between {@code origin} (inclusive) and {@code bound} (exclusive). + * + * @param rng a random number generator to be used as a + * source of pseudorandom {@code int} values + * @param origin the least value that can be produced, + * unless greater than or equal to {@code bound} + * @param bound the upper bound (exclusive), unless {@code origin} + * is greater than or equal to {@code bound} + * + * @return a pseudorandomly chosen {@code int} value, + * which will be between {@code origin} (inclusive) and + * {@code bound} exclusive unless {@code origin} + * is greater than or equal to {@code bound} + * + * @implNote The implementation of this method is identical to + * the implementation of {@code nextLong(origin, bound)} + * except that {@code int} values and the {@code nextInt()} + * method are used rather than {@code long} values and the + * {@code nextLong()} method. + */ + public static int boundedNextInt(RandomGenerator rng, int origin, int bound) { + int r = rng.nextInt(); + if (origin < bound) { + // It's not case (1). + final int n = bound - origin; + final int m = n - 1; + if ((n & m) == 0) { + // It is case (2): length of range is a power of 2. + r = (r & m) + origin; + } else if (n > 0) { + // It is case (3): need to reject over-represented candidates. + for (int u = r >>> 1; + u + m - (r = u % n) < 0; + u = rng.nextInt() >>> 1) + ; + r += origin; + } + else { + // It is case (4): length of range not representable as long. + while (r < origin || r >= bound) { + r = rng.nextInt(); + } + } + } + return r; + } + + /** + * This is the form of {@code nextInt} used by the public method + * {@code nextInt(bound)}. This is essentially a version of + * {@code boundedNextInt(origin, bound)} that has been + * specialized for the case where the {@code origin} is zero + * and the {@code bound} is greater than zero. The value + * returned is chosen pseudorandomly from nonnegative integer + * values less than {@code bound}. + * + * @param rng a random number generator to be used as a + * source of pseudorandom {@code long} values + * @param bound the upper bound (exclusive); must be greater than zero + * + * @return a pseudorandomly chosen {@code long} value + * + * @implNote The implementation of this method is identical to + * the implementation of {@code nextLong(bound)} + * except that {@code int} values and the {@code nextInt()} + * method are used rather than {@code long} values and the + * {@code nextLong()} method. + */ + public static int boundedNextInt(RandomGenerator rng, int bound) { + // Specialize boundedNextInt for origin == 0, bound > 0 + final int m = bound - 1; + int r = rng.nextInt(); + if ((bound & m) == 0) { + // The bound is a power of 2. + r &= m; + } else { + // Must reject over-represented candidates + for (int u = r >>> 1; + u + m - (r = u % bound) < 0; + u = rng.nextInt() >>> 1) + ; + } + return r; + } + + /** + * This is the form of {@code nextDouble} used by a {@link DoubleStream} + * {@link Spliterator} and by the public method + * {@code nextDouble(origin, bound)}. If {@code origin} is greater + * than {@code bound}, then this method simply calls the unbounded + * version of {@code nextDouble()}, and otherwise scales and translates + * the result of a call to {@code nextDouble()} so that it lies + * between {@code origin} (inclusive) and {@code bound} (exclusive). + * + * @implNote The implementation considers two cases: + *
    + * + *
  1. If the {@code bound} is less than or equal to the {@code origin} + * (indicated an unbounded form), the 64-bit {@code double} value + * obtained from {@code nextDouble()} is returned directly. + * + *
  2. Otherwise, the result of a call to {@code nextDouble} is + * multiplied by {@code (bound - origin)}, then {@code origin} + * is added, and then if this this result is not less than + * {@code bound} (which can sometimes occur because of rounding), + * it is replaced with the largest {@code double} value that + * is less than {@code bound}. + * + *
+ * + * @param rng a random number generator to be used as a + * source of pseudorandom {@code double} values + * @param origin the least value that can be produced, + * unless greater than or equal to {@code bound}; must be finite + * @param bound the upper bound (exclusive), unless {@code origin} + * is greater than or equal to {@code bound}; must be finite + * @return a pseudorandomly chosen {@code double} value, + * which will be between {@code origin} (inclusive) and + * {@code bound} exclusive unless {@code origin} + * is greater than or equal to {@code bound}, + * in which case it will be between 0.0 (inclusive) + * and 1.0 (exclusive) + */ + public static double boundedNextDouble(RandomGenerator rng, double origin, double bound) { + double r = rng.nextDouble(); + if (origin < bound) { + r = r * (bound - origin) + origin; + if (r >= bound) // may need to correct a rounding problem + r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); + } + return r; + } + + /** + * This is the form of {@code nextDouble} used by the public method + * {@code nextDouble(bound)}. This is essentially a version of + * {@code boundedNextDouble(origin, bound)} that has been + * specialized for the case where the {@code origin} is zero + * and the {@code bound} is greater than zero. + * + * @implNote The result of a call to {@code nextDouble} is + * multiplied by {@code bound}, and then if this result is + * not less than {@code bound} (which can sometimes occur + * because of rounding), it is replaced with the largest + * {@code double} value that is less than {@code bound}. + * + * @param rng a random number generator to be used as a + * source of pseudorandom {@code double} values + * @param bound the upper bound (exclusive); must be finite and + * greater than zero + * @return a pseudorandomly chosen {@code double} value + * between zero (inclusive) and {@code bound} (exclusive) + */ + public static double boundedNextDouble(RandomGenerator rng, double bound) { + // Specialize boundedNextDouble for origin == 0, bound > 0 + double r = rng.nextDouble(); + r = r * bound; + if (r >= bound) // may need to correct a rounding problem + r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); + return r; + } + + /** + * This is the form of {@code nextFloat} used by a {@code Stream} + * {@link Spliterator} (if there were any) and by the public method + * {@code nextFloat(origin, bound)}. If {@code origin} is greater + * than {@code bound}, then this method simply calls the unbounded + * version of {@code nextFloat()}, and otherwise scales and translates + * the result of a call to {@code nextFloat()} so that it lies + * between {@code origin} (inclusive) and {@code bound} (exclusive). + * + * @implNote The implementation of this method is identical to + * the implementation of {@code nextDouble(origin, bound)} + * except that {@code float} values and the {@code nextFloat()} + * method are used rather than {@code double} values and the + * {@code nextDouble()} method. + * + * @param rng a random number generator to be used as a + * source of pseudorandom {@code float} values + * @param origin the least value that can be produced, + * unless greater than or equal to {@code bound}; must be finite + * @param bound the upper bound (exclusive), unless {@code origin} + * is greater than or equal to {@code bound}; must be finite + * @return a pseudorandomly chosen {@code float} value, + * which will be between {@code origin} (inclusive) and + * {@code bound} exclusive unless {@code origin} + * is greater than or equal to {@code bound}, + * in which case it will be between 0.0 (inclusive) + * and 1.0 (exclusive) + */ + public static float boundedNextFloat(RandomGenerator rng, float origin, float bound) { + float r = rng.nextFloat(); + if (origin < bound) { + r = r * (bound - origin) + origin; + if (r >= bound) // may need to correct a rounding problem + r = Float.intBitsToFloat(Float.floatToIntBits(bound) - 1); + } + return r; + } + + /** + * This is the form of {@code nextFloat} used by the public method + * {@code nextFloat(bound)}. This is essentially a version of + * {@code boundedNextFloat(origin, bound)} that has been + * specialized for the case where the {@code origin} is zero + * and the {@code bound} is greater than zero. + * + * @implNote The implementation of this method is identical to + * the implementation of {@code nextDouble(bound)} + * except that {@code float} values and the {@code nextFloat()} + * method are used rather than {@code double} values and the + * {@code nextDouble()} method. + * + * @param rng a random number generator to be used as a + * source of pseudorandom {@code float} values + * @param bound the upper bound (exclusive); must be finite and + * greater than zero + * @return a pseudorandomly chosen {@code float} value + * between zero (inclusive) and {@code bound} (exclusive) + */ + public static float boundedNextFloat(RandomGenerator rng, float bound) { + // Specialize boundedNextFloat for origin == 0, bound > 0 + float r = rng.nextFloat(); + r = r * bound; + if (r >= bound) // may need to correct a rounding problem + r = Float.intBitsToFloat(Float.floatToIntBits(bound) - 1); + return r; + } + + // The following decides which of two strategies initialSeed() will use. + private static boolean secureRandomSeedRequested() { + String pp = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction( + "java.util.secureRandomSeed")); + return (pp != null && pp.equalsIgnoreCase("true")); + } + + private static final boolean useSecureRandomSeed = secureRandomSeedRequested(); + + /** + * Returns a {@code long} value (chosen from some + * machine-dependent entropy source) that may be useful for + * initializing a source of seed values for instances of {@link RandomGenerator} + * created by zero-argument constructors. (This method should + * not be called repeatedly, once per constructed + * object; at most it should be called once per class.) + * + * @return a {@code long} value, randomly chosen using + * appropriate environmental entropy + */ + public static long initialSeed() { + if (useSecureRandomSeed) { + byte[] seedBytes = java.security.SecureRandom.getSeed(8); + long s = (long)(seedBytes[0]) & 0xffL; + for (int i = 1; i < 8; ++i) + s = (s << 8) | ((long)(seedBytes[i]) & 0xffL); + return s; + } + return (mixStafford13(System.currentTimeMillis()) ^ + mixStafford13(System.nanoTime())); + } + + /** + * The first 32 bits of the golden ratio (1+sqrt(5))/2, forced to be odd. + * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value. + */ + public static final int GOLDEN_RATIO_32 = 0x9e3779b9; + + /** + * The first 64 bits of the golden ratio (1+sqrt(5))/2, forced to be odd. + * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value. + */ + public static final long GOLDEN_RATIO_64 = 0x9e3779b97f4a7c15L; + + /** + * The first 32 bits of the silver ratio 1+sqrt(2), forced to be odd. + * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value. + */ + public static final int SILVER_RATIO_32 = 0x6A09E667; + + /** + * The first 64 bits of the silver ratio 1+sqrt(2), forced to be odd. + * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value. + */ + public static final long SILVER_RATIO_64 = 0x6A09E667F3BCC909L; + + /** + * Computes the 64-bit mixing function for MurmurHash3. + * This is a 64-bit hashing function with excellent avalanche statistics. + * https://github.com/aappleby/smhasher/wiki/MurmurHash3 + * + * Note that if the argument {@code z} is 0, the result is 0. + * + * @param z any long value + * + * @return the result of hashing z + */ + public static long mixMurmur64(long z) { + z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL; + z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L; + return z ^ (z >>> 33); + } + + /** + * Computes Stafford variant 13 of the 64-bit mixing function for MurmurHash3. + * This is a 64-bit hashing function with excellent avalanche statistics. + * http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html + * + * Note that if the argument {@code z} is 0, the result is 0. + * + * @param z any long value + * + * @return the result of hashing z + */ + public static long mixStafford13(long z) { + z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L; + z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL; + return z ^ (z >>> 31); + } + + /** + * Computes Doug Lea's 64-bit mixing function. + * This is a 64-bit hashing function with excellent avalanche statistics. + * It has the advantages of using the same multiplicative constant twice + * and of using only 32-bit shifts. + * + * Note that if the argument {@code z} is 0, the result is 0. + * + * @param z any long value + * + * @return the result of hashing z + */ + public static long mixLea64(long z) { + z = (z ^ (z >>> 32)) * 0xdaba0b6eb09322e3L; + z = (z ^ (z >>> 32)) * 0xdaba0b6eb09322e3L; + return z ^ (z >>> 32); + } + + /** + * Computes the 32-bit mixing function for MurmurHash3. + * This is a 32-bit hashing function with excellent avalanche statistics. + * https://github.com/aappleby/smhasher/wiki/MurmurHash3 + * + * Note that if the argument {@code z} is 0, the result is 0. + * + * @param z any long value + * + * @return the result of hashing z + */ + public static int mixMurmur32(int z) { + z = (z ^ (z >>> 16)) * 0x85ebca6b; + z = (z ^ (z >>> 13)) * 0xc2b2ae35; + return z ^ (z >>> 16); + } + + /** + * Computes Doug Lea's 32-bit mixing function. + * This is a 32-bit hashing function with excellent avalanche statistics. + * It has the advantages of using the same multiplicative constant twice + * and of using only 16-bit shifts. + * + * Note that if the argument {@code z} is 0, the result is 0. + * + * @param z any long value + * + * @return the result of hashing z + */ + public static int mixLea32(int z) { + z = (z ^ (z >>> 16)) * 0xd36d884b; + z = (z ^ (z >>> 16)) * 0xd36d884b; + return z ^ (z >>> 16); + } + + // Non-public (package only) support for spliterators needed by AbstractSplittableGenerator + // and AbstractArbitrarilyJumpableGenerator and AbstractSharedGenerator + + /** + * Base class for making Spliterator classes for streams of randomly chosen values. + */ + public abstract static class RandomSpliterator { + + /** low range value */ + public long index; + + /** high range value */ + public final long fence; + + /** + * Constructor + * + * @param index low range value + * @param fence high range value + */ + public RandomSpliterator(long index, long fence) { + this.index = index; this.fence = fence; + } + + /** + * Returns estimated size. + * + * @return estimated size + */ + public long estimateSize() { + return fence - index; + } + + /** + * Returns characteristics. + * + * @return characteristics + */ + public int characteristics() { + return (Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.NONNULL | Spliterator.IMMUTABLE); + } + } + + + /* + * Implementation support for nextExponential() and nextGaussian() methods of RandomGenerator. + * + * Each is implemented using McFarland's fast modified ziggurat algorithm (largely + * table-driven, with rare cases handled by computation and rejection sampling). + * Walker's alias method for sampling a discrete distribution also plays a role. + * + * The tables themselves, as well as a number of associated parameters, are defined + * in class java.util.DoubleZigguratTables, which is automatically generated by the + * program create_ziggurat_tables.c (which takes only a few seconds to run). + * + * For more information about the algorithms, see these articles: + * + * Christopher D. McFarland. 2016 (published online 24 Jun 2015). A modified ziggurat + * algorithm for generating exponentially and normally distributed pseudorandom numbers. + * Journal of Statistical Computation and Simulation 86 (7), pages 1281-1294. + * https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234 + * Also at https://arxiv.org/abs/1403.6870 (26 March 2014). + * + * Alastair J. Walker. 1977. An efficient method for generating discrete random + * variables with general distributions. ACM Trans. Math. Software 3, 3 + * (September 1977), 253-256. DOI: https://doi.org/10.1145/355744.355749 + * + * Certain details of these algorithms depend critically on the quality of the + * low-order bits delivered by NextLong(). These algorithms should not be used + * with RNG algorithms (such as a simple Linear Congruential Generator) whose + * low-order output bits do not have good statistical quality. + */ + + // Implementation support for nextExponential() + + static double computeNextExponential(RandomGenerator rng) { + long U1 = rng.nextLong(); + // Experimentation on a variety of machines indicates that it is overall much faster + // to do the following & and < operations on longs rather than first cast U1 to int + // (but then we need to cast to int before doing the array indexing operation). + long i = U1 & DoubleZigguratTables.exponentialLayerMask; + if (i < DoubleZigguratTables.exponentialNumberOfLayers) { + // This is the fast path (occurring more than 98% of the time). Make an early exit. + return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1); + } + // We didn't use the upper part of U1 after all. We'll be able to use it later. + + for (double extra = 0.0; ; ) { + // Use Walker's alias method to sample an (unsigned) integer j from a discrete + // probability distribution that includes the tail and all the ziggurat overhangs; + // j will be less than DoubleZigguratTables.exponentialNumberOfLayers + 1. + long UA = rng.nextLong(); + int j = (int)UA & DoubleZigguratTables.exponentialAliasMask; + if (UA >= DoubleZigguratTables.exponentialAliasThreshold[j]) { + j = DoubleZigguratTables.exponentialAliasMap[j] & + DoubleZigguratTables.exponentialSignCorrectionMask; + } + if (j > 0) { // Sample overhang j + // For the exponential distribution, every overhang is convex. + final double[] X = DoubleZigguratTables.exponentialX; + final double[] Y = DoubleZigguratTables.exponentialY; + for (;; U1 = (rng.nextLong() >>> 1)) { + long U2 = (rng.nextLong() >>> 1); + // Compute the actual x-coordinate of the randomly chosen point. + double x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); + // Does the point lie below the curve? + long Udiff = U2 - U1; + if (Udiff < 0) { + // We picked a point in the upper-right triangle. None of those can be + // accepted. So remap the point into the lower-left triangle and try that. + // In effect, we swap U1 and U2, and invert the sign of Udiff. + Udiff = -Udiff; + U2 = U1; + U1 -= Udiff; + } + if (Udiff >= DoubleZigguratTables.exponentialConvexMargin) { + return x + extra; // The chosen point is way below the curve; accept it. + } + // Compute the actual y-coordinate of the randomly chosen point. + double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + // Now see how that y-coordinate compares to the curve + if (y <= Math.exp(-x)) { + return x + extra; // The chosen point is below the curve; accept it. + } + // Otherwise, we reject this sample and have to try again. + } + } + // We are now committed to sampling from the tail. We could do a recursive call + // and then add X[0] but we save some time and stack space by using an iterative loop. + extra += DoubleZigguratTables.exponentialX0; + // This is like the first five lines of this method, but if it returns, it first adds "extra". + U1 = rng.nextLong(); + i = U1 & DoubleZigguratTables.exponentialLayerMask; + if (i < DoubleZigguratTables.exponentialNumberOfLayers) { + return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1) + extra; + } + } + } + + // Implementation support for nextGaussian() + + static double computeNextGaussian(RandomGenerator rng) { + long U1 = rng.nextLong(); + // Experimentation on a variety of machines indicates that it is overall much faster + // to do the following & and < operations on longs rather than first cast U1 to int + // (but then we need to cast to int before doing the array indexing operation). + long i = U1 & DoubleZigguratTables.normalLayerMask; + + if (i < DoubleZigguratTables.normalNumberOfLayers) { + // This is the fast path (occurring more than 98% of the time). Make an early exit. + return DoubleZigguratTables.normalX[(int)i] * U1; // Note that the sign bit of U1 is used here. + } + // We didn't use the upper part of U1 after all. + // Pull U1 apart into a sign bit and a 63-bit value for later use. + double signBit = (U1 >= 0) ? 1.0 : -1.0; + U1 = (U1 << 1) >>> 1; + + // Use Walker's alias method to sample an (unsigned) integer j from a discrete + // probability distribution that includes the tail and all the ziggurat overhangs; + // j will be less than DoubleZigguratTables.normalNumberOfLayers + 1. + long UA = rng.nextLong(); + int j = (int)UA & DoubleZigguratTables.normalAliasMask; + if (UA >= DoubleZigguratTables.normalAliasThreshold[j]) { + j = DoubleZigguratTables.normalAliasMap[j] & DoubleZigguratTables.normalSignCorrectionMask; + } + + double x; + // Now the goal is to choose the result, which will be multiplied by signBit just before return. + + // There are four kinds of overhangs: + // + // j == 0 : Sample from tail + // 0 < j < normalInflectionIndex : Overhang is convex; can reject upper-right triangle + // j == normalInflectionIndex : Overhang includes the inflection point + // j > normalInflectionIndex : Overhang is concave; can accept point in lower-left triangle + // + // Choose one of four loops to compute x, each specialized for a specific kind of overhang. + // Conditional statements are arranged such that the more likely outcomes are first. + + // In the three cases other than the tail case: + // U1 represents a fraction (scaled by 2**63) of the width of rectangle measured from the left. + // U2 represents a fraction (scaled by 2**63) of the height of rectangle measured from the top. + // Together they indicate a randomly chosen point within the rectangle. + + final double[] X = DoubleZigguratTables.normalX; + final double[] Y = DoubleZigguratTables.normalY; + if (j > DoubleZigguratTables.normalInflectionIndex) { // Concave overhang + for (;; U1 = (rng.nextLong() >>> 1)) { + long U2 = (rng.nextLong() >>> 1); + // Compute the actual x-coordinate of the randomly chosen point. + x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); + // Does the point lie below the curve? + long Udiff = U2 - U1; + if (Udiff >= 0) { + break; // The chosen point is in the lower-left triangle; accept it. + } + if (Udiff <= -DoubleZigguratTables.normalConcaveMargin) { + continue; // The chosen point is way above the curve; reject it. + } + // Compute the actual y-coordinate of the randomly chosen point. + double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + // Now see how that y-coordinate compares to the curve + if (y <= Math.exp(-0.5*x*x)) { + break; // The chosen point is below the curve; accept it. + } + // Otherwise, we reject this sample and have to try again. + } + } else if (j == 0) { // Tail + // Tail-sampling method of Marsaglia and Tsang. See any one of: + // Marsaglia and Tsang. 1984. A fast, easily implemented method for sampling from decreasing + // or symmetric unimodal density functions. SIAM J. Sci. Stat. Comput. 5, 349-359. + // Marsaglia and Tsang. 1998. The Monty Python method for generating random variables. + // ACM Trans. Math. Softw. 24, 3 (September 1998), 341-350. See page 342, step (4). + // http://doi.org/10.1145/292395.292453 + // Thomas, Luk, Leong, and Villasenor. 2007. Gaussian random number generators. + // ACM Comput. Surv. 39, 4, Article 11 (November 2007). See Algorithm 16. + // http://doi.org/10.1145/1287620.1287622 + // Compute two separate random exponential samples and then compare them in certain way. + do { + x = (1.0 / DoubleZigguratTables.normalX0) * computeNextExponential(rng); + } while (computeNextExponential(rng) < 0.5*x*x); + x += DoubleZigguratTables.normalX0; + } else if (j < DoubleZigguratTables.normalInflectionIndex) { // Convex overhang + for (;; U1 = (rng.nextLong() >>> 1)) { + long U2 = (rng.nextLong() >>> 1); + // Compute the actual x-coordinate of the randomly chosen point. + x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); + // Does the point lie below the curve? + long Udiff = U2 - U1; + if (Udiff < 0) { + // We picked a point in the upper-right triangle. None of those can be accepted. + // So remap the point into the lower-left triangle and try that. + // In effect, we swap U1 and U2, and invert the sign of Udiff. + Udiff = -Udiff; + U2 = U1; + U1 -= Udiff; + } + if (Udiff >= DoubleZigguratTables.normalConvexMargin) { + break; // The chosen point is way below the curve; accept it. + } + // Compute the actual y-coordinate of the randomly chosen point. + double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + // Now see how that y-coordinate compares to the curve + if (y <= Math.exp(-0.5*x*x)) break; // The chosen point is below the curve; accept it. + // Otherwise, we reject this sample and have to try again. + } + } else { + // The overhang includes the inflection point, so the curve is both convex and concave + for (;; U1 = (rng.nextLong() >>> 1)) { + long U2 = (rng.nextLong() >>> 1); + // Compute the actual x-coordinate of the randomly chosen point. + x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1); + // Does the point lie below the curve? + long Udiff = U2 - U1; + if (Udiff >= DoubleZigguratTables.normalConvexMargin) { + break; // The chosen point is way below the curve; accept it. + } + if (Udiff <= -DoubleZigguratTables.normalConcaveMargin) { + continue; // The chosen point is way above the curve; reject it. + } + // Compute the actual y-coordinate of the randomly chosen point. + double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2); + // Now see how that y-coordinate compares to the curve + if (y <= Math.exp(-0.5*x*x)) { + break; // The chosen point is below the curve; accept it. + } + // Otherwise, we reject this sample and have to try again. + } + } + return signBit*x; + } + + /** + * This class overrides the stream-producing methods (such as {@code ints()}) + * in class {@link AbstractGenerator} to provide {@link Spliterator}-based + * implmentations that support potentially parallel execution. + * + * To implement a pseudorandom number generator, the programmer needs + * only to extend this class and provide implementations for the methods + * {@code nextInt()}, {@code nextLong()}, {@code makeIntsSpliterator}, + * {@code makeLongsSpliterator}, and {@code makeDoublesSpliterator}. + * + * This class is not public; it provides shared code to the public + * classes {@link AbstractSplittableGenerator}, {@link AbstractSharedGenerator}, + * and {@link AbstractArbitrarilyJumpableGenerator}. + * + * @since 14 + */ + public abstract static class AbstractSpliteratorGenerator implements RandomGenerator { + /* + * Implementation Overview. + * + * This class provides most of the "user API" methods needed to + * satisfy the interface RandomGenerator. An implementation of this + * interface need only extend this class and provide implementations + * of six methods: nextInt, nextLong, and nextDouble (the versions + * that take no arguments) and makeIntsSpliterator, + * makeLongsSpliterator, and makeDoublesSpliterator. + * + * File organization: First the non-public abstract methods needed + * to create spliterators, then the main public methods. + */ + + /** + * Create an instance of {@link Spliterator.OfInt} that for each traversal position + * between the specified index (inclusive) and the specified fence (exclusive) generates + * a pseudorandomly chosen {@code int} value between the specified origin (inclusive) and + * the specified bound (exclusive). + * + * @param index the (inclusive) lower bound on traversal positions + * @param fence the (exclusive) upper bound on traversal positions + * @param origin the (inclusive) lower bound on the pseudorandom values to be generated + * @param bound the (exclusive) upper bound on the pseudorandom values to be generated + * @return an instance of {@link Spliterator.OfInt} + */ + public abstract Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound); + + /** + * Create an instance of {@link Spliterator.OfLong} that for each traversal position + * between the specified index (inclusive) and the specified fence (exclusive) generates + * a pseudorandomly chosen {@code long} value between the specified origin (inclusive) and + * the specified bound (exclusive). + * + * @param index the (inclusive) lower bound on traversal positions + * @param fence the (exclusive) upper bound on traversal positions + * @param origin the (inclusive) lower bound on the pseudorandom values to be generated + * @param bound the (exclusive) upper bound on the pseudorandom values to be generated + * @return an instance of {@link Spliterator.OfLong} + */ + public abstract Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound); + + /** + * Create an instance of {@link Spliterator.OfDouble} that for each traversal position + * between the specified index (inclusive) and the specified fence (exclusive) generates + * a pseudorandomly chosen {@code double} value between the specified origin (inclusive) and + * the specified bound (exclusive). + * + * @param index the (inclusive) lower bound on traversal positions + * @param fence the (exclusive) upper bound on traversal positions + * @param origin the (inclusive) lower bound on the pseudorandom values to be generated + * @param bound the (exclusive) upper bound on the pseudorandom values to be generated + * @return an instance of {@link Spliterator.OfDouble} + */ + public abstract Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound); + + /* ---------------- public methods ---------------- */ + + // stream methods, coded in a way intended to better isolate for + // maintenance purposes the small differences across forms. + + private static IntStream intStream(Spliterator.OfInt srng) { + return StreamSupport.intStream(srng, false); + } + + private static LongStream longStream(Spliterator.OfLong srng) { + return StreamSupport.longStream(srng, false); + } + + private static DoubleStream doubleStream(Spliterator.OfDouble srng) { + return StreamSupport.doubleStream(srng, false); + } + + /** + * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code int} + * values from this generator and/or one split from it. + * + * @param streamSize the number of values to generate + * + * @return a stream of pseudorandom {@code int} values + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + */ + public IntStream ints(long streamSize) { + RandomSupport.checkStreamSize(streamSize); + return intStream(makeIntsSpliterator(0L, streamSize, Integer.MAX_VALUE, 0)); + } + + /** + * Returns an effectively unlimited stream of pseudorandomly chosen + * {@code int} values. + * + * @implNote The implementation of this method is effectively + * equivalent to {@code ints(Long.MAX_VALUE)}. + * + * @return a stream of pseudorandomly chosen {@code int} values + */ + + public IntStream ints() { + return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0)); + } + + /** + * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code int} + * values from this generator and/or one split from it; each value conforms to the given origin + * (inclusive) and bound (exclusive). + * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * + * @return a stream of pseudorandom {@code int} values, each with the given origin (inclusive) + * and bound (exclusive) + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero, or {@code + * randomNumberOrigin} is greater than or equal to {@code + * randomNumberBound} + */ + public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) { + RandomSupport.checkStreamSize(streamSize); + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return intStream(makeIntsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound)); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code int} values from this + * generator and/or one split from it; each value conforms to the given origin (inclusive) and + * bound (exclusive). + * + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * + * @return a stream of pseudorandom {@code int} values, each with the given origin (inclusive) + * and bound (exclusive) + * + * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to + * {@code randomNumberBound} + * + * @implNote This method is implemented to be equivalent to {@code ints(Long.MAX_VALUE, + * randomNumberOrigin, randomNumberBound)}. + */ + public IntStream ints(int randomNumberOrigin, int randomNumberBound) { + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)); + } + + /** + * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code long} + * values from this generator and/or one split from it. + * + * @param streamSize the number of values to generate + * + * @return a stream of pseudorandom {@code long} values + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + */ + public LongStream longs(long streamSize) { + RandomSupport.checkStreamSize(streamSize); + return longStream(makeLongsSpliterator(0L, streamSize, Long.MAX_VALUE, 0L)); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code long} values from this + * generator and/or one split from it. + * + * @return a stream of pseudorandom {@code long} values + * + * @implNote This method is implemented to be equivalent to {@code + * longs(Long.MAX_VALUE)}. + */ + public LongStream longs() { + return longStream(makeLongsSpliterator(0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L)); + } + + /** + * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code long} + * values from this generator and/or one split from it; each value conforms to the given origin + * (inclusive) and bound (exclusive). + * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * + * @return a stream of pseudorandom {@code long} values, each with the given origin (inclusive) + * and bound (exclusive) + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero, or {@code + * randomNumberOrigin} is greater than or equal to {@code + * randomNumberBound} + */ + public LongStream longs(long streamSize, long randomNumberOrigin, + long randomNumberBound) { + RandomSupport.checkStreamSize(streamSize); + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return longStream(makeLongsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound)); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code long} values from this + * generator and/or one split from it; each value conforms to the given origin (inclusive) and + * bound (exclusive). + * + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * + * @return a stream of pseudorandom {@code long} values, each with the given origin (inclusive) + * and bound (exclusive) + * + * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to + * {@code randomNumberBound} + * + * @implNote This method is implemented to be equivalent to {@code longs(Long.MAX_VALUE, + * randomNumberOrigin, randomNumberBound)}. + */ + public LongStream longs(long randomNumberOrigin, long randomNumberBound) { + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return StreamSupport.longStream + (makeLongsSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), + false); + } + + /** + * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code double} + * values from this generator and/or one split from it; each value is between zero (inclusive) + * and one (exclusive). + * + * @param streamSize the number of values to generate + * + * @return a stream of {@code double} values + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + */ + public DoubleStream doubles(long streamSize) { + RandomSupport.checkStreamSize(streamSize); + return doubleStream(makeDoublesSpliterator(0L, streamSize, Double.MAX_VALUE, 0.0)); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code double} values from this + * generator and/or one split from it; each value is between zero (inclusive) and one + * (exclusive). + * + * @return a stream of pseudorandom {@code double} values + * + * @implNote This method is implemented to be equivalent to {@code + * doubles(Long.MAX_VALUE)}. + */ + public DoubleStream doubles() { + return doubleStream(makeDoublesSpliterator(0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0)); + } + + /** + * Returns a stream producing the given {@code streamSize} number of pseudorandom {@code double} + * values from this generator and/or one split from it; each value conforms to the given origin + * (inclusive) and bound (exclusive). + * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * + * @return a stream of pseudorandom {@code double} values, each with the given origin + * (inclusive) and bound (exclusive) + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to + * {@code randomNumberBound} + */ + public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) { + RandomSupport.checkStreamSize(streamSize); + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return doubleStream(makeDoublesSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound)); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code double} values from this + * generator and/or one split from it; each value conforms to the given origin (inclusive) and + * bound (exclusive). + * + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * + * @return a stream of pseudorandom {@code double} values, each with the given origin + * (inclusive) and bound (exclusive) + * + * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to + * {@code randomNumberBound} + * + * @implNote This method is implemented to be equivalent to {@code + * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. + */ + public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) { + RandomSupport.checkRange(randomNumberOrigin, randomNumberBound); + return doubleStream(makeDoublesSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)); + } + + } + + /** + * This class provides much of the implementation of the + * {@link ArbitrarilyJumpableGenerator} interface, to minimize the effort + * required to implement that interface. + * + * To implement a pseudorandom number generator, the programmer needs + * only to extend this class and provide implementations for the + * methods {@link #nextInt()}, {@link #nextLong()}, {@link #copy()}, + * {@link #jump(double)}, {@link #jumpPowerOfTwo(int)}, + * {@link #defaultJumpDistance()}, and {@link #defaultLeapDistance()}. + * + * (If the pseudorandom number generator also has the ability to split, + * then the programmer may wish to consider instead extending + * {@link AbstractSplittableGenerator}.) + * + * The programmer should generally provide at least three constructors: + * one that takes no arguments, one that accepts a {@code long} + * seed value, and one that accepts an array of seed {@code byte} values. + * This class provides a public {@code initialSeed()} method that may + * be useful in initializing some static state from which to derive + * defaults seeds for use by the no-argument constructor. + * + * For the stream methods (such as {@code ints()} and {@code splits()}), + * this class provides {@link Spliterator}-based implementations that + * allow parallel execution when appropriate. In this respect + * {@link ArbitrarilyJumpableGenerator} differs from {@link JumpableGenerator}, + * which provides very simple implementations that produce + * sequential streams only. + * + *

An implementation of the {@link AbstractArbitrarilyJumpableGenerator} class + * must provide concrete definitions for the methods {@code nextInt()}, + * {@code nextLong}, {@code period()}, {@code copy()}, {@code jump(double)}, + * {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}. + * Default implementations are provided for all other methods. + * + * The documentation for each non-abstract method in this class + * describes its implementation in detail. Each of these methods may + * be overridden if the pseudorandom number generator being + * implemented admits a more efficient implementation. + * + * @since 14 + */ + public abstract static class AbstractArbitrarilyJumpableGenerator + extends AbstractSpliteratorGenerator implements RandomGenerator.ArbitrarilyJumpableGenerator { + + /* + * Implementation Overview. + * + * This class provides most of the "user API" methods needed to satisfy + * the interface ArbitrarilyJumpableGenerator. Most of these methods + * are in turn inherited from AbstractGenerator and the non-public class + * AbstractSpliteratorGenerator; this file implements four versions of the + * jumps method and defines the spliterators necessary to support them. + * + * File organization: First the non-public methods needed by the class + * AbstractSpliteratorGenerator, then the main public methods, followed by some + * custom spliterator classes needed for stream methods. + */ + + // IllegalArgumentException messages + static final String BadLogDistance = "logDistance must be non-negative"; + + // Methods required by class AbstractSpliteratorGenerator + public Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) { + return new RandomIntsSpliterator(this, index, fence, origin, bound); + } + public Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) { + return new RandomLongsSpliterator(this, index, fence, origin, bound); + } + public Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound) { + return new RandomDoublesSpliterator(this, index, fence, origin, bound); + } + + // Similar methods used by this class + Spliterator makeJumpsSpliterator(long index, long fence, double distance) { + return new RandomJumpsSpliterator(this, index, fence, distance); + } + Spliterator makeLeapsSpliterator(long index, long fence, double distance) { + return new RandomLeapsSpliterator(this, index, fence, distance); + } + Spliterator makeArbitraryJumpsSpliterator(long index, long fence, double distance) { + return new RandomArbitraryJumpsSpliterator(this, index, fence, distance); + } + + /* ---------------- public methods ---------------- */ + + /** + * Returns a new generator whose internal state is an exact copy + * of this generator (therefore their future behavior should be + * identical if subjected to the same series of operations). + * + * @return a new object that is a copy of this generator + */ + public abstract AbstractArbitrarilyJumpableGenerator copy(); + + // Stream methods for jumping + + private static Stream stream(Spliterator srng) { + return StreamSupport.stream(srng, false); + } + + /** + * Returns an effectively unlimited stream of new pseudorandom number generators, each of which + * implements the {@link RandomGenerator} interface, produced by jumping copies of this + * generator by different integer multiples of the default jump distance. + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @implNote This method is implemented to be equivalent to {@code + * jumps(Long.MAX_VALUE)}. + */ + public Stream jumps() { + return stream(makeJumpsSpliterator(0L, Long.MAX_VALUE, defaultJumpDistance())); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * new pseudorandom number generators, each of which implements the + * {@link RandomGenerator} interface, produced by jumping copies of this generator + * by different integer multiples of the default jump distance. + * + * @param streamSize the number of generators to generate + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + */ + public Stream jumps(long streamSize) { + RandomSupport.checkStreamSize(streamSize); + return stream(makeJumpsSpliterator(0L, streamSize, defaultJumpDistance())); + } + + /** + * Returns an effectively unlimited stream of new pseudorandom number generators, each of which + * implements the {@link RandomGenerator} interface, produced by jumping copies of this + * generator by different integer multiples of the specified jump distance. + * + * @param distance a distance to jump forward within the state cycle + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @implNote This method is implemented to be equivalent to {@code + * jumps(Long.MAX_VALUE)}. + */ + public Stream jumps(double distance) { + return stream(makeArbitraryJumpsSpliterator(0L, Long.MAX_VALUE, distance)); + } + + /** + * Returns a stream producing the given {@code streamSize} number of new pseudorandom number + * generators, each of which implements the {@link RandomGenerator} interface, produced by + * jumping copies of this generator by different integer multiples of the specified jump + * distance. + * + * @param streamSize the number of generators to generate + * @param distance a distance to jump forward within the state cycle + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + */ + public Stream jumps(long streamSize, double distance) { + RandomSupport.checkStreamSize(streamSize); + return stream(makeArbitraryJumpsSpliterator(0L, streamSize, distance)); + } + + /** + * Alter the state of this pseudorandom number generator so as to + * jump forward a very large, fixed distance (typically 2128 + * or more) within its state cycle. The distance used is that + * returned by method {@code defaultLeapDistance()}. + */ + public void leap() { + jump(defaultLeapDistance()); + } + + // Stream methods for leaping + + /** + * Returns an effectively unlimited stream of new pseudorandom number generators, each of which + * implements the {@link RandomGenerator} interface, produced by jumping copies of this + * generator by different integer multiples of the default leap distance. + * + * @implNote This method is implemented to be equivalent to {@code leaps(Long.MAX_VALUE)}. + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + */ + public Stream leaps() { + return stream(makeLeapsSpliterator(0L, Long.MAX_VALUE, defaultLeapDistance())); + } + + /** + * Returns a stream producing the given {@code streamSize} number of new pseudorandom number + * generators, each of which implements the {@link RandomGenerator} interface, produced by + * jumping copies of this generator by different integer multiples of the default leap + * distance. + * + * @param streamSize the number of generators to generate + * + * @return a stream of objects that implement the {@link RandomGenerator} interface + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + */ + public Stream leaps(long streamSize) { + return stream(makeLeapsSpliterator(0L, streamSize, defaultLeapDistance())); + } + + + /** + * Spliterator for int streams. We multiplex the four int versions into one class by treating a + * bound less than origin as unbounded, and also by treating "infinite" as equivalent to + * {@code Long.MAX_VALUE}. For splits, we choose to override the method {@code trySplit()} to + * try to optimize execution speed: instead of dividing a range in half, it breaks off the + * largest possible chunk whose size is a power of two such that the remaining chunk is not + * empty. In this way, the necessary jump distances will tend to be powers of two. The long + * and double versions of this class are identical except for types. + */ + static class RandomIntsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfInt { + final ArbitrarilyJumpableGenerator generatingGenerator; + final int origin; + final int bound; + + RandomIntsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, int origin, int bound) { + super(index, fence); + this.origin = origin; this.bound = bound; + this.generatingGenerator = generatingGenerator; + } + + public Spliterator.OfInt trySplit() { + long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta; + if (m <= i) return null; + index = m; + ArbitrarilyJumpableGenerator r = generatingGenerator; + return new RandomIntsSpliterator(r.copyAndJump((double)delta), i, m, origin, bound); + } + + public boolean tryAdvance(IntConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(RandomSupport.boundedNextInt(generatingGenerator, origin, bound)); + index = i + 1; + return true; + } + else return false; + } + + public void forEachRemaining(IntConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + ArbitrarilyJumpableGenerator r = generatingGenerator; + int o = origin, b = bound; + do { + consumer.accept(RandomSupport.boundedNextInt(r, o, b)); + } while (++i < f); + } + } + } + + /** + * Spliterator for long streams. + */ + static class RandomLongsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfLong { + final ArbitrarilyJumpableGenerator generatingGenerator; + final long origin; + final long bound; + + RandomLongsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, long origin, long bound) { + super(index, fence); + this.generatingGenerator = generatingGenerator; + this.origin = origin; this.bound = bound; + } + + public Spliterator.OfLong trySplit() { + long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta; + if (m <= i) return null; + index = m; + ArbitrarilyJumpableGenerator r = generatingGenerator; + return new RandomLongsSpliterator(r.copyAndJump((double)delta), i, m, origin, bound); + } + + public boolean tryAdvance(LongConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(RandomSupport.boundedNextLong(generatingGenerator, origin, bound)); + index = i + 1; + return true; + } + else return false; + } + + public void forEachRemaining(LongConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + ArbitrarilyJumpableGenerator r = generatingGenerator; + long o = origin, b = bound; + do { + consumer.accept(RandomSupport.boundedNextLong(r, o, b)); + } while (++i < f); + } + } + } + + /** + * Spliterator for double streams. + */ + static class RandomDoublesSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfDouble { + final ArbitrarilyJumpableGenerator generatingGenerator; + final double origin; + final double bound; + + RandomDoublesSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double origin, double bound) { + super(index, fence); + this.generatingGenerator = generatingGenerator; + this.origin = origin; this.bound = bound; + } + + public Spliterator.OfDouble trySplit() { + + long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta; + if (m <= i) return null; + index = m; + ArbitrarilyJumpableGenerator r = generatingGenerator; + return new RandomDoublesSpliterator(r.copyAndJump((double)delta), i, m, origin, bound); + } + + public boolean tryAdvance(DoubleConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(RandomSupport.boundedNextDouble(generatingGenerator, origin, bound)); + index = i + 1; + return true; + } + else return false; + } + + public void forEachRemaining(DoubleConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + ArbitrarilyJumpableGenerator r = generatingGenerator; + double o = origin, b = bound; + do { + consumer.accept(RandomSupport.boundedNextDouble(r, o, b)); + } while (++i < f); + } + } + } + + // Spliterators for producing new generators by jumping or leaping. The + // complete implementation of each of these spliterators is right here. + // In the same manner as for the preceding spliterators, the method trySplit() is + // coded to optimize execution speed: instead of dividing a range + // in half, it breaks off the largest possible chunk whose + // size is a power of two such that the remaining chunk is not + // empty. In this way, the necessary jump distances will tend to be + // powers of two. + + /** + * Spliterator for stream of generators of type RandomGenerator produced by jumps. + */ + static class RandomJumpsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator { + ArbitrarilyJumpableGenerator generatingGenerator; + final double distance; + + RandomJumpsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double distance) { + super(index, fence); + this.generatingGenerator = generatingGenerator; this.distance = distance; + } + + public Spliterator trySplit() { + long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta; + if (m <= i) return null; + index = m; + ArbitrarilyJumpableGenerator r = generatingGenerator; + // Because delta is a power of two, (distance * (double)delta) can always be computed exactly. + return new RandomJumpsSpliterator(r.copyAndJump(distance * (double)delta), i, m, distance); + } + + public boolean tryAdvance(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(generatingGenerator.copyAndJump(distance)); + index = i + 1; + return true; + } + return false; + } + + public void forEachRemaining(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + ArbitrarilyJumpableGenerator r = generatingGenerator; + do { + consumer.accept(r.copyAndJump(distance)); + } while (++i < f); + } + } + } + + /** + * Spliterator for stream of generators of type RandomGenerator produced by leaps. + */ + static class RandomLeapsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator { + ArbitrarilyJumpableGenerator generatingGenerator; + final double distance; + + RandomLeapsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double distance) { + super(index, fence); + this.generatingGenerator = generatingGenerator; this.distance = distance; + } + + public Spliterator trySplit() { + long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta; + if (m <= i) return null; + index = m; + // Because delta is a power of two, (distance * (double)delta) can always be computed exactly. + return new RandomLeapsSpliterator(generatingGenerator.copyAndJump(distance * (double)delta), i, m, distance); + } + + public boolean tryAdvance(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(generatingGenerator.copyAndJump(distance)); + index = i + 1; + return true; + } + return false; + } + + public void forEachRemaining(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + ArbitrarilyJumpableGenerator r = generatingGenerator; + do { + consumer.accept(r.copyAndJump(distance)); + } while (++i < f); + } + } + } + + /** + * Spliterator for stream of generators of type RandomGenerator produced by arbitrary jumps. + */ + static class RandomArbitraryJumpsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator { + ArbitrarilyJumpableGenerator generatingGenerator; + final double distance; + + RandomArbitraryJumpsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double distance) { + super(index, fence); + this.generatingGenerator = generatingGenerator; this.distance = distance; + } + + public Spliterator trySplit() { + long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta; + if (m <= i) return null; + index = m; + // Because delta is a power of two, (distance * (double)delta) can always be computed exactly. + return new RandomArbitraryJumpsSpliterator(generatingGenerator.copyAndJump(distance * (double)delta), i, m, distance); + } + + public boolean tryAdvance(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(generatingGenerator.copyAndJump(distance)); + index = i + 1; + return true; + } + return false; + } + + public void forEachRemaining(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + ArbitrarilyJumpableGenerator r = generatingGenerator; + do { + consumer.accept(r.copyAndJump(distance)); + } while (++i < f); + } + } + } + + } + + /** + * This class provides much of the implementation of the {@link SplittableGenerator} interface, to + * minimize the effort required to implement this interface. + *

+ * To implement a pseudorandom number generator, the programmer needs only to extend this class and + * provide implementations for the methods {@code nextInt()}, {@code nextLong()}, {@code period()}, + * and {@code split(SplittableGenerator)}. + *

+ * (If the pseudorandom number generator also has the ability to jump an arbitrary + * specified distance, then the programmer may wish to consider instead extending the + * class {@link AbstractArbitrarilyJumpableGenerator}. See also the class + * {@link AbstractSplittableWithBrineGenerator}.) + *

+ * The programmer should generally provide at least three constructors: one that takes no arguments, + * one that accepts a {@code long} seed value, and one that accepts an array of seed {@code byte} + * values. This class provides a public {@code initialSeed()} method that may be useful in + * initializing some static state from which to derive defaults seeds for use by the no-argument + * constructor. + *

+ * For the stream methods (such as {@code ints()} and {@code splits()}), this class provides + * {@link Spliterator}-based implementations that allow parallel execution when appropriate. + *

+ * The documentation for each non-abstract method in this class describes its implementation in + * detail. Each of these methods may be overridden if the pseudorandom number generator being + * implemented admits a more efficient implementation. + * + * @since 14 + */ + public abstract static class AbstractSplittableGenerator extends AbstractSpliteratorGenerator implements SplittableGenerator { + + /* + * Implementation Overview. + * + * This class provides most of the "user API" methods needed to + * satisfy the interface SplittableGenerator. Most of these methods + * are in turn inherited from AbstractGenerator and the non-public class + * AbstractSpliteratorGenerator; this class provides two versions of the + * splits method and defines the spliterators necessary to support + * them. + * + * File organization: First the non-public methods needed by the class + * AbstractSpliteratorGenerator, then the main public methods, followed by some + * custom spliterator classes. + */ + + public Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) { + return new RandomIntsSpliterator(this, index, fence, origin, bound); + } + + public Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) { + return new RandomLongsSpliterator(this, index, fence, origin, bound); + } + + public Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound) { + return new RandomDoublesSpliterator(this, index, fence, origin, bound); + } + + Spliterator makeSplitsSpliterator(long index, long fence, SplittableGenerator source) { + return new RandomSplitsSpliterator(source, index, fence, this); + } + + /* ---------------- public methods ---------------- */ + + /** + * Implements the @code{split()} method as {@code this.split(this)}. + * + * @return the new {@link SplittableGenerator} instance + */ + public SplittableGenerator split() { + return this.split(this); + } + + // Stream methods for splittings + + /** + * Returns an effectively unlimited stream of new pseudorandom number generators, each of which + * implements the {@link SplittableGenerator} interface. + *

+ * This pseudorandom number generator provides the entropy used to seed the new ones. + * + * @return a stream of {@link SplittableGenerator} objects + * + * @implNote This method is implemented to be equivalent to {@code splits(Long.MAX_VALUE)}. + */ + public Stream splits() { + return this.splits(Long.MAX_VALUE, this); + } + + /** + * Returns a stream producing the given {@code streamSize} number of new pseudorandom number + * generators, each of which implements the {@link SplittableGenerator} interface. + *

+ * This pseudorandom number generator provides the entropy used to seed the new ones. + * + * @param streamSize the number of values to generate + * + * @return a stream of {@link SplittableGenerator} objects + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + */ + public Stream splits(long streamSize) { + return this.splits(streamSize, this); + } + + /** + * Returns an effectively unlimited stream of new pseudorandom number generators, each of which + * implements the {@link SplittableGenerator} interface. + * + * @param source a {@link SplittableGenerator} instance to be used instead of this one as a source of + * pseudorandom bits used to initialize the state of the new ones. + * + * @return a stream of {@link SplittableGenerator} objects + * + * @implNote This method is implemented to be equivalent to {@code splits(Long.MAX_VALUE)}. + */ + public Stream splits(SplittableGenerator source) { + return this.splits(Long.MAX_VALUE, source); + } + + /** + * Returns a stream producing the given {@code streamSize} number of new pseudorandom number + * generators, each of which implements the {@link SplittableGenerator} interface. + * + * @param streamSize the number of values to generate + * @param source a {@link SplittableGenerator} instance to be used instead of this one as a source + * of pseudorandom bits used to initialize the state of the new ones. + * + * @return a stream of {@link SplittableGenerator} objects + * + * @throws IllegalArgumentException if {@code streamSize} is less than zero + */ + public Stream splits(long streamSize, SplittableGenerator source) { + RandomSupport.checkStreamSize(streamSize); + return StreamSupport.stream(makeSplitsSpliterator(0L, streamSize, source), false); + } + + /** + * Spliterator for int streams. We multiplex the four int versions into one class by treating a + * bound less than origin as unbounded, and also by treating "infinite" as equivalent to + * {@code Long.MAX_VALUE}. For splits, it uses the standard divide-by-two approach. The long and + * double versions of this class are identical except for types. + */ + static class RandomIntsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfInt { + final SplittableGenerator generatingGenerator; + final int origin; + final int bound; + + RandomIntsSpliterator(SplittableGenerator generatingGenerator, long index, long fence, int origin, int bound) { + super(index, fence); + this.generatingGenerator = generatingGenerator; + this.origin = origin; this.bound = bound; + } + + public Spliterator.OfInt trySplit() { + long i = index, m = (i + fence) >>> 1; + if (m <= i) return null; + index = m; + return new RandomIntsSpliterator(generatingGenerator.split(), i, m, origin, bound); + } + + public boolean tryAdvance(IntConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(RandomSupport.boundedNextInt(generatingGenerator, origin, bound)); + index = i + 1; + return true; + } + else return false; + } + + public void forEachRemaining(IntConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + RandomGenerator r = generatingGenerator; + int o = origin, b = bound; + do { + consumer.accept(RandomSupport.boundedNextInt(r, o, b)); + } while (++i < f); + } + } + } + + /** + * Spliterator for long streams. + */ + static class RandomLongsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfLong { + final SplittableGenerator generatingGenerator; + final long origin; + final long bound; + + RandomLongsSpliterator(SplittableGenerator generatingGenerator, long index, long fence, long origin, long bound) { + super(index, fence); + this.generatingGenerator = generatingGenerator; + this.origin = origin; this.bound = bound; + } + + public Spliterator.OfLong trySplit() { + long i = index, m = (i + fence) >>> 1; + if (m <= i) return null; + index = m; + return new RandomLongsSpliterator(generatingGenerator.split(), i, m, origin, bound); + } + + public boolean tryAdvance(LongConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(RandomSupport.boundedNextLong(generatingGenerator, origin, bound)); + index = i + 1; + return true; + } + else return false; + } + + public void forEachRemaining(LongConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + RandomGenerator r = generatingGenerator; + long o = origin, b = bound; + do { + consumer.accept(RandomSupport.boundedNextLong(r, o, b)); + } while (++i < f); + } + } + } + + /** + * Spliterator for double streams. + */ + static class RandomDoublesSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfDouble { + final SplittableGenerator generatingGenerator; + final double origin; + final double bound; + + RandomDoublesSpliterator(SplittableGenerator generatingGenerator, long index, long fence, double origin, double bound) { + super(index, fence); + this.generatingGenerator = generatingGenerator; + this.origin = origin; this.bound = bound; + } + + public Spliterator.OfDouble trySplit() { + long i = index, m = (i + fence) >>> 1; + if (m <= i) return null; + index = m; + return new RandomDoublesSpliterator(generatingGenerator.split(), i, m, origin, bound); + } + + public boolean tryAdvance(DoubleConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(RandomSupport.boundedNextDouble(generatingGenerator, origin, bound)); + index = i + 1; + return true; + } + else return false; + } + + public void forEachRemaining(DoubleConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + RandomGenerator r = generatingGenerator; + double o = origin, b = bound; + do { + consumer.accept(RandomSupport.boundedNextDouble(r, o, b)); + } while (++i < f); + } + } + } + + /** + * Spliterator for stream of generators of type SplittableGenerator. We multiplex the two + * versions into one class by treating "infinite" as equivalent to Long.MAX_VALUE. + * For splits, it uses the standard divide-by-two approach. + */ + static class RandomSplitsSpliterator extends RandomSpliterator implements Spliterator { + final SplittableGenerator generatingGenerator; + final SplittableGenerator constructingGenerator; + + RandomSplitsSpliterator(SplittableGenerator generatingGenerator, + long index, long fence, + SplittableGenerator constructingGenerator) { + super(index, fence); + this.generatingGenerator = generatingGenerator; + this.constructingGenerator = constructingGenerator; + } + + public Spliterator trySplit() { + long i = index, m = (i + fence) >>> 1; + if (m <= i) return null; + index = m; + return new RandomSplitsSpliterator(generatingGenerator.split(), i, m, constructingGenerator); + } + + public boolean tryAdvance(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(constructingGenerator.split(generatingGenerator)); + index = i + 1; + return true; + } + else return false; + } + + public void forEachRemaining(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + SplittableGenerator c = constructingGenerator; + SplittableGenerator r = generatingGenerator; + do { + consumer.accept(c.split(r)); + } while (++i < f); + } + } + } + + } + + /** + * This class provides much of the implementation of the {@link SplittableGenerator} interface, to + * minimize the effort required to implement this interface. It is similar to the class + * {@link AbstractSplittableGenerator} but makes use of the brine technique for ensuring that + * distinct generators created by a single call to a {@code splits} method have distinct state cycles. + *

+ * To implement a pseudorandom number generator, the programmer needs only to extend this class and + * provide implementations for the methods {@code nextInt()}, {@code nextLong()}, {@code period()}, + * and {@code split(SplittableGenerator, long)}. + *

+ * The programmer should generally provide at least three constructors: one that takes no arguments, + * one that accepts a {@code long} seed value, and one that accepts an array of seed {@code byte} + * values. This class provides a public {@code initialSeed()} method that may be useful in + * initializing some static state from which to derive defaults seeds for use by the no-argument + * constructor. + *

+ * For the stream methods (such as {@code ints()} and {@code splits()}), this class provides + * {@link Spliterator}-based implementations that allow parallel execution when appropriate. + *

+ * The documentation for each non-abstract method in this class describes its implementation in + * detail. Each of these methods may be overridden if the pseudorandom number generator being + * implemented admits a more efficient implementation. + * + * @since 14 + */ + public abstract static class AbstractSplittableWithBrineGenerator + extends AbstractSplittableGenerator { + + /* + * Implementation Overview. + * + * This class provides most of the "user API" methods needed to + * satisfy the interface SplittableGenerator. Most of these methods + * are in turn inherited from AbstractSplittableGenerator and the non-public class + * AbstractSpliteratorGenerator; this class provides four versions of the + * splits method and defines the spliterators necessary to support + * them. + * + * File organization: First the non-public methods needed by the class + * AbstractSplittableWithBrineGenerator, then the main public methods, + * followed by some custom spliterator classes needed for stream methods. + */ + + // The salt consists groups of bits each SALT_SHIFT in size, starting from + // the left-hand (high-order) end of the word. We can regard them as + // digits base (1 << SALT_SHIFT). If SALT_SHIFT does not divide 64 + // evenly, then any leftover bits at the low end of the word are zero. + // The lowest digit of the salt is set to the largest possible digit + // (all 1-bits, or ((1 << SALT_SHIFT) - 1)); all other digits are set + // to a randomly chosen value less than that largest possible digit. + // The salt may be shifted left by SALT_SHIFT any number of times. + // If any salt remains in the word, its right-hand end can be identified + // by searching from left to right for an occurrence of a digit that is + // all 1-bits (not that we ever do that; this is simply a proof that one + // can identify the boundary between the salt and the index if any salt + // remains in the word). The idea is that before computing the bitwise OR + // of an index and the salt, one can first check to see whether the + // bitwise AND is nonzero; if so, one can shift the salt left by + // SALT_SHIFT and try again. In this way, when the bitwise OR is + // computed, if the salt is nonzero then its rightmost 1-bit is to the + // left of the leftmost 1-bit of the index. + + // We need 2 <= SALT_SHIFT <= 63 (3 through 8 are good values; 4 is probably best) + static final int SALT_SHIFT = 4; + + // Methods required by class AbstractSpliteratorGenerator (override) + Spliterator makeSplitsSpliterator(long index, long fence, SplittableGenerator source) { + // This little algorithm to generate a new salt value is carefully + // designed to work even if SALT_SHIFT does not evenly divide 64 + // (the number of bits in a long value). + long bits = nextLong(); + long multiplier = (1 << SALT_SHIFT) - 1; + long salt = multiplier << (64 - SALT_SHIFT); + while ((salt & multiplier) != 0) { + long digit = Math.multiplyHigh(bits, multiplier); + salt = (salt >>> SALT_SHIFT) | (digit << (64 - SALT_SHIFT)); + bits *= multiplier; + } + // This is the point at which newly generated salt gets injected into + // the root of a newly created brine-generating splits-spliterator. + return new RandomSplitsSpliteratorWithSalt(source, index, fence, this, salt); + } + + /* ---------------- public methods ---------------- */ + + // Stream methods for splitting + + /** + * Constructs and returns a new instance of {@code AbstractSplittableWithBrineGenerator} + * that shares no mutable state with this instance. However, with very high + * probability, the set of values collectively generated by the two objects + * should have the same statistical properties as if the same quantity of + * values were generated by a single thread using a single may be + * {@code AbstractSplittableWithBrineGenerator} object. Either or both of the two objects + * further split using the {@code split()} method, and the same expected + * statistical properties apply to the entire set of generators constructed + * by such recursive splitting. + * + * @param brine a long value, of which the low 63 bits provide a unique id + * among calls to this method for constructing a single series of Generator objects. + * + * @return the new {@code AbstractSplittableWithBrineGenerator} instance + */ + public SplittableGenerator split(long brine) { + return this.split(this, brine); + } + + /** + * Constructs and returns a new instance of {@code L64X128MixRandom} + * that shares no mutable state with this instance. + * However, with very high probability, the set of values collectively + * generated by the two objects has the same statistical properties as if + * same the quantity of values were generated by a single thread using + * a single {@code L64X128MixRandom} object. Either or both of the two + * objects may be further split using the {@code split} method, + * and the same expected statistical properties apply to the + * entire set of generators constructed by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @return a new instance of {@code L64X128MixRandom} + */ + public SplittableGenerator split(SplittableGenerator source) { + // It's a one-off: supply randomly chosen brine + return this.split(source, source.nextLong()); + } + + /** + * Constructs and returns a new instance of {@code AbstractSplittableWithBrineGenerator} + * that shares no mutable state with this instance. However, with very high + * probability, the set of values collectively generated by the two objects + * should have the same statistical properties as if the same quantity of + * values were generated by a single thread using a single may be + * {@code AbstractSplittableWithBrineGenerator} object. Either or both of the two objects + * further split using the {@code split()} method, and the same expected + * statistical properties apply to the entire set of generators constructed + * by such recursive splitting. + * + * @param source a {@code SplittableGenerator} instance to be used instead + * of this one as a source of pseudorandom bits used to + * initialize the state of the new ones. + * @param brine a long value, of which the low 63 bits provide a unique id + * among calls to this method for constructing a single series of + * {@code RandomGenerator} objects. + * + * @return the new {@code AbstractSplittableWithBrineGenerator} instance + */ + public abstract SplittableGenerator split(SplittableGenerator source, long brine); + + + /* ---------------- spliterator ---------------- */ + /** + * Alternate spliterator for stream of generators of type SplittableGenerator. We multiplex + * the two versions into one class by treating "infinite" as equivalent to Long.MAX_VALUE. + * For splits, it uses the standard divide-by-two approach. + * + * This differs from {@code SplittableGenerator.RandomSplitsSpliterator} in that it provides + * a brine argument (a mixture of salt and an index) when calling the {@code split} method. + */ + static class RandomSplitsSpliteratorWithSalt + extends RandomSpliterator implements Spliterator { + + final SplittableGenerator generatingGenerator; + final AbstractSplittableWithBrineGenerator constructingGenerator; + long salt; + + // Important invariant: 0 <= index <= fence + + // Important invariant: if salt and index are both nonzero, + // the rightmost 1-bit of salt is to the left of the leftmost 1-bit of index. + // If necessary, the salt can be leftshifted by SALT_SHIFT as many times as + // necessary to maintain the invariant. + + RandomSplitsSpliteratorWithSalt(SplittableGenerator generatingGenerator, long index, long fence, + AbstractSplittableWithBrineGenerator constructingGenerator, long salt) { + super(index, fence); + this.generatingGenerator = generatingGenerator; + this.constructingGenerator = constructingGenerator; + while ((salt != 0) && (Long.compareUnsigned(salt & -salt, index) <= 0)) { + salt = salt << SALT_SHIFT; + } + this.salt = salt; + } + + public Spliterator trySplit() { + long i = index, m = (i + fence) >>> 1; + if (m <= i) return null; + RandomSplitsSpliteratorWithSalt result = + new RandomSplitsSpliteratorWithSalt(generatingGenerator.split(), i, m, constructingGenerator, salt); + index = m; + while ((salt != 0) && (Long.compareUnsigned(salt & -salt, index) <= 0)) { + salt = salt << SALT_SHIFT; + } + return result; + } + + public boolean tryAdvance(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(constructingGenerator.split(generatingGenerator, salt | i)); + ++i; + index = i; + if ((i & salt) != 0) salt <<= SALT_SHIFT; + return true; + } + return false; + } + + public void forEachRemaining(Consumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + AbstractSplittableWithBrineGenerator c = constructingGenerator; + SplittableGenerator r = generatingGenerator; + do { + consumer.accept(c.split(r, salt | i)); + ++i; + if ((i & salt) != 0) salt <<= SALT_SHIFT; + } while (i < f); + } + } + } + + } + +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/Xoroshiro128StarStar.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/Xoroshiro128StarStar.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.LeapableGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link Xoroshiro128StarStar} implements + * interfaces {@link RandomGenerator} and {@link LeapableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new {@link Xoroshiro128StarStar} objects + * by "jumping" or "leaping". + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + *

+ * The class {@link Xoroshiro128StarStar} uses the {@code xoroshiro128} algorithm, + * version 1.0 (parameters 24, 16, 37), with the "**" scrambler (a mixing function). + * Its state consists of two {@code long} fields {@code x0} and {@code x1}, + * which can take on any values provided that they are not both zero. + * The period of this generator is 2128-1. + *

+ * The 64-bit values produced by the {@code nextLong()} method are equidistributed. + * To be precise, over the course of the cycle of length 2128-1, + * each nonzero {@code long} value is generated 264 times, + * but the value 0 is generated only 264-1 times. + * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()} + * methods are likewise equidistributed. + *

+ * In fact, the 64-bit values produced by the {@code nextLong()} method are 2-equidistributed. + * To be precise: consider the (overlapping) length-2 subsequences of the cycle of 64-bit + * values produced by {@code nextLong()} (assuming no other methods are called that would + * affect the state). There are 2128-1 such subsequences, and each subsequence, + * which consists of 2 64-bit values, can have one of 2128 values. Of those + * 2128 subsequence values, each one is generated exactly once over the course + * of the entire cycle, except that the subsequence (0, 0) never appears. + * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()} + * methods are likewise 2-equidistributed, but note that that the subsequence (0, 0) + * can also appear (but occurring somewhat less frequently than all other subsequences), + * because the values produced by those methods have fewer than 64 randomly chosen bits. + *

+ * Instances {@link Xoroshiro128StarStar} are not thread-safe. + * They are designed to be used so that each thread as its own instance. + * The methods {@link #jump} and {@link #leap} and {@link #jumps} and {@link #leaps} + * can be used to construct new instances of {@link Xoroshiro128StarStar} that traverse + * other parts of the state cycle. + *

+ * Instances of {@link Xoroshiro128StarStar} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class Xoroshiro128StarStar implements LeapableGenerator { + + /* + * Implementation Overview. + * + * This is an implementation of the xoroshiro128** algorithm written + * in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org), + * and updated with improved parameters in 2018. + * See http://xoshiro.di.unimi.it and these two papers: + * + * Sebastiano Vigna. 2016. An Experimental Exploration of Marsaglia's + * xorshift Generators, Scrambled. ACM Transactions on Mathematical + * Software 42, 4, Article 30 (June 2016), 23 pages. + * https://doi.org/10.1145/2845077 + * + * David Blackman and Sebastiano Vigna. 2018. Scrambled Linear + * Pseudorandom Number Generators. Computing Research Repository (CoRR). + * http://arxiv.org/abs/1805.01407 + * + * The jump operation moves the current generator forward by 2*64 + * steps; this has the same effect as calling nextLong() 2**64 + * times, but is much faster. Similarly, the leap operation moves + * the current generator forward by 2*96 steps; this has the same + * effect as calling nextLong() 2**96 times, but is much faster. + * The copy method may be used to make a copy of the current + * generator. Thus one may repeatedly and cumulatively copy and + * jump to produce a sequence of generators whose states are well + * spaced apart along the overall state cycle (indeed, the jumps() + * and leaps() methods each produce a stream of such generators). + * The generators can then be parceled out to other threads. + * + * File organization: First the non-public methods that constitute the + * main algorithm, then the public methods. Note that many methods are + * defined by classes {@link AbstractJumpableGenerator} and {@link AbstractGenerator}. + */ + + /* ---------------- static fields ---------------- */ + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong DEFAULT_GEN = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is 2**128 - 1. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE); + + /* ---------------- instance fields ---------------- */ + + /** + * The per-instance state. + * At least one of the two fields x0 and x1 must be nonzero. + */ + private long x0, x1; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param x0 first word of the initial state + * @param x1 second word of the initial state + */ + public Xoroshiro128StarStar(long x0, long x1) { + this.x0 = x0; + this.x1 = x1; + // If x0 and x1 are both zero, we must choose nonzero values. + if ((x0 | x1) == 0) { + this.x0 = RandomSupport.GOLDEN_RATIO_64; + this.x1 = RandomSupport.SILVER_RATIO_64; + } + } + + /** + * Creates a new instance of {@link Xoroshiro128StarStar} using the + * specified {@code long} value as the initial seed. Instances of + * {@link Xoroshiro128StarStar} created with the same seed in the same + * program generate identical sequences of values. + * + * @param seed the initial seed + */ + public Xoroshiro128StarStar(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The x values are then filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer. + this(RandomSupport.mixStafford13(seed ^= RandomSupport.SILVER_RATIO_64), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link Xoroshiro128StarStar} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public Xoroshiro128StarStar() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(DEFAULT_GEN.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link Xoroshiro128StarStar} using the specified array of + * initial seed bytes. Instances of {@link Xoroshiro128StarStar} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public Xoroshiro128StarStar(byte[] seed) { + // Convert the seed to 2 long values, which are not both zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 2, 2); + long x0 = data[0], x1 = data[1]; + this.x0 = x0; + this.x1 = x1; + } + + /* ---------------- public methods ---------------- */ + + public Xoroshiro128StarStar copy() { return new Xoroshiro128StarStar(x0, x1); } + + /* + * To the extent possible under law, the author has dedicated all copyright and related and + * neighboring rights to this software to the public domain worldwide. This software is + * distributed without any warranty. + *

+ * See . + */ + + /* + * This is the successor to xorshift128+. It is the fastest full-period generator passing + * BigCrush without systematic failures, but due to the relatively short period it is acceptable + * only for applications with a mild amount of parallelism; otherwise, use a xorshift1024* + * generator. + *

+ * Beside passing BigCrush, this generator passes the PractRand test suite up to (and included) + * 16TB, with the exception of binary rank tests, which fail due to the lowest bit being an + * LFSR; all other bits pass all tests. We suggest to use a sign test to extract a random + * Boolean value. + *

+ * Note that the generator uses a simulated rotate operation, which most C compilers will turn + * into a single instruction. In Java, you can use Long.rotateLeft(). In languages that do not + * make low-level rotation instructions accessible xorshift128+ could be faster. + *

+ * The state must be seeded so that it is not everywhere zero. If you have a 64-bit seed, we + * suggest to seed a splitmix64 generator and use its output to fill s. + */ + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + final long s0 = x0; + long s1 = x1; + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + final long result = Long.rotateLeft(s0 * 5, 7) * 9; // "starstar" mixing function + + s1 ^= s0; + x0 = Long.rotateLeft(s0, 24) ^ s1 ^ (s1 << 16); // a, b + x1 = Long.rotateLeft(s1, 37); // c + + return result; + } + + public BigInteger period() { + return PERIOD; + } + + public double defaultJumpDistance() { + return 0x1.0p64; + } + + public double defaultLeapDistance() { + return 0x1.0p96; + } + + private static final long[] JUMP_TABLE = { 0xdf900294d8f554a5L, 0x170865df4b3201fcL }; + + private static final long[] LEAP_TABLE = { 0xd2a98b26625eee7bL, 0xdddf9b1090aa7ac1L }; + + /** + * This is the jump function for the generator. It is equivalent to 2**64 calls to nextLong(); + * it can be used to generate 2**64 non-overlapping subsequences for parallel computations. + */ + public void jump() { + jumpAlgorithm(JUMP_TABLE); + } + + /** + * This is the long-jump function for the generator. It is equivalent to 2**96 calls to next(); + * it can be used to generate 2**32 starting points, from each of which jump() will generate + * 2**32 non-overlapping subsequences for parallel distributed computations. + */ + public void leap() { + jumpAlgorithm(LEAP_TABLE); + } + + private void jumpAlgorithm(long[] table) { + long s0 = 0, s1 = 0; + for (int i = 0; i < table.length; i++) { + for (int b = 0; b < 64; b++) { + if ((table[i] & (1L << b)) != 0) { + s0 ^= x0; + s1 ^= x1; + } + nextLong(); + } + x0 = s0; + x1 = s1; + } + } +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/Xoshiro256StarStar.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/Xoshiro256StarStar.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.random.RandomGenerator.LeapableGenerator; + +/** + * A generator of uniform pseudorandom values applicable for use in + * (among other contexts) isolated parallel computations that may + * generate subtasks. Class {@link Xoshiro256StarStar} implements + * interfaces {@link RandomGenerator} and {@link LeapableGenerator}, + * and therefore supports methods for producing pseudorandomly chosen + * numbers of type {@code int}, {@code long}, {@code float}, and {@code double} + * as well as creating new {@link Xoshiro256StarStar} objects + * by "jumping" or "leaping". + *

+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites + * that measure independence and uniformity properties of random number generators. + * (Most recently validated with + * version 1.2.3 of TestU01 + * and version 0.90 of PractRand. + * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()} + * method but also the result of bit-reversing each value produced by {@code nextLong()}.) + * These tests validate only the methods for certain + * types and ranges, but similar properties are expected to hold, at + * least approximately, for others as well. + *

+ * The class {@link Xoshiro256StarStar} uses the {@code xoshiro256} algorithm, + * version 1.0 (parameters 17, 45), with the "**" scrambler (a mixing function). + * Its state consists of four {@code long} fields {@code x0}, {@code x1}, {@code x2}, + * and {@code x3}, which can take on any values provided that they are not all zero. + * The period of this generator is 2256-1. + *

+ * The 64-bit values produced by the {@code nextLong()} method are equidistributed. + * To be precise, over the course of the cycle of length 2256-1, + * each nonzero {@code long} value is generated 2192 times, + * but the value 0 is generated only 2192-1 times. + * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()} + * methods are likewise equidistributed. + *

+ * In fact, the 64-bit values produced by the {@code nextLong()} method are 4-equidistributed. + * To be precise: consider the (overlapping) length-4 subsequences of the cycle of 64-bit + * values produced by {@code nextLong()} (assuming no other methods are called that would + * affect the state). There are 2256-1 such subsequences, and each subsequence, + * which consists of 4 64-bit values, can have one of 2256 values. Of those + * 2256 subsequence values, each one is generated exactly once over the course + * of the entire cycle, except that the subsequence (0, 0, 0, 0) never appears. + * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()} + * methods are likewise 4-equidistributed, but note that that the subsequence (0, 0, 0, 0) + * can also appear (but occurring somewhat less frequently than all other subsequences), + * because the values produced by those methods have fewer than 64 randomly chosen bits. + *

+ * Instances {@link Xoshiro256StarStar} are not thread-safe. + * They are designed to be used so that each thread as its own instance. + * The methods {@link #jump} and {@link #leap} and {@link #jumps} and {@link #leaps} + * can be used to construct new instances of {@link Xoshiro256StarStar} that traverse + * other parts of the state cycle. + *

+ * Instances of {@link Xoshiro256StarStar} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. + * + * @since 14 + */ +public final class Xoshiro256StarStar implements LeapableGenerator { + + /* + * Implementation Overview. + * + * This is an implementation of the xoroshiro128** algorithm written + * in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org). + * See http://xoshiro.di.unimi.it and these two papers: + * + * Sebastiano Vigna. 2016. An Experimental Exploration of Marsaglia's + * xorshift Generators, Scrambled. ACM Transactions on Mathematical + * Software 42, 4, Article 30 (June 2016), 23 pages. + * https://doi.org/10.1145/2845077 + * + * David Blackman and Sebastiano Vigna. 2018. Scrambled Linear + * Pseudorandom Number Generators. Computing Research Repository (CoRR). + * http://arxiv.org/abs/1805.01407 + * + * The jump operation moves the current generator forward by 2*128 + * steps; this has the same effect as calling nextLong() 2**128 + * times, but is much faster. Similarly, the leap operation moves + * the current generator forward by 2*192 steps; this has the same + * effect as calling nextLong() 2**192 times, but is much faster. + * The copy method may be used to make a copy of the current + * generator. Thus one may repeatedly and cumulatively copy and + * jump to produce a sequence of generators whose states are well + * spaced apart along the overall state cycle (indeed, the jumps() + * and leaps() methods each produce a stream of such generators). + * The generators can then be parceled out to other threads. + * + * File organization: First static fields, then instance + * fields, then constructors, then instance methods. + */ + + /* ---------------- static fields ---------------- */ + + /** + * The seed generator for default constructors. + */ + private static final AtomicLong DEFAULT_GEN = new AtomicLong(RandomSupport.initialSeed()); + + /* + * The period of this generator, which is 2**256 - 1. + */ + private static final BigInteger PERIOD = + BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE); + + /* ---------------- instance fields ---------------- */ + + /** + * The per-instance state. + * At least one of the four fields x0, x1, x2, and x3 must be nonzero. + */ + private long x0, x1, x2, x3; + + /* ---------------- constructors ---------------- */ + + /** + * Basic constructor that initializes all fields from parameters. + * It then adjusts the field values if necessary to ensure that + * all constraints on the values of fields are met. + * + * @param x0 first word of the initial state + * @param x1 second word of the initial state + * @param x2 third word of the initial state + * @param x3 fourth word of the initial state + */ + public Xoshiro256StarStar(long x0, long x1, long x2, long x3) { + this.x0 = x0; + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + // If x0, x1, x2, and x3 are all zero, we must choose nonzero values. + if ((x0 | x1 | x2 | x3) == 0) { + // At least three of the four values generated here will be nonzero. + this.x0 = RandomSupport.mixStafford13(x0 += RandomSupport.GOLDEN_RATIO_64); + this.x1 = (x0 += RandomSupport.GOLDEN_RATIO_64); + this.x2 = (x0 += RandomSupport.GOLDEN_RATIO_64); + this.x3 = (x0 += RandomSupport.GOLDEN_RATIO_64); + } + } + + /** + * Creates a new instance of {@link Xoshiro256StarStar} using the + * specified {@code long} value as the initial seed. Instances of + * {@link Xoshiro256StarStar} created with the same seed in the same + * program generate identical sequences of values. + * + * @param seed the initial seed + */ + public Xoshiro256StarStar(long seed) { + // Using a value with irregularly spaced 1-bits to xor the seed + // argument tends to improve "pedestrian" seeds such as 0 or + // other small integers. We may as well use SILVER_RATIO_64. + // + // The x values are then filled in as if by a SplitMix PRNG with + // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer. + this(RandomSupport.mixStafford13(seed ^= RandomSupport.SILVER_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64), + RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link Xoshiro256StarStar} that is likely to + * generate sequences of values that are statistically independent + * of those of any other instances in the current program execution, + * but may, and typically does, vary across program invocations. + */ + public Xoshiro256StarStar() { + // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values. + this(DEFAULT_GEN.getAndAdd(RandomSupport.GOLDEN_RATIO_64)); + } + + /** + * Creates a new instance of {@link Xoshiro256StarStar} using the specified array of + * initial seed bytes. Instances of {@link Xoshiro256StarStar} created with the same + * seed array in the same program execution generate identical sequences of values. + * + * @param seed the initial seed + */ + public Xoshiro256StarStar(byte[] seed) { + // Convert the seed to 4 long values, which are not all zero. + long[] data = RandomSupport.convertSeedBytesToLongs(seed, 4, 4); + long x0 = data[0], x1 = data[1], x2 = data[2], x3 = data[3]; + this.x0 = x0; + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + } + + /* ---------------- public methods ---------------- */ + + public Xoshiro256StarStar copy() { + return new Xoshiro256StarStar(x0, x1, x2, x3); + } + + /** + * Returns a pseudorandom {@code long} value. + * + * @return a pseudorandom {@code long} value + */ + public long nextLong() { + // Compute the result based on current state information + // (this allows the computation to be overlapped with state update). + final long result = Long.rotateLeft(x0 * 5, 7) * 9; // "starstar" mixing function + + long q0 = x0, q1 = x1, q2 = x2, q3 = x3; + { // xoshiro256 1.0 + long t = q1 << 17; + q2 ^= q0; + q3 ^= q1; + q1 ^= q2; + q0 ^= q3; + q2 ^= t; + q3 = Long.rotateLeft(q3, 45); + } + x0 = q0; x1 = q1; x2 = q2; x3 = q3; + return result; + } + + public BigInteger period() { + return PERIOD; + } + + public double defaultJumpDistance() { + return 0x1.0p64; + } + + public double defaultLeapDistance() { + return 0x1.0p96; + } + + private static final long[] JUMP_TABLE = { + 0x180ec6d33cfd0abaL, 0xd5a61266f0c9392cL, 0xa9582618e03fc9aaL, 0x39abdc4529b1661cL }; + + private static final long[] LEAP_TABLE = { + 0x76e15d3efefdcbbfL, 0xc5004e441c522fb3L, 0x77710069854ee241L, 0x39109bb02acbe635L }; + + /** + * This is the jump function for the generator. It is equivalent to 2**128 calls to next(); it + * can be used to generate 2**128 non-overlapping subsequences for parallel computations. + */ + public void jump() { + jumpAlgorithm(JUMP_TABLE); + } + + /** + * This is the long-jump function for the generator. It is equivalent to 2**192 calls to next(); + * it can be used to generate 2**64 starting points, from each of which jump() will generate + * 2**64 non-overlapping subsequences for parallel distributed computations. + */ + public void leap() { + jumpAlgorithm(LEAP_TABLE); + } + + private void jumpAlgorithm(long[] table) { + long s0 = 0, s1 = 0, s2 = 0, s3 = 0; + for (int i = 0; i < table.length; i++) { + for (int b = 0; b < 64; b++) { + if ((table[i] & (1L << b)) != 0) { + s0 ^= x0; + s1 ^= x1; + s2 ^= x2; + s3 ^= x3; + } + nextLong(); + } + x0 = s0; + x1 = s1; + x2 = s2; + x3 = s3; + } + } + +} diff -r effb66aab08b -r da026c172c1e src/java.base/share/classes/java/util/random/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/package-info.java Thu Nov 14 12:50:08 2019 -0400 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /** + * Classes and interfaces that support the definition and use of "random generators", a term that + * is meant to cover what have traditionally been called "random number generators" as well as + * generators of other sorts of randomly chosen values, and also to cover not only deterministic + * (pseudorandom) algorithms but also generators of values that use some "truly random" physical + * source (perhaps making use of thermal noise, for example, or quantum-mechanical effects). + * + * The principal interface is {@link java.util.random.RandomGenerator}, which provides methods + * for requesting individual values of type {@code int}, {@code long}, {@code float}, {@code double}, or {@code boolean} + * chosen (pseudo)randomly from a uniform distribution; methods for requesting values of type {@code double} + * chosen (pseudo)randomly from a normal distribution or from an exponential distribution; + * and methods for creating streams of (pseudo)randomly chosen values of type {@code int}, {@code long}, or {@code double}. + * These streams are spliterator-based, allowing for parallel processing of their elements. + * + * An important subsidiary interface is {@link java.util.random.RandomGenerator.StreamableGenerator}, + * which provides methods for creating spliterator-based streams of {@code RandomGenerator} objects, + * allowing for allowing for parallel processing of these objects using multiple threads. + * Unlike {@link java.util.Random}, most implementations of {@code java.util.random.RandomGenerator} + * are not thread-safe. The intent is that instances should not be shared among threads; + * rather, each thread should have its own random generator(s) to use. The various pseudorandom algorithms + * provided by this package are designed so that multiple instances will (with very high probability) behave as + * if statistically independent. + * + * Historically, most pseudorandom generator algorithms have been based on some sort of + * finite-state machine with a single, large cycle of states; when it is necessary to have + * multiple threads use the same algorithm simultaneously, the usual technique is to arrange for + * each thread to traverse a different region of the state cycle. These regions may be doled out + * to threads by starting with a single initial state and then using a "jump function" that + * travels a long distance around the cycle (perhaps 264 steps or more); the jump function is applied repeatedly + * and sequentially, to identify widely spaced initial states for each thread's generator. This strategy is + * supported by the interface {@link java.util.random.RandomGenerator.JumpableGenerator}. + * Sometimes it is desirable to support two levels of jumping (by long distances and + * by really long distances); this strategy is supported by the interface + * {@link java.util.random.RandomGenerator.LeapableGenerator}. There is also an interface + * {@link java.util.random.RandomGenerator.ArbitrarilyJumpableGenerator} for algorithms that + * allow jumping along the state cycle by any user-specified distance. + * In this package, implementations of these interfaces include + * {@link java.util.random.Xoroshiro128PlusPlus}, + * {@link java.util.random.Xoroshiro128StarStar}, + * {@link java.util.random.Xoshiro256StarStar}, + * and {@link java.util.random.MRG32K3A}. + * + * A more recent category of "splittable" pseudorandom generator algorithms uses a large family + * of state cycles and makes some attempt to ensure that distinct instances use different state + * cycles; but even if two instances "accidentally" use the same state cycle, they are highly + * likely to traverse different regions parts of that shared state cycle. This strategy is + * supported by the interface {@link java.util.random.RandomGenerator.SplittableGenerator}. + * In this package, implementations of this interface include + * {@link java.util.random.L32X64MixRandom}, + * {@link java.util.random.L64X128MixRandom}, + * {@link java.util.random.L64X128PlusPlusRandom}, + * {@link java.util.random.L64X128StarStarMixRandom}, + * {@link java.util.random.L64X256MixRandom}, + * {@link java.util.random.L64X1024MixRandom}, + * {@link java.util.random.L128X128MixRandom}, + * {@link java.util.random.L128X128PlusPlusRandom}, + * {@link java.util.random.L128X128StarStarMixRandom}, + * {@link java.util.random.L128X256MixRandom}, + * {@link java.util.random.L128X1024MixRandom}, + * and {@link java.util.SplittableRandom}. + * Generally speaking, among the "{@code LmmmXnnn}" generators, the state size of the generator is + * {@code (mmm - 1 + nnn)} bits and the memory required for an instance is {@code (2 * mmm + nnn)} bits; + * larger values of "{@code mmm}" imply a lower probability that two instances will traverse the + * same state cycle; and larger values of "{@code nnn}" imply that the generator is equidistributed + * in a larger number of dimensions. A class with "{@code Mix}" in its name uses a strong mixing + * function with excellent avalanche characteristics; a class with "{@code StarStar}" or "{@code PlusPlus}" + * in its name uses a weaker but faster mixing function. See the documentation for individual classes + * for details about their specific characteristics. + * + * The class {@link java.util.random.RandomSupport} provides utility methods, constants, and + * abstract classes frequently useful in the implementation of pseudorandom number generators + * that satisfy the interface {@link RandomGenerator}. + * + * @since 14 + */ + + package java.util.random; + +