11/**
22 * XOR128 js implementation
3- * @version 1.0 .0
3+ * @version 1.1 .0
44 * @author Lorenzo Rossi - https://www.lorenzoros.si - https://github.com/lorossi/
55 * @license MIT
66 */
@@ -12,17 +12,47 @@ class XOR128 {
1212 * All parameters are optional, if nothing is passed a random value from
1313 * js functions Math.random() will be used
1414 *
15- * @param {number } [x] first seed
15+ * @param {number|Array } [x] first seed or array of seeds. \
16+ * If an array is passed, the first 4 elements will be used as seeds
1617 * @param {number } [y] second seed
1718 * @param {number } [z] third seed
1819 * @param {number } [w] fourth seed
1920 * @returns {XOR128 }
2021 */
2122 constructor ( x = null , y = null , z = null , w = null ) {
22- if ( x == null || x == undefined ) x = Math . floor ( Math . random ( ) * 4294967296 ) ;
23- if ( y == null || x == undefined ) y = Math . floor ( Math . random ( ) * 4294967296 ) ;
24- if ( z == null || x == undefined ) z = Math . floor ( Math . random ( ) * 4294967296 ) ;
25- if ( w == null || x == undefined ) w = Math . floor ( Math . random ( ) * 4294967296 ) ;
23+ if ( x instanceof Array ) {
24+ if ( x . length > 4 ) throw new Error ( "XOR128: too many seeds" ) ;
25+
26+ for ( let i = x . length ; i < 4 ; i ++ ) x . push ( x [ i - 1 ] + 1 ) ;
27+
28+ return new XOR128 ( x [ 0 ] , x [ 1 ] , x [ 2 ] , x [ 3 ] ) ;
29+ }
30+
31+ if ( x == null ) x = Math . floor ( Math . random ( ) * 4294967296 ) ;
32+
33+ if ( y == null ) {
34+ if ( x != null ) {
35+ y = x + 1 ;
36+ } else {
37+ y = Math . floor ( Math . random ( ) * 4294967296 ) ;
38+ }
39+ }
40+
41+ if ( z == null ) {
42+ if ( y != null ) {
43+ z = y + 1 ;
44+ } else {
45+ z = Math . floor ( Math . random ( ) * 4294967296 ) ;
46+ }
47+ }
48+
49+ if ( w == null ) {
50+ if ( z != null ) {
51+ w = z + 1 ;
52+ } else {
53+ w = Math . floor ( Math . random ( ) * 4294967296 ) ;
54+ }
55+ }
2656
2757 if (
2858 typeof x !== "number" ||
@@ -35,6 +65,8 @@ class XOR128 {
3565 if ( x < 1 || y < 1 || z < 1 || w < 1 )
3666 throw new Error ( "XOR128: seed values must be greater than 0" ) ;
3767
68+ if ( arguments . length > 4 ) throw new Error ( "XOR128: too many arguments" ) ;
69+
3870 this . _x = x ;
3971 this . _y = y ;
4072 this . _z = z ;
@@ -59,6 +91,12 @@ class XOR128 {
5991 a = 0 ;
6092 }
6193
94+ if ( a > b )
95+ throw new Error ( "XOR128: first parameter must be smaller than second" ) ;
96+
97+ if ( ! ( typeof a === "number" && typeof b === "number" ) )
98+ throw new Error ( "XOR128: parameters must be numbers" ) ;
99+
62100 const t = this . _x ^ ( ( this . _x << 11 ) >>> 0 ) ;
63101
64102 this . _x = this . _y ;
@@ -87,7 +125,34 @@ class XOR128 {
87125 a = 0 ;
88126 }
89127
90- return Math . floor ( this . random ( a , b + 1 ) ) ;
128+ return Math . floor ( this . random ( a , b ) ) ;
129+ }
130+
131+ /**
132+ * Returns a random boolean
133+ *
134+ * @returns {Boolean } random boolean
135+ */
136+ random_bool ( ) {
137+ return this . random ( ) > 0.5 ;
138+ }
139+
140+ /**
141+ * Returns a random string
142+ *
143+ * @param {number } [length=10] length of the string
144+ * @param {string } [chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"] characters to use
145+ */
146+ random_string (
147+ length = 10 ,
148+ chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
149+ ) {
150+ let str = "" ;
151+
152+ for ( let i = 0 ; i < length ; i ++ )
153+ str += chars [ this . random_int ( 0 , chars . length ) ] ;
154+
155+ return str ;
91156 }
92157
93158 /**
@@ -110,16 +175,43 @@ class XOR128 {
110175 * @returns {any } item from input array
111176 */
112177 random_from_array ( arr ) {
178+ if ( ! ( arr instanceof Array ) )
179+ throw new Error ( "XOR128: parameter must be an array" ) ;
180+
113181 return arr [ this . random_int ( 0 , arr . length ) ] ;
114182 }
115183
116184 /**
117- * Shuffles the provided array without returning it (the original array gets shuffled)
185+ * Returns a random char from the provided string
186+ *
187+ * @param {string } str a string
188+ * @returns {string } char from input string
189+ */
190+ random_from_string ( str ) {
191+ if ( typeof str !== "string" )
192+ throw new Error ( "XOR128: parameter must be a string" ) ;
193+
194+ return str . charAt ( this . random_int ( 0 , str . length ) ) ;
195+ }
196+
197+ /**
198+ * Returns a random item from the provided array or a random char from the provided string
199+ *
200+ * @returns {any } item from input array or char from input string
201+ */
202+ pick ( x ) {
203+ if ( x instanceof Array ) return this . random_from_array ( x ) ;
204+ else if ( typeof x === "string" ) return this . random_from_string ( x ) ;
205+ else throw new Error ( "XOR128: parameter must be an array or a string" ) ;
206+ }
207+
208+ /**
209+ * Shuffles the provided array (the original array does not get shuffled)
118210 *
119211 * @param {Array } arr an array
120212 */
121213 shuffle_array ( arr ) {
122- return arr
214+ return [ ... arr ]
123215 . map ( ( s ) => ( { sort : this . random ( ) , value : s } ) )
124216 . sort ( ( a , b ) => a . sort - b . sort )
125217 . map ( ( a ) => a . value ) ;
@@ -139,4 +231,17 @@ class XOR128 {
139231 . map ( ( a ) => a . value )
140232 . join ( "" ) ;
141233 }
234+
235+ /**
236+ * Shuffles and returns an array or a string.
237+ *
238+ * @param {Array|String } x an array or a string
239+ * @returns {any } shuffled array or string
240+ */
241+ shuffle ( x ) {
242+ if ( x instanceof Array ) return this . shuffle_array ( x ) ;
243+ if ( typeof x === "string" ) return this . shuffle_string ( x ) ;
244+
245+ throw new Error ( "XOR128: parameter must be an array or a string" ) ;
246+ }
142247}
0 commit comments