1+ /*
2+ * Copyright 2020-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+ */
4+
5+ package org.jetbrains.kotlinx.multik.api
6+
7+ import org.jetbrains.kotlinx.multik.ndarray.data.*
8+ import kotlin.jvm.JvmName
9+ import kotlin.random.Random
10+
11+ /* *
12+ * Returns a vector of the specified size filled with random numbers uniformly distributed for:
13+ * Int - [Int.MIN_VALUE, Int.MAX_VALUE)
14+ * Long - [Long.MIN_VALUE, Long.MAX_VALUE)
15+ * Float - [0f, 1f)
16+ * Double - [0.0, 1.0)
17+ */
18+ public inline fun <reified T : Number > Multik.rand (dim0 : Int ): D1Array <T > {
19+ require(dim0 > 0 ) { " Dimension must be positive." }
20+ val dtype = DataType .ofKClass(T ::class )
21+ val frand: () -> T = fRand(dtype)
22+ val data = initMemoryView(dim0, dtype) { frand() }
23+ return D1Array (data, shape = intArrayOf(dim0), dim = D1 )
24+ }
25+
26+ /* *
27+ * Returns a matrix of the specified shape filled with random numbers uniformly distributed for:
28+ * Int - [Int.MIN_VALUE, Int.MAX_VALUE)
29+ * Long - [Long.MIN_VALUE, Long.MAX_VALUE)
30+ * Float - [0f, 1f)
31+ * Double - [0.0, 1.0)
32+ */
33+ public inline fun <reified T : Number > Multik.rand (dim0 : Int , dim1 : Int ): D2Array <T > {
34+ val dtype = DataType .ofKClass(T ::class )
35+ val shape = intArrayOf(dim0, dim1)
36+ for (i in shape.indices) {
37+ require(shape[i] > 0 ) { " Dimension $i must be positive." }
38+ }
39+ val frand: () -> T = fRand(dtype)
40+ val data = initMemoryView(dim0 * dim1, dtype) { frand() }
41+ return D2Array (data, shape = shape, dim = D2 )
42+ }
43+
44+ /* *
45+ * Returns an NDArray of the specified shape filled with random numbers uniformly distributed for:
46+ * Int - [Int.MIN_VALUE, Int.MAX_VALUE)
47+ * Long - [Long.MIN_VALUE, Long.MAX_VALUE)
48+ * Float - [0f, 1f)
49+ * Double - [0.0, 1.0)
50+ */
51+ public inline fun <reified T : Number > Multik.rand (dim0 : Int , dim1 : Int , dim2 : Int ): D3Array <T > {
52+ val dtype = DataType .ofKClass(T ::class )
53+ val shape = intArrayOf(dim0, dim1, dim2)
54+ for (i in shape.indices) {
55+ require(shape[i] > 0 ) { " Dimension $i must be positive." }
56+ }
57+ val frand: () -> T = fRand(dtype)
58+ val data = initMemoryView(dim0 * dim1 * dim2, dtype) { frand() }
59+ return D3Array (data, shape = shape, dim = D3 )
60+ }
61+
62+ /* *
63+ * Returns an NDArray of the specified shape filled with random numbers uniformly distributed for:
64+ * Int - [Int.MIN_VALUE, Int.MAX_VALUE)
65+ * Long - [Long.MIN_VALUE, Long.MAX_VALUE)
66+ * Float - [0f, 1f)
67+ * Double - [0.0, 1.0)
68+ */
69+ public inline fun <reified T : Number > Multik.rand (dim0 : Int , dim1 : Int , dim2 : Int , dim3 : Int ): D4Array <T > {
70+ val dtype = DataType .ofKClass(T ::class )
71+ val shape = intArrayOf(dim0, dim1, dim2, dim3)
72+ for (i in shape.indices) {
73+ require(shape[i] > 0 ) { " Dimension $i must be positive." }
74+ }
75+ val frand: () -> T = fRand(dtype)
76+ val data = initMemoryView(dim0 * dim1 * dim2 * dim3, dtype) { frand() }
77+ return D4Array (data, shape = shape, dim = D4 )
78+ }
79+
80+ /* *
81+ * Returns an NDArray of the specified shape filled with random numbers uniformly distributed for:
82+ * Int - [Int.MIN_VALUE, Int.MAX_VALUE)
83+ * Long - [Long.MIN_VALUE, Long.MAX_VALUE)
84+ * Float - [0f, 1f)
85+ * Double - [0.0, 1.0)
86+ */
87+ public inline fun <reified T : Number > Multik.rand (
88+ dim0 : Int , dim1 : Int , dim2 : Int , dim3 : Int , vararg dims : Int
89+ ): NDArray <T , DN > {
90+ return rand(intArrayOf(dim0, dim1, dim2, dim3, * dims))
91+ }
92+
93+ /* *
94+ * Returns an NDArray of the specified shape filled with random numbers uniformly distributed for:
95+ * Int - [Int.MIN_VALUE, Int.MAX_VALUE)
96+ * Long - [Long.MIN_VALUE, Long.MAX_VALUE)
97+ * Float - [0f, 1f)
98+ * Double - [0.0, 1.0)
99+ */
100+ public inline fun <reified T : Number , reified D : Dimension > Multik.rand (shape : IntArray ): NDArray <T , D > {
101+ val dtype = DataType .ofKClass(T ::class )
102+ val dim = dimensionClassOf<D >(shape.size)
103+ requireDimension(dim, shape.size)
104+ for (i in shape.indices) {
105+ require(shape[i] > 0 ) { " Dimension $i must be positive." }
106+ }
107+ val size = shape.fold(1 , Int ::times)
108+ val frand: () -> T = fRand(dtype)
109+ val data = initMemoryView(size, dtype) { frand() }
110+ return NDArray (data, shape = shape, dim = dim)
111+ }
112+
113+
114+ /* *
115+ * Returns an NDArray of the specified shape filled with number uniformly distributed between [[from], [until])
116+ */
117+ @JvmName(" randWithVarArg" )
118+ public inline fun <reified T : Number , reified D : Dimension > Multik.rand (
119+ from : T , until : T , vararg dims : Int
120+ ): NDArray <T , D > =
121+ Multik .rand(from, until, dims)
122+
123+ /* *
124+ * Returns an NDArray of the specified shape filled with number uniformly distributed between [[from], [until])
125+ *
126+ * Note: Float generation is inefficient.
127+ */
128+ @JvmName(" randWithShape" )
129+ public inline fun <reified T : Number , reified D : Dimension > Multik.rand (
130+ from : T , until : T , dims : IntArray
131+ ): NDArray <T , D > {
132+ val dtype = DataType .ofKClass(T ::class )
133+ val dim = dimensionClassOf<D >(dims.size)
134+ requireDimension(dim, dims.size)
135+ for (i in dims.indices) {
136+ require(dims[i] > 0 ) { " Dimension $i must be positive." }
137+ }
138+ val size = dims.fold(1 , Int ::times)
139+ val data = randData(from, until, size, dtype)
140+ return NDArray (data, shape = dims, dim = dim)
141+ }
142+
143+ /* *
144+ * Returns an NDArray of the specified shape filled with number uniformly distributed between [[from], [until])
145+ * with the specified [seed].
146+ *
147+ * Note: Float generation is inefficient.
148+ */
149+ @JvmName(" randSeedVarArg" )
150+ public inline fun <reified T : Number , reified D : Dimension > Multik.rand (
151+ seed : Int , from : T , until : T , vararg dims : Int
152+ ): NDArray <T , D > = Multik .rand(Random (seed), from, until, dims)
153+
154+ /* *
155+ * Returns an NDArray of the specified shape filled with number uniformly distributed between [[from], [until])
156+ * with the specified [seed].
157+ *
158+ * Note: Float generation is inefficient.
159+ */
160+ @JvmName(" randSeedShape" )
161+ public inline fun <reified T : Number , reified D : Dimension > Multik.rand (
162+ seed : Int , from : T , until : T , dims : IntArray
163+ ): NDArray <T , D > = Multik .rand(Random (seed), from, until, dims)
164+
165+ /* *
166+ * Returns an NDArray of the specified shape filled with number uniformly distributed between [[from], [until])
167+ * with the specified [gen].
168+ *
169+ * Note: Float generation is inefficient.
170+ */
171+ @JvmName(" randGenVarArg" )
172+ public inline fun <reified T : Number , reified D : Dimension > Multik.rand (
173+ gen : Random , from : T , until : T , vararg dims : Int
174+ ): NDArray <T , D > = Multik .rand(gen, from, until, dims)
175+
176+ /* *
177+ * Returns an NDArray of the specified shape filled with number uniformly distributed between [[from], [until])
178+ * with the specified [gen].
179+ *
180+ * Note: Float generation is inefficient.
181+ */
182+ @JvmName(" randGenShape" )
183+ public inline fun <reified T : Number , reified D : Dimension > Multik.rand (
184+ gen : Random , from : T , until : T , dims : IntArray
185+ ): NDArray <T , D > {
186+ val dtype = DataType .ofKClass(T ::class )
187+ val dim = dimensionClassOf<D >(dims.size)
188+ requireDimension(dim, dims.size)
189+ for (i in dims.indices) {
190+ require(dims[i] > 0 ) { " Dimension $i must be positive." }
191+ }
192+ val size = dims.fold(1 , Int ::times)
193+ val data = randData(from, until, size, dtype, gen)
194+ return NDArray (data, shape = dims, dim = dim)
195+ }
196+
197+ @PublishedApi
198+ @Suppress(" UNCHECKED_CAST" )
199+ internal inline fun <T : Number > fRand (dtype : DataType ): () -> T {
200+ return when (dtype) {
201+ DataType .IntDataType -> { { Random .nextInt() } }
202+ DataType .LongDataType -> { { Random .nextLong() } }
203+ DataType .FloatDataType -> { { Random .nextFloat() } }
204+ DataType .DoubleDataType -> { { Random .nextDouble() } }
205+ else -> throw UnsupportedOperationException (" Other types are not currently supported" )
206+ } as () -> T
207+ }
208+
209+ @PublishedApi
210+ @Suppress(" UNCHECKED_CAST" )
211+ internal inline fun <T : Number > randData (
212+ from : T , until : T , size : Int , dtype : DataType , gen : Random ? = null
213+ ): MemoryView <T > {
214+ var f = 0.0
215+ var u = 0.0
216+ val random = gen ? : Random .Default
217+ if (from is Float && until is Float ) {
218+ f = from.toDouble()
219+ u = until.toDouble()
220+ }
221+ return when {
222+ from is Int && until is Int -> initMemoryView(size, dtype) { random.nextInt(from, until) }
223+ from is Long && until is Long -> initMemoryView(size, dtype) { random.nextLong(from, until) }
224+ from is Float && until is Float -> initMemoryView(size, dtype) { random.nextDouble(f, u).toFloat() }
225+ from is Double && until is Double -> initMemoryView(size, dtype) { random.nextDouble(from, until) }
226+ else -> throw UnsupportedOperationException ()
227+ } as MemoryView <T >
228+ }
0 commit comments