Passed
Push — main ( 595812...39c26d )
by Shubham
01:50
created

vector::argMx()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Np;
6
7
use Np\core\{
8
    nd,
9
    blas,
10
    lapack
11
};
12
use Np\exceptions\{
13
    invalidArgumentException,
14
    dimensionalityMismatch,
15
    dtypeException,
16
};
17
18
/** A fast lite memory efficient Scientific Computing in php
19
 * Vector (rank-1)
20
 * 
21
 * @package NumPhp
22
 * @version V0.0.alpha
23
 * @category Php Scientific Library
24
 * @author ghost (Shubham Chaudhary)
25
 * @email [email protected]
26
 * @copyright (c) 2020-2021, Shubham Chaudhary
27
 * 
28
 */
29
class vector extends nd {
30
31
    /**
32
     * Factory method to build a new vector.
33
     * 
34
     * @param int $col
35
     * @param int $dtype
36
     * @return vector
37
     */
38
    public static function factory(int $col, int $dtype = self::FLOAT): vector {
39
        return new self($col, $dtype);
40
    }
41
42
    /**
43
     * Build a new vector from a php array.
44
     * 
45
     * @param array $data
46
     * @param int $dtype
47
     * @return vector
48
     */
49
    public static function ar(array $data, int $dtype = self::FLOAT): vector {
50
        if (is_array($data) && !is_array($data[0])) {
51
            $ar = self::factory(count($data), $dtype);
52
            $ar->setData($data);
53
            return $ar;
54
        } else {
55
            self::_err('data must be of same dimensions');
1 ignored issue
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Np\vector. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
56
        }
57
    }
58
59
    /**
60
     * Return vector with random values
61
     * @param int $col
62
     * @param int $dtype
63
     * @return vector
64
     */
65
    public static function randn(int $col, int $dtype = self::FLOAT): vector {
66
        $ar = self::factory($col, $dtype);
67
        $max = getrandmax();
68
        for ($i = 0; $i < $ar->col; ++$i) {
69
            $ar->data[$i] = rand() / $max;
70
        }
71
        return $ar;
72
    }
73
74
    /**
75
     * Return vector with uniform values
76
     * @param int $col
77
     * @param int $dtype
78
     * @return vector
79
     */
80
    public static function uniform(int $col, int $dtype = self::FLOAT): vector {
81
        $ar = self::factory($col, $dtype);
82
        $max = getrandmax();
83
        for ($i = 0; $i < $col; ++$i) {
84
            $ar->data[$i] = rand(-$max, $max) / $max;
85
        }
86
        return $ar;
87
    }
88
89
    /**
90
     * Build a vector of zeros with n elements.
91
     * 
92
     * @param int $col
93
     * @param int $dtype
94
     * @return vector
95
     */
96
    public static function zeros(int $col, int $dtype = self::FLOAT): vector {
97
        $ar = self::factory($col, $dtype);
98
        for ($i = 0; $i < $col; ++$i) {
99
            $ar->data[$i] = 0;
100
        }
101
        return $ar;
102
    }
103
104
    /**
105
     * create one like vector
106
     * 
107
     * @param int $col
108
     * @return vector
109
     */
110
    public static function ones(int $col, int $dtype = self::FLOAT): vector {
111
        $ar = self::factory($col, $dtype);
112
        for ($i = 0; $i < $col; ++$i) {
113
            $ar->data[$i] = 1;
114
        }
115
        return $ar;
116
    }
117
118
    /**
119
     * create a null like vector
120
     * @param int $col
121
     * @return vector
122
     */
123
    public static function null(int $col, int $dtype = self::FLOAT): vector {
124
        $ar = self::factory($col, $dtype);
125
        for ($i = 0; $i < $col; ++$i) {
126
            $ar->data[$i] = null;
127
        }
128
        return $ar;
129
    }
130
131
    /**
132
     * create a vector with given scalar value
133
     * @param int $col
134
     * @param int|float|double $val
135
     * @param int $dtype
136
     * @return vector
137
     */
138
    public static function full(int $col, int|float $val, int $dtype = self::FLOAT): vector {
139
        $ar = self::factory($col, $dtype);
140
        for ($i = 0; $i < $col; ++$i) {
141
            $ar->data[$i] = $val;
142
        }
143
        return $ar;
144
    }
145
146
    /**
147
     * Return evenly spaced values within a given interval.
148
     *
149
     * @param int|float $start
150
     * @param int|float $end
151
     * @param int|float $interval
152
     * @param int $dtype 
153
     * @return vector
154
     */
155
    public static function range(int|float $start, int|float $end, int|float $interval = 1, int $dtype = self::FLOAT): vector {
0 ignored issues
show
Unused Code introduced by
The parameter $dtype is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

155
    public static function range(int|float $start, int|float $end, int|float $interval = 1, /** @scrutinizer ignore-unused */ int $dtype = self::FLOAT): vector {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
156
        return self::ar(range($start, $end, $interval));
157
    }
158
159
    /**
160
     * Return a Gaussian random vector with mean 0
161
     * and unit variance.
162
     *
163
     * @param int $n
164
     * @param int $dtype
165
     * @return self
166
     */
167
    public static function gaussian(int $n, int $dtype = self::FLOAT): vector {
168
        $max = getrandmax();
169
        $a = new self($n, $dtype);
170
        while (count($a) < $n) {
0 ignored issues
show
Bug introduced by
$a of type Np\vector is incompatible with the type Countable|array expected by parameter $value of count(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

170
        while (count(/** @scrutinizer ignore-type */ $a) < $n) {
Loading history...
171
            $r = sqrt(-2.0 * log(rand() / $max));
172
            $phi = rand() / $max * (2. * M_PI);
173
            $a[] = $r * sin($phi);
174
            $a[] = $r * cos($phi);
175
        }
176
        if (count($a) > $n) {
177
            $a = array_slice($a, 0, $n);
0 ignored issues
show
Bug introduced by
$a of type Np\vector is incompatible with the type array expected by parameter $array of array_slice(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

177
            $a = array_slice(/** @scrutinizer ignore-type */ $a, 0, $n);
Loading history...
178
        }
179
        return self::ar($a, $dtype);
1 ignored issue
show
Bug introduced by
It seems like $a can also be of type Np\vector; however, parameter $data of Np\vector::ar() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

179
        return self::ar(/** @scrutinizer ignore-type */ $a, $dtype);
Loading history...
180
    }
181
182
    /**
183
     * Generate a vector with n elements from a Poisson distribution.
184
     *
185
     * @param int $n
186
     * @param float $lambda
187
     * @param int $dtype 
188
     * @return vector
189
     */
190
    public static function poisson(int $n, float $lambda = 1.0, int $dtype = self::FLOAT): vector {
191
        $max = getrandmax();
192
        $l = exp(-$lambda);
193
        $a = new self($n, $dtype);
194
        for ($i = 0; $i < $n; ++$i) {
195
            $k = 0;
196
            $p = 1.0;
197
            while ($p > $l) {
198
                ++$k;
199
                $p *= rand() / $max;
200
            }
201
            $a->data[$i] = $k - 1;
202
        }
203
        return $a;
204
    }
205
206
    /**
207
     * Return a vector of n evenly spaced numbers between minimum and maximum.
208
     *
209
     * @param float $min
210
     * @param float $max
211
     * @param int $n
212
     * @param int $dtype
213
     * @throws invalidArgumentException
214
     * @return vector
215
     */
216
    public static function linspace(float $min, float $max, int $n, int $dtype = self::FLOAT): vector {
0 ignored issues
show
Unused Code introduced by
The parameter $dtype is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

216
    public static function linspace(float $min, float $max, int $n, /** @scrutinizer ignore-unused */ int $dtype = self::FLOAT): vector {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
217
        if ($min > $max) {
218
            throw new invalidArgumentException('Minimum must be less than maximum.');
219
        }
220
        if ($n < 2) {
221
            throw new invalidArgumentException('Number of elements must be greater than 1.');
222
        }
223
        $k = $n - 1;
224
        $interval = abs($max - $min) / $k;
225
        $a = [$min];
226
        while (count($a) < $k) {
227
            $a[] = end($a) + $interval;
228
        }
229
        $a[] = $max;
230
        return self::ar($a);
231
    }
232
233
    /**
234
     * make a copy of vector
235
     * @return vector
236
     */
237
    public function copyVector(): vector {
238
        return clone $this;
239
    }
240
241
    /**
242
     * Return the element-wise maximum of given vector with current vector
243
     * 
244
     * @param \Np\vector $vector
245
     * @return vector
246
     */
247
    public function maximum(\Np\vector $vector): vector {
248
        if ($this->checkDimensions($vector) && $this->checkDtype($vector)) {
249
            $v = new self($this->ndim, $this->dtype);
250
            for($i = 0; $i<$v->ndim; ++$i) {
251
                $v->data[$i] = max($this->data[$i],$vector->data[$i]);
252
            }
253
            return $v;
254
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 248 is false. This is incompatible with the type-hinted return Np\vector. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
255
    }
256
257
    /**
258
     * Return the element-wise minium of given vector with current vector
259
     * 
260
     * @param \Np\vector $vector
261
     * @return vector
262
     */
263
    public function minium(\Np\vector $vector): vector {
264
        if ($this->checkDimensions($vector) && $this->checkDtype($vector)) {
265
            $v = new self($this->ndim, $this->dtype);
266
            for($i = 0; $i<$v->ndim; ++$i) {
267
                $v->data[$i] = min($this->data[$i],$vector->data[$i]);
268
            }
269
            return $v;
270
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 264 is false. This is incompatible with the type-hinted return Np\vector. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
271
    }
272
    
273
    /**
274
     * Return the index of the minimum element in the vector.
275
     * 
276
     * @return int
277
     */
278
    public function argMin():int {
279
        return blas::min($this);
280
    }
281
    
282
    /**
283
     * Return the index of the maximum element in the vector.
284
     * 
285
     * @return int
286
     */
287
    public function argMx():int {
288
        return blas::max($this);
289
    }
290
291
    /**
292
     * vector-vector dot product
293
     * @param \Np\vector $vector
294
     * @param int $incX
295
     * @param int $incY
296
     * @return vector
297
     */
298
    public function dotVector(\Np\vector $v) {
299
        if ($this->checkDtype($v)) {
300
            return blas::dot($this, $v);
301
        }
302
    }
303
304
    /**
305
     * 
306
     * @return float
307
     */
308
    public function sum(): float {
309
        return blas::asum($this);
310
    }
311
312
    /**
313
     * Return the product of the vector.
314
     * @return int|float
315
     */
316
    public function product(): float {
317
        $r = 1.0;
318
        for ($i = 0; $i < $this->col; ++$i) {
319
            $r *= $this->data[$i];
320
        }
321
        return $r;
322
    }
323
324
    /**
325
     * Compute the vector-matrix dot product of this vector and matrix .
326
     * @param \Np\matrix $m
327
     * @return vector
328
     */
329
    public function dotMatrix(\Np\matrix $m): vector {
330
        if ($this->dtype != $m->dtype) {
331
            self::_err('Mismatch Dtype of given matrix');
332
        }
333
        $mvr = self::factory($this->col, $this->dtype);
334
        core\blas::gemv($m, $this, $mvr);
335
        return $mvr;
336
    }
337
338
    /**
339
     * 
340
     * @param int|float|matrix|vector $d
341
     * @return matrix|vector
342
     */
343
    public function divide(int|float|matrix|vector $d): matrix|vector {
344
        if ($d instanceof matrix) {
345
            return $this->divideMatrix($d);
346
        } elseif ($d instanceof self) {
347
            return $this->divideVector($d);
348
        } else {
349
            return $this->divideScalar($d);
350
        }
351
    }
352
353
    /**
354
     * 
355
     * @param \Np\matrix $m
356
     * @return matrix
357
     */
358
    protected function divideMatrix(\Np\matrix $m): matrix {
359
        if ($this->col == $m->col && $this->dtype == $m->dtype) {
360
            $vr = matrix::factory($m->row, $m->col, $m->dtype);
361
            for ($i = 0; $i < $m->row; ++$i) {
362
                for ($j = 0; $j < $m->col; ++$j) {
363
                    $vr->data[$i * $m->col + $j] = $this->data[$j] / $m->data[$i * $m->col + $j];
364
                }
365
            }
366
            return $vr;
367
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 359 is false. This is incompatible with the type-hinted return Np\matrix. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
368
    }
369
370
    /**
371
     * 
372
     * @param vector $v
373
     * @return vector
374
     */
375
    protected function divideVector(vector $v): vector {
376
        if ($this->checkDimensions($v) && $this->checkDtype($v)) {
377
            $vr = self::factory($this->col, $this->dtype);
378
            for ($i = 0; $i < $this->col; ++$i) {
379
                $vr->data[$i] = $this->data[$i] / $v->data[$i];
380
            }
381
            return $vr;
382
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 376 is false. This is incompatible with the type-hinted return Np\vector. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
383
    }
384
385
    /**
386
     * 
387
     * @param int|float $s
388
     * @return vector
389
     */
390
    protected function divideScalar(int|float $s): vector {
391
        $vr = self::factory($this->col, $this->dtype);
392
        for ($i = 0; $i < $this->col; ++$i) {
393
            $vr->data[$i] = $this->data[$i] / $s;
394
        }
395
        return $vr;
396
    }
397
398
    /**
399
     * 
400
     * @param int|float|matrix|vector $d
401
     * @return matrix|vector
402
     */
403
    public function multiply(int|float|matrix|vector $d): matrix|vector {
404
        if ($d instanceof matrix) {
405
            return $this->multiplyMatrix($d);
406
        } elseif ($d instanceof self) {
407
            return $this->multiplyVector($d);
408
        } else {
409
            return $this->multiplyScalar($d);
410
        }
411
    }
412
413
    /**
414
     * 
415
     * @param \Np\matrix $m
416
     * @return matrix
417
     */
418
    protected function multiplyMatrix(\Np\matrix $m): matrix {
419
        if ($this->col == $m->col && $this->dtype == $m->dtype) {
420
            $vr = matrix::factory($m->row, $m->col, $m->dtype);
421
            for ($i = 0; $i < $m->row; ++$i) {
422
                for ($j = 0; $j < $m->col; ++$j) {
423
                    $vr->data[$i * $m->col + $j] = $this->data[$j] * $m->data[$i * $m->col + $j];
424
                }
425
            }
426
            return $vr;
427
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 419 is false. This is incompatible with the type-hinted return Np\matrix. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
428
    }
429
430
    /**
431
     * 
432
     * @param \Np\vector $vector
433
     * @return vector
434
     */
435
    protected function multiplyVector(\Np\vector $vector): vector {
436
        if ($this->checkDimensions($vector) && $this->checkDtype($vector)) {
437
            $vr = self::factory($this->col, $this->dtype);
438
            for ($i = 0; $i < $this->col; ++$i) {
439
                $vr->data[$i] = $this->data[$i] * $vector->data[$i];
440
            }
441
            return $vr;
442
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 436 is false. This is incompatible with the type-hinted return Np\vector. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
443
    }
444
445
    /**
446
     * 
447
     * @param int|float $s
448
     * @return vector
449
     */
450
    protected function multiplyScalar(int|float $s): vector {
451
        $vr = $this->copyVector();
452
        blas::scale($s, $vr);
453
        return $vr;
454
    }
455
456
    /**
457
     * 
458
     * @param int|float|matrix|vector $d
459
     * @return matrix|vector
460
     */
461
    public function add(int|float|matrix|vector $d): matrix|vector {
462
        if ($d instanceof matrix) {
463
            return $this->addMatrix($d);
464
        } elseif ($d instanceof self) {
465
            return $this->addVector($d);
466
        } else {
467
            return $this->addScalar($d);
468
        }
469
    }
470
471
    /**
472
     * 
473
     * @param \Np\matrix $m
474
     * @return matrix
475
     */
476
    protected function addMatrix(\Np\matrix $m): matrix {
477
        if ($this->col == $m->col && $this->dtype == $m->dtype) {
478
            $vr = matrix::factory($m->row, $m->col, $m->dtype);
479
            for ($i = 0; $i < $m->row; ++$i) {
480
                for ($j = 0; $j < $m->col; ++$j) {
481
                    $vr->data[$i * $m->col + $j] = $this->data[$j] + $m->data[$i * $m->col + $j];
482
                }
483
            }
484
            return $vr;
485
        }
486
        self::_invalidArgument('');
1 ignored issue
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Np\matrix. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
487
    }
488
489
    /**
490
     * 
491
     * @param \Np\vector $vector
492
     * @return vector
493
     */
494
    protected function addVector(\Np\vector $vector): vector {
495
        if ($this->checkDimensions($vector) && $this->checkDtype($vector)) {
496
            $vr = self::factory($this->col, $this->dtype);
497
            for ($i = 0; $i < $this->col; ++$i) {
498
                $vr->data[$i] = $this->data[$i] + $vector->data[$i];
499
            }
500
            return $vr;
501
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 495 is false. This is incompatible with the type-hinted return Np\vector. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
502
    }
503
504
    /**
505
     * 
506
     * @param int|float $s
507
     * @return vector
508
     */
509
    protected function addScalar(int|float $s): vector {
510
        $vr = $this->copyVector();
511
        for ($i = 0; $i < $this->col; ++$i) {
512
            $vr->data[$i] += $s;
513
        }
514
        return $vr;
515
    }
516
517
    /**
518
     * 
519
     * @param \Np\vector $vector
520
     * @return vector
521
     */
522
    public function powVector(\Np\vector $vector): vector {
523
        if ($this->checkDimensions($vector) && $this->checkDtype($vector)) {
524
            $vr = self::factory($this->col, $this->dtype);
525
            for ($i = 0; $i < $this->col; ++$i) {
526
                $vr->data[$i] = $this->data[$i] ** $vector->data[$i];
527
            }
528
            return $vr;
529
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 523 is false. This is incompatible with the type-hinted return Np\vector. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
530
    }
531
532
    /**
533
     * 
534
     * @param \Np\vector $vector
535
     * @return vector
536
     */
537
    public function modVector(\Np\vector $vector): vector {
538
        if ($this->checkDimensions($vector) && $this->checkDtype($vector)) {
539
            $vr = self::factory($this->col, $this->dtype);
540
            for ($i = 0; $i < $this->col; ++$i) {
541
                $vr->data[$i] = $this->data[$i] % $vector->data[$i];
542
            }
543
            return $vr;
544
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 538 is false. This is incompatible with the type-hinted return Np\vector. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
545
    }
546
547
    /**
548
     * 
549
     * @param int|float|matrix|vector $d
550
     * @return matrix|vector
551
     */
552
    public function subtract(int|float|matrix|vector $d): matrix|vector {
553
        if ($d instanceof matrix) {
554
            return $this->subtractMatrix($d);
555
        } elseif ($d instanceof self) {
556
            return $this->subtractVector($d);
557
        } else {
558
            return $this->substractScalar($d);
559
        }
560
    }
561
562
    /**
563
     * 
564
     * @param \Np\matrix $m
565
     * @return matrix
566
     */
567
    protected function subtractMatrix(\Np\matrix $m): matrix {
568
        if ($this->col == $m->col && $this->dtype == $m->dtype) {
569
            $vr = matrix::factory($m->row, $m->col, $m->dtype);
570
            for ($i = 0; $i < $m->row; ++$i) {
571
                for ($j = 0; $j < $m->col; ++$j) {
572
                    $vr->data[$i * $m->col + $j] = $this->data[$j] - $m->data[$i * $m->col + $j];
573
                }
574
            }
575
            return $vr;
576
        }
577
        self::_invalidArgument('');
1 ignored issue
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Np\matrix. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
578
    }
579
580
    /**
581
     * 
582
     * @param \Np\vector $vector
583
     * @return vector
584
     */
585
    protected function subtractVector(\Np\vector $vector): vector {
586
        if ($this->checkDimensions($vector) && $this->checkDtype($vector)) {
587
            $vr = self::factory($this->col, $this->dtype);
588
            for ($i = 0; $i < $this->col; ++$i) {
589
                $vr->data[$i] = $this->data[$i] - $vector->data[$i];
590
            }
591
            return $vr;
592
        }
1 ignored issue
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 586 is false. This is incompatible with the type-hinted return Np\vector. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
593
    }
594
595
    /**
596
     * 
597
     * @param \Np\vector $scalar
598
     * @return \Np\vector
599
     */
600
    protected function substractScalar(int|float $scalar): vector {
601
        $vr = self::factory($this->col, $this->dtype);
602
        for ($i = 0; $i < $this->col; ++$i) {
603
            $vr->data[$i] = $this->data[$i] - $scalar;
604
        }
605
        return $vr;
606
    }
607
608
    /**
609
     * 
610
     * @param \Np\vector $v
611
     * @param int $stride
612
     * @return vector
613
     */
614
    public function convolve(\Np\vector $v, int $stride = 1): vector {
615
        return convolve::conv1D($this, $v, $stride);
616
    }
617
618
    /**
619
     * Return the inner product of two vectors.
620
     *
621
     * @param \Np\vector $vector
622
     * @return float
623
     */
624
    public function inner(\Np\vector $vector) {
625
        return $this->dotVector($vector);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->dotVector($vector) returns the type Np\vector which is incompatible with the documented return type double.
Loading history...
626
    }
627
628
    public function l1_norm() {
629
        
630
    }
631
632
    public function l2_norm() {
633
        
634
    }
635
636
    /**
637
     * sort the vector 
638
     * @param string $type i or d
639
     * 
640
     */
641
    public function sort($type = 'i') {
642
        lapack::sort($this, $type);
643
        return $this;
644
    }
645
646
    /**
647
     * set data to vector
648
     * @param int|float|array $data
649
     */
650
    public function setData(int|float|array $data) {
651
        if (is_array($data) && !is_array($data[0])) {
652
            for ($i = 0; $i < $this->col; ++$i) {
653
                $this->data[$i] = $data[$i];
654
            }
655
        } elseif (is_numeric($data)) {
656
            for ($i = 0; $i < $this->col; ++$i) {
657
                $this->data[$i] = $data;
658
            }
659
        }
660
    }
661
662
    public function asMatrix(): matrix {
663
        $size = (int) sqrt($this->col);
664
        $ar = matrix::factory($size, $size, $this->dtype);
665
        for ($i = 0; $i < $ar->ndim; ++$i) {
666
            $ar->data[$i] = $this->data[$i];
667
        }
668
        return $ar;
669
    }
670
671
    /**
672
     * get the shape of matrix
673
     * @return int
674
     */
675
    public function getShape(): int {
676
        return $this->col;
677
    }
678
679
    public function getDtype() {
680
        return $this->dtype;
681
    }
682
683
    public function asArray() {
684
        $ar = array_fill(0, $this->col, null);
685
        for ($i = 0; $i < $this->col; ++$i) {
686
            $ar[$i] = $this->data[$i];
687
        }
688
        return $ar;
689
    }
690
691
    public function printVector() {
692
        for ($j = 0; $j < $this->col; ++$j) {
693
            printf('%lf  ', $this->data[$j]);
694
        }
695
        echo PHP_EOL;
696
    }
697
698
    public function __toString() {
699
        return (string) $this->printVector();
1 ignored issue
show
Bug introduced by
Are you sure the usage of $this->printVector() targeting Np\vector::printVector() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
700
    }
701
702
    protected function checkDimensions(vector $vector) {
703
        if ($this->col != $vector->col) {
704
            throw new dimensionalityMismatch('Mismatch Dimensions of given vectors');
705
        }
706
        return true;
707
    }
708
709
    protected function checkDtype(vector $vector) {
710
        if ($this->dtype != $vector->dtype) {
711
            throw new dtypeException('Mismatch dtype of given vector');
712
        }
713
        return true;
714
    }
715
716
    protected function __construct(int $col, int $dtype = self::FLOAT) {
717
        if ($col < 1) {
718
            throw new invalidArgumentException('* To create Numphp/Vector col must be greater than 0!, Op Failed! * ');
719
        }
720
        parent::__construct($col, $dtype);
721
        $this->col = $col;
0 ignored issues
show
Bug Best Practice introduced by
The property col does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
722
        return $this;
723
    }
724
725
}
726