Passed
Push — main ( 15c446...595812 )
by Shubham
01:44
created

blas::dsymm()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
400
     */
401
    public static function scale(float $alpha, \Np\vector|\Np\matrix $v) {
402
        self::init();
403
        if ($v->dtype == \Np\vector::DOUBLE) {
404
            return self::$ffi_blas->cblas_dscal($v->ndim, $alpha, $v->data, 1);
405
        } else {
406
            return self::$ffi_blas->cblas_sscal($v->ndim, $alpha, $v->data, 1);
407
        }
408
    }
409
410
}
411