Passed
Push — main ( b63ebb...d6f51d )
by Shubham
02:04
created

blas   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 308
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 69
dl 0
loc 308
rs 10
c 1
b 0
f 0
wmc 26

25 Methods

Rating   Name   Duplication   Size   Complexity  
A getCoreName() 0 3 1
A getConfig() 0 3 1
A setNumThreads() 0 3 1
A init() 0 5 2
A getNumThreads() 0 3 1
A getNumPorcs() 0 3 1
A getNumParallel() 0 3 1
A min() 0 3 1
A copy() 0 4 1
A rotg() 0 3 1
A asum() 0 3 1
A rotate() 0 3 1
A scale() 0 3 1
A gemm() 0 3 1
A nrm2() 0 3 1
A dot() 0 3 1
A max() 0 3 1
A symm() 0 4 1
A syr2k() 0 4 1
A syrk() 0 4 1
A axpy() 0 4 1
A swap() 0 3 1
A gbmv() 0 7 1
A ger() 0 4 1
A gemv() 0 4 1
1
<?php
2
3
namespace Np\core;
4
5
/**
6
 * OpenBlas
7
 * 
8
 * php interface for OpenBLAS
9
 * 
10
 * @package Np
11
 * @category Scientific Computing
12
 * @author ghost (Shubham Chaudhary)
13
 * @email [email protected]
14
 * @copyright (c) 2020-2021, Shubham Chaudhary
15
 */
16
class blas {
17
18
    const CblasLeft = 141, CblasRight = 142;
19
    const CblasUpper = 121, CblasLower = 122;
20
    const CblasNonUnit = 131, CblasUnit = 132;
21
    const CblasRowMajor = 101, CblasColMajor = 102;
22
    const CblasNoTrans = 111, CblasTrans = 112, CblasConjTrans = 113;
23
24
    public static $ffi_blas = null;
25
26
    public static function init() {
27
        if (is_null(self::$ffi_blas)) {
28
            self::$ffi_blas = \FFI::scope('blas');
29
        }
30
        return self::$ffi_blas;
31
    }
32
33
    public static function setNumThreads(int $num_threads) {
34
        self::init();
35
        self::$ffi_blas->openblas_set_num_threads($num_threads);
36
    }
37
38
    public static function getNumThreads(): int {
39
        self::init();
40
        return self::$ffi_blas->openblas_get_num_threads();
41
    }
42
43
    public static function getNumPorcs(): int {
44
        self::init();
45
        return self::$ffi_blas->openblas_get_num_procs();
46
    }
47
48
    public static function getConfig() {
49
        self::init();
50
        return self::$ffi_blas->openblas_get_config();
51
    }
52
53
    public static function getCoreName() {
54
        self::init();
55
        return self::$ffi_blas->openblas_get_corename();
56
    }
57
58
    public static function getNumParallel(): int {
59
        self::init();
60
        return self::$ffi_blas->openblas_get_parallel();
61
    }
62
63
    /**
64
     * Product of general matrix and general matrix
65
     *    C := alpha * AB + beta * C
66
     * @dtype Float
67
     * @param \Np\matrix $m1
68
     * @param \Np\matrix $m2
69
     * @param \Np\matrix $mr
70
     * @return \FFI\CData
71
     */
72
    public static function gemm(\Np\matrix $m1, \Np\matrix $m2, \Np\matrix $mr, int $trans1 = self::CblasNoTrans, int $trans2 = self::CblasNoTrans) {
73
        self::init();
74
        return self::$ffi_blas->cblas_dgemm(self::CblasRowMajor, $trans1, $trans2, $m1->row, $m2->col, $m1->col, 1.0, $m1->data, $m1->col, $m2->data, $m2->col, 0.0, $mr->data, $mr->col);
75
    }
76
77
    /**
78
     *  Product of symmetric matrix and general matrix
79
     *    C := alpha * AB + beta * C
80
     *            or
81
     *    C := alpha * BA + beta * C
82
     * 
83
     * @param \Np\matrix $m1
84
     * @param \Np\matrix $m2
85
     * @param \Np\matrix $mr
86
     */
87
    public static function symm(\Np\matrix $m1, \Np\matrix $m2, \Np\matrix $mr) {
88
        self::init();
89
        return self::$ffi_blas->cblas_dsymm(self::CblasRowMajor, self::CblasLeft, self::CblasUpper, $m1->row,
90
                        $m2->col, 1.0, $m1->data, $m1->row, $m2->data, $m2->row, 0.0, $mr->data, $mr->row);
91
    }
92
93
    /**
94
     * Update rank n of symmetric matrix
95
     *    C := alpha * A A^T + beta * C
96
     *            or
97
     *    C := alpha * A^T A + beta * C
98
     * 
99
     * @param \Np\matrix $m1
100
     * @param \Np\matrix $m2
101
     */
102
    public static function syrk(\Np\matrix $m1, \Np\matrix $m2) {
103
        self::init();
104
        return self::$ffi_blas->cblas_dsyrk(self::CblasRowMajor, self::CblasUpper,
105
                        self::CblasNoTrans, $m1->row, $m2->col, 1.0, $m1->data, $m1->row, 0.0, $m2->data, $m2->row);
106
    }
107
108
    /**
109
     * Update rank 2k of symmetric matrix
110
     *    C := alpha * A B^T + alpha B A^T + beta * C
111
     *            or
112
     *    C := alpha * B^T A + alpha A^T B + beta * C
113
     * 
114
     * @param \Np\matrix $m1
115
     * @param \Np\matrix $m2
116
     * @param \Np\matrix $mr
117
     */
118
    public static function syr2k(\Np\matrix $m1, \Np\matrix $m2, \Np\matrix $mr) {
119
        self::init();
120
        return self::$ffi_blas->cblas_dsyr2k(self::CblasRowMajor, self::CblasLower, self::CblasNoTrans,
121
                        $m1->col, $m2->row, 1.0, $m1->data, $m1->row, $m2->data, $m2->row, 0.0, $mr->data, $mr->row);
122
    }
123
124
    /**
125
     * @static
126
     * @dtype Double
127
     * @param \Np\matrix $m
128
     * @param \Np\vector $v
129
     * @param \Np\vector $mvr
130
     * @return \FFI\CData
131
     */
132
    public static function gemv(\Np\matrix $m, \Np\vector $v, \Np\vector $mvr) {
133
        self::init();
134
        return self::$ffi_blas->cblas_dgemv(self::CblasRowMajor, self::CblasNoTrans, $m->row, $m->col,
135
                        1.0, $m->data, $m->row, $v->data, 1, 1.0, $mvr->data, 1);
136
    }
137
138
    /**
139
     * Compute the product of a general matrix and a vector stored in band format.
140
     *    y := alpha * Ax + beta * y
141
     * @param int $KL   Number of elements in the lower left part
142
     * @param int $KU   Number of elements in the upper right part
143
     * @param double $alpha  Coefficient of scalar multiple of vector
144
     * @param double $beta   Coefficient of scalar multiple of  mvr
145
     * @param \Np\matrix $matrix
146
     * @param \Np\vector $vector
147
     * @param \Np\vector $mvr
148
     */
149
    public static function gbmv(int $KL, int $KU, float $alpha, float $beta, \Np\matrix $matrix, \Np\vector $vector, \Np\vector $mvr) {
150
        self::init();
151
        return self::$ffi_blas->cblas_dgbmv(self::CblasRowMajor,
152
                        self::CblasNoTrans, $matrix->row, $matrix->col,
153
                        $KL, $KU, $alpha,
154
                        $matrix->data, $matrix->row, $vector->data,
155
                        1, $beta, $mvr->data, 1);
156
    }
157
158
    /**
159
     * Compute the product of a column vector and a row vector. (Real number)
160
     *    A := alpha * x y^t + A
161
     * @param \Np\vector $v1
162
     * @param \Np\vector $v2
163
     * @param \Np\matrix $m
164
     * @return void
165
     */
166
    public static function ger(\Np\vector $v1, \Np\vector $v2, \Np\matrix $m) {
167
        self::init();
168
        return self::$ffi_blas->cblas_dger(self::CblasRowMajor, $v1->col, $v2->col,
169
                        1.0, $v1->data, 1, $v2->data, 1, $m->data, $m->row);
170
    }
171
172
    /**
173
     * @static
174
     * @dtype Double
175
     * @param \Np\vector $v1
176
     * @param \Np\vector $v2
177
     */
178
    public static function dot(\Np\vector $v1, \Np\vector $v2) {
179
        self::init();
180
        return self::$ffi_blas->cblas_ddot($v1->col, $v1->data, 1, $v2->data, 1);
181
    }
182
183
    /**
184
     * Calculates the index of the element with the largest absolute value in the vector.
185
     *  Note that this subscript starts from 1. If 0 is returned, n is invalid.
186
     *    ret := arg max |X(i)|
187
     *
188
     *  @param \Np\vector $v
189
     * @return int index of the element(Note that start from 0 according to cblas)
190
     */
191
    public static function max(\Np\vector $v) {
192
        self::init();
193
        return self::$ffi_blas->cblas_idamax($v->col, $v->data, 1);
194
    }
195
196
    /**
197
     *  Calculates the index of the element with the smallest absolute value in the vector.
198
     *  Note that this subscript starts from 1. If 0 is returned, n is invalid.
199
     *   ret := arg min |X(i)|
200
     * 
201
     * @param \Np\vector $v
202
     * @return int
203
     */
204
    public static function min(\Np\vector $v) {
205
        self::init();
206
        return self::$ffi_blas->cblas_idamin($v->col, $v->data, 1);
207
    }
208
209
    /**
210
     * Exchange the contents of the vector.
211
     *    X := Y
212
     *    Y := X
213
     * @param \Np\vector $v1
214
     * @param \Np\vector $v2
215
     * @param int $inv1
216
     * @param int $inv2
217
     */
218
    public static function swap(\Np\vector $v1, \Np\vector $v2, int $inv1 = 1, int $inv2 = 1) {
219
        self::init();
220
        return self::$ffi_blas->cblas_dswap($v1->col, $v1->data, $inv1, $v2->data, $inv2);
221
    }
222
223
    /**
224
     *  Copy the vector from X to Y.
225
     *    Y := X
226
     *  @param \Np\vector $vect_X        Vector X buffer
227
     *  @param \Np\vector $vect_Y        Vector Y buffer
228
     *  @param int $invX
229
     *  @param int $invY 
230
     *  @return void
231
     */
232
    public static function copy(\Np\vector $vect_X, \Np\vector $vect_Y, int $invX = 1, int $invY = 1) {
233
        self::init();
234
        return self::$ffi_blas->cblas_dcopy($vect_X->col, $vect_X->data, $invX,
235
                        $vect_Y->data, $invY);
236
    }
237
238
    /**
239
     * Compute the Euclidean norm of a vector.
240
     *    ret := ||X||
241
     * @param \Np\vector $v
242
     * @return float
243
     */
244
    public static function nrm2(\Np\vector $v): float {
245
        self::init();
246
        return self::$ffi_blas->cblas_dnrme($v->col, $v->data, 1);
247
    }
248
249
    /**
250
     *  Add vectors
251
     *    Y := alpha * X + Y
252
     *  @param float $alpha     Coefficient of scalar multiple of X vector
253
     *  @param \Np\vector $vect_X        Vector X buffer
254
     *  @param \Np\vector $vect_Y        Vector Y buffer
255
     *  @return void
256
     */
257
    public static function axpy(float $alpha, \Np\vector $vect_X, \Np\vector $vect_Y) {
258
        self::init();
259
        return self::$ffi_blas->cblas_daxpy($vect_X->col, $alpha, $vect_X->data,
260
                        1, $vect_Y->data, 1);
261
    }
262
263
    /**
264
     *  Calculates the sum of the absolute values of each component of the vector.
265
     *    ret := |x_1| + ... + |x_n|
266
     *  @param \Np\vector $v        Vector X buffer
267
     *  @return float
268
     */
269
    public static function asum(\Np\vector $v): float {
270
        self::init();
271
        return self::$ffi_blas->cblas_dasum($v->col, $v->data, 1);
272
    }
273
274
    /**
275
     * Rotate about a given point.
276
     *    X(i) := c * X(i) + s * Y(i)
277
     *    Y(i) :=-s * X(i) + c * Y(i)
278
     * @param \Np\vector $v1 Vector X buffer
279
     * @param \Np\vector $v2 Vector Y buffer
280
     * @param float $c         value of cos A(Value obtained with rotg function.)
281
     * @param float $s         value of sin A(Value obtained with rotg function.)
282
     * 
283
     */
284
    public static function rotate(\Np\vector $v1, \Np\vector $v2, float $c, float $s) {
285
        self::init();
286
        return self::$ffi_blas->cblas_drot($v1->col, $v1->data, 1, $v2->data, 1, $c, $s);
287
    }
288
289
    /**
290
     *  Give the point P (a, b).
291
     *  Rotate this point to givens and calculate the parameters a, b, c,
292
     *  and s to make the y coordinate zero.
293
     *    Conditions description:
294
     *       c * a + s * b = r
295
     *       -s * a + c * b = 0
296
     *       r = ||(a,b)||
297
     *       c^2 + s^2 = 1
298
     *       z=s if |a| > |b|
299
     *       z=1/c if |a| <= |b| and c != 0 and r != 0
300
     *    Find r, z, c, s that satisfies the above description.
301
     *    However, when r = 0, z = 0, c = 1, and s = 0 are returned.
302
     *    Also, if c = 0, | a | <= | b | and c! = 0 and r! = 0, z = 1 is returned.
303
     *  @param float $a     X-coordinate of P: The calculated r value is stored and returned
304
     *  @param float $b     Y-coordinate of P: The calculated z value is stored and returned
305
     *  @param float $c     Stores the calculated value of c
306
     *  @param float $s     Stores the calculated value of s
307
     *  @return void
308
     */
309
    public static function rotg(float $a, float $b, float $c, float $s) {
310
        self::init();
311
        return self::$ffi_blas->cblas_drotg($a, $b, $c, $s);
312
    }
313
314
    /**
315
     * Multiply vector by scalar.
316
     *
317
     * @param float $alpha Coefficient of scalar multiple of V vector
318
     * @param \Np\vector|\Np\matrix $v
319
     * @return \FFI\CData
320
     */
321
    public static function scale(float $alpha, \Np\vector|\Np\matrix $v) {
322
        self::init();
323
        return self::$ffi_blas->cblas_dscal($v->ndim, $alpha, $v->data, 1);
324
    }
325
326
}
327