Passed
Push — main ( cb3172...6ba222 )
by Shubham
01:56
created

vector::mod()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 7
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
};
15
16
/** A fast lite memory efficient Scientific Computing in php
17
 * Vector (rank-1)
18
 * 
19
 * @package NumPhp
20
 * @version V0.0.alpha
21
 * @category Php Scientific Library
22
 * @author ghost (Shubham Chaudhary)
23
 * @email [email protected]
24
 * @copyright (c) 2020-2021, Shubham Chaudhary
25
 * 
26
 */
27
class vector extends nd {
28
29
    /**
30
     * Factory method to build a new vector.
31
     * 
32
     * @param int $col
33
     * @param int $dtype
34
     * @return vector
35
     */
36
    public static function factory(int $col, int $dtype = self::FLOAT): vector {
37
        return new self($col, $dtype);
38
    }
39
40
    /**
41
     * Build a new vector from a php array.
42
     * 
43
     * @param array $data
44
     * @param int $dtype
45
     * @return vector
46
     */
47
    public static function ar(array $data, int $dtype = self::FLOAT): vector {
48
        if (is_array($data) && !is_array($data[0])) {
49
            $ar = self::factory(count($data), $dtype);
50
            $ar->setData($data);
51
            return $ar;
52
        } else {
53
            self::_err('data must be of same dimensions');
54
        }
55
    }
56
57
    /**
58
     * Return vector with random values
59
     * @param int $col
60
     * @param int $dtype
61
     * @return vector
62
     */
63
    public static function randn(int $col, int $dtype = self::FLOAT): vector {
64
        $ar = self::factory($col, $dtype);
65
        $max = getrandmax();
66
        for ($i = 0; $i < $ar->col; ++$i) {
67
            $ar->data[$i] = rand() / $max;
68
        }
69
        return $ar;
70
    }
71
72
    /**
73
     * Return vector with uniform values
74
     * @param int $col
75
     * @param int $dtype
76
     * @return vector
77
     */
78
    public static function uniform(int $col, int $dtype = self::FLOAT): vector {
79
        $ar = self::factory($col, $dtype);
80
        $max = getrandmax();
81
        for ($i = 0; $i < $col; ++$i) {
82
            $ar->data[$i] = rand(-$max, $max) / $max;
83
        }
84
        return $ar;
85
    }
86
87
    /**
88
     * Build a vector of zeros with n elements.
89
     * 
90
     * @param int $col
91
     * @param int $dtype
92
     * @return vector
93
     */
94
    public static function zeros(int $col, int $dtype = self::FLOAT): vector {
95
        $ar = self::factory($col, $dtype);
96
        for ($i = 0; $i < $col; ++$i) {
97
            $ar->data[$i] = 0;
98
        }
99
        return $ar;
100
    }
101
102
    /**
103
     * create one like vector
104
     * 
105
     * @param int $col
106
     * @return vector
107
     */
108
    public static function ones(int $col, int $dtype = self::FLOAT): vector {
109
        $ar = self::factory($col, $dtype);
110
        for ($i = 0; $i < $col; ++$i) {
111
            $ar->data[$i] = 1;
112
        }
113
        return $ar;
114
    }
115
116
    /**
117
     * create a null like vector
118
     * @param int $col
119
     * @return vector
120
     */
121
    public static function null(int $col, int $dtype = self::FLOAT): vector {
122
        $ar = self::factory($col, $dtype);
123
        for ($i = 0; $i < $col; ++$i) {
124
            $ar->data[$i] = null;
125
        }
126
        return $ar;
127
    }
128
129
    /**
130
     * create a vector with given scalar value
131
     * @param int $col
132
     * @param int|float|double $val
133
     * @param int $dtype
134
     * @return vector
135
     */
136
    public static function full(int $col, int|float $val, int $dtype = self::FLOAT): vector {
137
        $ar = self::factory($col, $dtype);
138
        for ($i = 0; $i < $col; ++$i) {
139
            $ar->data[$i] = $val;
140
        }
141
        return $ar;
142
    }
143
144
    /**
145
     * Return evenly spaced values within a given interval.
146
     *
147
     * @param int|float $start
148
     * @param int|float $end
149
     * @param int|float $interval
150
     * @param int $dtype 
151
     * @return vector
152
     */
153
    public static function range(int|float $start, int|float $end, int|float $interval = 1, int $dtype = self::FLOAT): vector {
154
        return self::ar(range($start, $end, $interval), $dtype);
155
    }
156
157
    /**
158
     * Return a Gaussian random vector with mean 0
159
     * and unit variance.
160
     *
161
     * @param int $n
162
     * @param int $dtype
163
     * @return self
164
     */
165
    public static function gaussian(int $n, int $dtype = self::FLOAT): vector {
166
        $max = getrandmax();
167
        $a = [];
168
        while (count($a) < $n) {
169
            $r = sqrt(-2.0 * log(rand() / $max));
170
            $phi = rand() / $max * (2. * M_PI);
171
            $a[] = $r * sin($phi);
172
            $a[] = $r * cos($phi);
173
        }
174
        if (count($a) > $n) {
175
            $a = array_slice($a, 0, $n);
176
        }
177
        return self::ar($a, $dtype);
178
    }
179
180
    /**
181
     * Generate a vector with n elements from a Poisson distribution.
182
     *
183
     * @param int $n
184
     * @param float $lambda
185
     * @param int $dtype 
186
     * @return vector
187
     */
188
    public static function poisson(int $n, float $lambda = 1.0, int $dtype = self::FLOAT): vector {
189
        $max = getrandmax();
190
        $l = exp(-$lambda);
191
        $a = new self($n, $dtype);
192
        for ($i = 0; $i < $n; ++$i) {
193
            $k = 0;
194
            $p = 1.0;
195
            while ($p > $l) {
196
                ++$k;
197
                $p *= rand() / $max;
198
            }
199
            $a->data[$i] = $k - 1;
200
        }
201
        return $a;
202
    }
203
204
    /**
205
     * Return a vector of n evenly spaced numbers between minimum and maximum.
206
     *
207
     * @param float $min
208
     * @param float $max
209
     * @param int $n
210
     * @param int $dtype
211
     * @throws invalidArgumentException
212
     * @return vector
213
     */
214
    public static function linspace(float $min, float $max, int $n, int $dtype = self::FLOAT): vector {
215
        if ($min > $max) {
216
            throw new invalidArgumentException('Minimum must be less than maximum.');
217
        }
218
        if ($n < 2) {
219
            throw new invalidArgumentException('Number of elements must be greater than 1.');
220
        }
221
        $k = $n - 1;
222
        $interval = abs($max - $min) / $k;
223
        $a = [$min];
224
        while (count($a) < $k) {
225
            $a[] = end($a) + $interval;
226
        }
227
        $a[] = $max;
228
        return self::ar($a, $dtype);
229
    }
230
231
    /**
232
     * make a copy of vector
233
     * @return vector
234
     */
235
    public function copyVector(): vector {
236
        return clone $this;
237
    }
238
239
    /**
240
     * Return the element-wise maximum of given vector with current vector
241
     * 
242
     * @param \Np\vector $vector
243
     * @return vector
244
     */
245
    public function maximum(\Np\vector $vector): vector {
246
        if ($this->checkShape($this, $vector) && $this->checkDtype($this, $vector)) {
247
            $v = new self($this->ndim, $this->dtype);
248
            for ($i = 0; $i < $v->ndim; ++$i) {
249
                $v->data[$i] = max($this->data[$i], $vector->data[$i]);
250
            }
251
            return $v;
252
        }
253
    }
254
255
    /**
256
     * Return the element-wise minium of given vector with current vector
257
     * 
258
     * @param \Np\vector $vector
259
     * @return vector
260
     */
261
    public function minium(\Np\vector $vector): vector {
262
        if ($this->checkShape($this, $vector) && $this->checkDtype($this, $vector)) {
263
            $v = new self($this->ndim, $this->dtype);
264
            for ($i = 0; $i < $v->ndim; ++$i) {
265
                $v->data[$i] = min($this->data[$i], $vector->data[$i]);
266
            }
267
            return $v;
268
        }
269
    }
270
271
    /**
272
     * Return the index of the minimum element in the vector.
273
     * 
274
     * @return int
275
     */
276
    public function argMin(): int {
277
        return blas::min($this);
278
    }
279
280
    /**
281
     * Return the index of the maximum element in the vector.
282
     * 
283
     * @return int
284
     */
285
    public function argMx(): int {
286
        return blas::max($this);
287
    }
288
289
    /**
290
     * vector-vector dot product
291
     * @param \Np\vector $vector
292
     * @param int $incX
293
     * @param int $incY
294
     * @return vector
295
     */
296
    public function dotVector(\Np\vector $v) {
297
        if ($this->checkDtype($this, $v)) {
298
            return blas::dot($this, $v);
299
        }
300
    }
301
302
    /**
303
     * The sum of the vector.
304
     * @return float
305
     */
306
    public function sum(): float {
307
        return blas::asum($this);
308
    }
309
310
    /**
311
     * Return the product of the vector.
312
     * @return int|float
313
     */
314
    public function product(): float {
315
        $r = 1.0;
316
        for ($i = 0; $i < $this->col; ++$i) {
317
            $r *= $this->data[$i];
318
        }
319
        return $r;
320
    }
321
322
    /**
323
     * Compute the vector-matrix dot product of this vector and matrix .
324
     * @param \Np\matrix $m
325
     * @return vector
326
     */
327
    public function dotMatrix(\Np\matrix $m): vector {
328
        if ($this->checkDtype($this, $m)) {
329
            $mvr = self::factory($this->col, $this->dtype);
330
            core\blas::gemv($m, $this, $mvr);
331
            return $mvr;
332
        }
333
    }
334
335
    /**
336
     * 
337
     * @param int|float|matrix|vector $d
338
     * @return matrix|vector
339
     */
340
    public function divide(int|float|matrix|vector $d): matrix|vector {
341
        if ($d instanceof matrix) {
342
            return $this->divideMatrix($d);
343
        } elseif ($d instanceof self) {
344
            return $this->divideVector($d);
345
        } else {
346
            return $this->divideScalar($d);
347
        }
348
    }
349
350
    /**
351
     * 
352
     * @param \Np\matrix $m
353
     * @return matrix
354
     */
355
    protected function divideMatrix(\Np\matrix $m): matrix {
356
        if ($this->checkShape($this, $m) && $this->checkDtype($this, $m)) {
357
            $vr = matrix::factory($m->row, $m->col, $m->dtype);
358
            for ($i = 0; $i < $m->row; ++$i) {
359
                for ($j = 0; $j < $m->col; ++$j) {
360
                    $vr->data[$i * $m->col + $j] = $this->data[$j] / $m->data[$i * $m->col + $j];
361
                }
362
            }
363
            return $vr;
364
        }
365
    }
366
367
    /**
368
     * 
369
     * @param vector $v
370
     * @return vector
371
     */
372
    protected function divideVector(vector $v): vector {
373
        if ($this->checkShape($this, $v) && $this->checkDtype($this, $v)) {
374
            $vr = self::factory($this->col, $this->dtype);
375
            for ($i = 0; $i < $this->col; ++$i) {
376
                $vr->data[$i] = $this->data[$i] / $v->data[$i];
377
            }
378
            return $vr;
379
        }
380
    }
381
382
    /**
383
     * 
384
     * @param int|float $s
385
     * @return vector
386
     */
387
    protected function divideScalar(int|float $s): vector {
388
        $vr = self::factory($this->col, $this->dtype);
389
        for ($i = 0; $i < $this->col; ++$i) {
390
            $vr->data[$i] = $this->data[$i] / $s;
391
        }
392
        return $vr;
393
    }
394
395
    /**
396
     * 
397
     * @param int|float|matrix|vector $d
398
     * @return matrix|vector
399
     */
400
    public function multiply(int|float|matrix|vector $d): matrix|vector {
401
        if ($d instanceof matrix) {
402
            return $this->multiplyMatrix($d);
403
        } elseif ($d instanceof self) {
404
            return $this->multiplyVector($d);
405
        } else {
406
            return $this->multiplyScalar($d);
407
        }
408
    }
409
410
    /**
411
     * 
412
     * @param \Np\matrix $m
413
     * @return matrix
414
     */
415
    protected function multiplyMatrix(\Np\matrix $m): matrix {
416
        if ($this->checkShape($this, $m) && $this->checkDtype($this, $m)) {
417
            $vr = matrix::factory($m->row, $m->col, $m->dtype);
418
            for ($i = 0; $i < $m->row; ++$i) {
419
                for ($j = 0; $j < $m->col; ++$j) {
420
                    $vr->data[$i * $m->col + $j] = $this->data[$j] * $m->data[$i * $m->col + $j];
421
                }
422
            }
423
            return $vr;
424
        }
425
    }
426
427
    /**
428
     * 
429
     * @param \Np\vector $vector
430
     * @return vector
431
     */
432
    protected function multiplyVector(\Np\vector $vector): vector {
433
        if ($this->checkShape($this, $vector) && $this->checkDtype($this, $vector)) {
434
            $vr = self::factory($this->col, $this->dtype);
435
            for ($i = 0; $i < $this->col; ++$i) {
436
                $vr->data[$i] = $this->data[$i] * $vector->data[$i];
437
            }
438
            return $vr;
439
        }
440
    }
441
442
    /**
443
     * 
444
     * @param int|float $s
445
     * @return vector
446
     */
447
    protected function multiplyScalar(int|float $s): vector {
448
        $vr = $this->copyVector();
449
        blas::scale($s, $vr);
450
        return $vr;
451
    }
452
453
    /**
454
     * 
455
     * @param int|float|matrix|vector $d
456
     * @return matrix|vector
457
     */
458
    public function add(int|float|matrix|vector $d): matrix|vector {
459
        if ($d instanceof matrix) {
460
            return $this->addMatrix($d);
461
        } elseif ($d instanceof self) {
462
            return $this->addVector($d);
463
        } else {
464
            return $this->addScalar($d);
465
        }
466
    }
467
468
    /**
469
     * 
470
     * @param \Np\matrix $m
471
     * @return matrix
472
     */
473
    protected function addMatrix(\Np\matrix $m): matrix {
474
        if ($this->checkShape($this, $m) && $this->checkDtype($this, $m)) {
475
            $vr = matrix::factory($m->row, $m->col, $m->dtype);
476
            for ($i = 0; $i < $m->row; ++$i) {
477
                for ($j = 0; $j < $m->col; ++$j) {
478
                    $vr->data[$i * $m->col + $j] = $this->data[$j] + $m->data[$i * $m->col + $j];
479
                }
480
            }
481
            return $vr;
482
        }
483
    }
484
485
    /**
486
     * 
487
     * @param \Np\vector $vector
488
     * @return vector
489
     */
490
    protected function addVector(\Np\vector $vector): vector {
491
        if ($this->checkShape($this, $vector) && $this->checkDtype($this, $vector)) {
492
            $vr = self::factory($this->col, $this->dtype);
493
            for ($i = 0; $i < $this->col; ++$i) {
494
                $vr->data[$i] = $this->data[$i] + $vector->data[$i];
495
            }
496
            return $vr;
497
        }
498
    }
499
500
    /**
501
     * 
502
     * @param int|float $s
503
     * @return vector
504
     */
505
    protected function addScalar(int|float $s): vector {
506
        $vr = $this->copyVector();
507
        for ($i = 0; $i < $this->col; ++$i) {
508
            $vr->data[$i] += $s;
509
        }
510
        return $vr;
511
    }
512
513
    /**
514
     * 
515
     * @param int|float|\Np\matrix|\Np\vector $d
516
     * @return matrix|vector
517
     */
518
    public function pow(int|float|\Np\matrix|\Np\vector $d): matrix|vector {
519
        if ($d instanceof matrix) {
520
            return $this->powMatrix($d);
521
        } elseif ($d instanceof vector) {
522
            return $this->powVector($d);
523
        } else {
524
            return $this->powScalar($d);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->powScalar($d) targeting Np\vector::powScalar() 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...
525
        }
526
    }
527
528
    /**
529
     * 
530
     * @param \Np\matrix $m
531
     * @return matrix
532
     */
533
    protected function powMatrix(\Np\matrix $m): matrix {
534
        if ($this->checkDimensions($this, $m) && $this->checkDtype($this, $m)) {
535
            $ar = matrix::factory($m->row, $m->col, $this->dtype);
536
            for ($i = 0; $i < $m->row; ++$i) {
537
                for ($j = 0; $j < $m - col; ++$j) {
0 ignored issues
show
Bug introduced by
The constant Np\col was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
538
                    $ar->data[$i * $m->col + $j] = $m->data[$i * $m->col + $j] ** $this->data[$j];
539
                }
540
            }
541
            return $ar;
542
        }
543
    }
544
545
    /**
546
     * 
547
     * @param \Np\vector $vector
548
     * @return vector
549
     */
550
    protected function powVector(\Np\vector $vector): vector {
551
        if ($this->checkShape($this, $vector) && $this->checkDtype($this, $vector)) {
552
            $vr = self::factory($this->col, $this->dtype);
553
            for ($i = 0; $i < $this->col; ++$i) {
554
                $vr->data[$i] = $this->data[$i] ** $vector->data[$i];
555
            }
556
            return $vr;
557
        }
558
    }
559
560
    /**
561
     * 
562
     * @param int|float $s
563
     */
564
    protected function powScalar(int|float $s) {
565
        $v = $this->copyVector();
566
        for ($i = 0; $i < $this->col; ++$i) {
567
            $v->data[$i] = $v->data[$i] ** $s;
568
        }
569
    }
570
571
    /**
572
     * 
573
     * @param int|float|\Np\matrix|\Np\vector $d
574
     * @return matrix|vector
575
     */
576
    public function mod(int|float|\Np\matrix|\Np\vector $d): matrix|vector {
577
        if ($d instanceof matrix) {
578
            return $this->powMatrix($d);
579
        } elseif ($d instanceof vector) {
580
            return $this->powVector($d);
581
        } else {
582
            return $this->powScalar($d);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->powScalar($d) targeting Np\vector::powScalar() 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...
583
        }
584
    }
585
586
    /**
587
     * 
588
     * @param \Np\matrix $m
589
     * @return matrix
590
     */
591
    protected function modMatrix(\Np\matrix $m): matrix {
592
        if ($this->checkDimensions($this, $m) && $this->checkDtype($this, $m)) {
593
            $ar = matrix::factory($m->row, $m->col, $this->dtype);
594
            for ($i = 0; $i < $m->row; ++$i) {
595
                for ($j = 0; $j < $m - col; ++$j) {
0 ignored issues
show
Bug introduced by
The constant Np\col was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
596
                    $ar->data[$i * $m->col + $j] = $m->data[$i * $m->col + $j] % $this->data[$j];
597
                }
598
            }
599
            return $ar;
600
        }
601
    }
602
603
    /**
604
     * 
605
     * @param \Np\vector $vector
606
     * @return vector
607
     */
608
    protected function modVector(\Np\vector $vector): vector {
609
        if ($this->checkShape($this, $vector) && $this->checkDtype($this, $vector)) {
610
            $vr = self::factory($this->col, $this->dtype);
611
            for ($i = 0; $i < $this->col; ++$i) {
612
                $vr->data[$i] = $this->data[$i] % $vector->data[$i];
613
            }
614
            return $vr;
615
        }
616
    }
617
618
    /**
619
     * 
620
     * @param int|float $s
621
     */
622
    protected function modScalar(int|float $s) {
623
        $v = $this->copyVector();
624
        for ($i = 0; $i < $this->col; ++$i) {
625
            $v->data[$i] = $v->data[$i] % $s;
626
        }
627
    }
628
629
    /**
630
     * 
631
     * @param int|float|matrix|vector $d
632
     * @return matrix|vector
633
     */
634
    public function subtract(int|float|matrix|vector $d): matrix|vector {
635
        if ($d instanceof matrix) {
636
            return $this->subtractMatrix($d);
637
        } elseif ($d instanceof self) {
638
            return $this->subtractVector($d);
639
        } else {
640
            return $this->substractScalar($d);
641
        }
642
    }
643
644
    /**
645
     * 
646
     * @param \Np\matrix $m
647
     * @return matrix
648
     */
649
    protected function subtractMatrix(\Np\matrix $m): matrix {
650
        if ($this->checkShape($this, $m) && $this->checkDtype($this, $m)) {
651
            $vr = matrix::factory($m->row, $m->col, $m->dtype);
652
            for ($i = 0; $i < $m->row; ++$i) {
653
                for ($j = 0; $j < $m->col; ++$j) {
654
                    $vr->data[$i * $m->col + $j] = $this->data[$j] - $m->data[$i * $m->col + $j];
655
                }
656
            }
657
            return $vr;
658
        }
659
    }
660
661
    /**
662
     * 
663
     * @param \Np\vector $vector
664
     * @return vector
665
     */
666
    protected function subtractVector(\Np\vector $vector): vector {
667
        if ($this->checkShape($this, $vector) && $this->checkDtype($this, $vector)) {
668
            $vr = self::factory($this->col, $this->dtype);
669
            for ($i = 0; $i < $this->col; ++$i) {
670
                $vr->data[$i] = $this->data[$i] - $vector->data[$i];
671
            }
672
            return $vr;
673
        }
674
    }
675
676
    /**
677
     * 
678
     * @param \Np\vector $scalar
679
     * @return \Np\vector
680
     */
681
    protected function substractScalar(int|float $scalar): vector {
682
        $vr = self::factory($this->col, $this->dtype);
683
        for ($i = 0; $i < $this->col; ++$i) {
684
            $vr->data[$i] = $this->data[$i] - $scalar;
685
        }
686
        return $vr;
687
    }
688
689
    /**
690
     * 
691
     * @param \Np\vector $v
692
     * @param int $stride
693
     * @return vector
694
     */
695
    public function convolve(\Np\vector $v, int $stride = 1): vector {
696
        return convolve::conv1D($this, $v, $stride);
697
    }
698
699
    /**
700
     * Run a function over all of the elements in the vector. 
701
     * 
702
     * @param callable $func
703
     * @return vector
704
     */
705
    public function map(callable $func): vector {
706
        $vr = self::factory($this->col, $this->dtype);
707
        for ($i = 0; $i < $this->col; ++$i) {
708
            $vr->data[$i] = $func($this->data[$i]);
709
        }
710
        return $vr;
711
    }
712
713
    public function log(float $b = M_E): vector {
714
        $vr = $this->copyVector();
715
        for ($i = 0; $i < $vr->col; ++$i) {
716
            log($vr->data[$i], $b);
717
        }
718
        return $vr;
719
    }
720
721
    public function max() {
722
        return $this->data[blas::max($this)];
723
    }
724
725
    public function min() {
726
        $this->data[blas::min($this)];
727
    }
728
729
    public function abs(): vector {
730
        return $this->map('abs');
731
    }
732
733
    public function sqrt(): vector {
734
        return $this->map('sqrt');
735
    }
736
737
    public function exp(): vector {
738
        return $this->map('exp');
739
    }
740
741
    public function exp1(): vector {
742
        return $this->map('exp1');
743
    }
744
745
    public function log1p(): vector {
746
        return $this->map('log1p');
747
    }
748
749
    public function sin(): vector {
750
        return $this->map('sin');
751
    }
752
753
    public function asin(): vector {
754
        return $this->map('asin');
755
    }
756
757
    public function cos(): vector {
758
        return $this->map('cos');
759
    }
760
761
    public function acos(): vector {
762
        return $this->map('acos');
763
    }
764
765
    public function tan(): vector {
766
        return $this->map('tan');
767
    }
768
769
    public function atan(): vector {
770
        return $this->map('atan');
771
    }
772
773
    public function radToDeg(): vector {
774
        return $this->map('rad2deg');
775
    }
776
777
    public function degToRad(): vector {
778
        return $this->map('deg2rad');
779
    }
780
781
    public function floor(): vector {
782
        return $this->map('floor');
783
    }
784
785
    public function ceil(): vector {
786
        return $this->map('ceil');
787
    }
788
    
789
    /**
790
     * 
791
     * @param float $min
792
     * @param float $max
793
     * @return vector
794
     */
795
    public function clip(float $min, float $max) : vector {
796
        if ($min > $max) {
797
            self::_invalidArgument('Minimum cannot be greater than maximum.');
798
        }
799
800
        $vr = self::factory($this->col, $this->dtype);
801
        
802
        for($i = 0; $i < $this->col; ++$i) {
803
            if ($this->data[$i] > $max) {
804
                $vr->data[$i] = $max;
805
                continue;
806
            }
807
            if ($this->data[$i] < $min) {
808
                $vr->data[$i] = $min;
809
                continue;
810
            }
811
        }
812
813
        return $vr;
814
    }
815
    
816
    public function clipUpper(float $min) : vector {
817
        $vr = self::factory($this->col, $this->dtype);
818
        for($i = 0; $i < $this->col; ++$i) {
819
            if ($this->data[$i] > $min) {
820
                $vr->data[$i] = $min;
821
                continue;
822
            }
823
        }
824
        return $vr;
825
    }
826
    
827
    public function clipLower(float $min) : vector {
828
        $vr = self::factory($this->col, $this->dtype);
829
        for($i = 0; $i < $this->col; ++$i) {
830
            if ($this->data[$i] < $min) {
831
                $vr->data[$i] = $min;
832
                continue;
833
            }
834
        }
835
        return $vr;
836
    }
837
    
838
    /**
839
     * Return the inner product of two vectors.
840
     *
841
     * @param \Np\vector $vector
842
     * 
843
     */
844
    public function inner(\Np\vector $vector) {
845
        return $this->dotVector($vector);
846
    }
847
848
    /**
849
     * Calculate the L1 norm of the vector.
850
     * @return float
851
     */
852
    public function normL1(): float {
853
        return $this->abs()->sum();
854
    }
855
856
    public function normL2() {
857
        return sqrt($this->square()->sum());
858
    }
859
860
    public function normMax() {
861
        return $this->abs()->max();
862
    }
863
864
    public function normP(float $p = 2.5) {
865
        if ($p <= 0.0) {
866
            self::_invalidArgument('P must be greater than 0.0 !');
867
        }
868
        return $this->abs()->powScalar($p)->sum() ** (1.0 / $p);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->abs()->powScalar($p) targeting Np\vector::powScalar() 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...
869
    }
870
871
    /**
872
     * Return the reciprocal of the vector element-wise.
873
     *
874
     * @return self
875
     */
876
    public function reciprocal(): vector {
877
        return self::ones($this->col, $this->dtype)
878
                        ->divideVector($this);
879
    }
880
    
881
    /**
882
     * 
883
     * @return int|float
884
     */
885
    public function mean():int|float {
886
        return $this->sum()/ $this->col;
887
    }
888
    
889
    /**
890
     * 
891
     * @return int|float
892
     */
893
    public function median():int|float {
894
        $mid = intdiv($this->col, 2);
895
896
        $a = $this->copyVector()->sort();
897
        if ($this->col % 2 === 1) {
898
            $median = $a->data[$mid];
899
        } else {
900
            $median = ($a->data[$mid - 1] + $a->data[$mid]) / 2.;
901
        }
902
        return $median;
903
    }
904
    
905
    public function variance($mean = null)
906
    {
907
        if (is_null($mean)) {
908
            $mean = $this->mean();
909
        }
910
911
        $sd = $this->substractScalar($mean)
912
            ->square()
913
            ->sum();
914
915
        return $sd / $this->col;
916
    }
917
918
    /**
919
     * 
920
     * @return vector
921
     */
922
    public function square(): vector {
923
        return $this->multiplyVector($this);
924
    }
925
926
    /**
927
     * sort the vector 
928
     * @param string $type i or d
929
     * 
930
     */
931
    public function sort($type = 'i') {
932
        lapack::sort($this, $type);
933
        return $this;
934
    }
935
936
    /**
937
     * set data to vector
938
     * @param int|float|array $data
939
     */
940
    public function setData(int|float|array $data) {
941
        if (is_array($data) && !is_array($data[0])) {
942
            for ($i = 0; $i < $this->col; ++$i) {
943
                $this->data[$i] = $data[$i];
944
            }
945
        } elseif (is_numeric($data)) {
946
            for ($i = 0; $i < $this->col; ++$i) {
947
                $this->data[$i] = $data;
948
            }
949
        }
950
    }
951
952
    public function asMatrix(): matrix {
953
        $size = (int) sqrt($this->col);
954
        $ar = matrix::factory($size, $size, $this->dtype);
955
        for ($i = 0; $i < $ar->ndim; ++$i) {
956
            $ar->data[$i] = $this->data[$i];
957
        }
958
        return $ar;
959
    }
960
961
    /**
962
     * get the shape of matrix
963
     * @return int
964
     */
965
    public function getShape(): int {
966
        return $this->col;
967
    }
968
969
    public function getDtype() {
970
        return $this->dtype;
971
    }
972
973
    public function asArray() {
974
        $ar = array_fill(0, $this->col, null);
975
        for ($i = 0; $i < $this->col; ++$i) {
976
            $ar[$i] = $this->data[$i];
977
        }
978
        return $ar;
979
    }
980
981
    public function printVector() {
982
        for ($j = 0; $j < $this->col; ++$j) {
983
            printf('%lf  ', $this->data[$j]);
984
        }
985
        echo PHP_EOL;
986
    }
987
988
    public function __toString() {
989
        return (string) $this->printVector();
990
    }
991
992
    protected function __construct(public int $col, int $dtype = self::FLOAT) {
993
        if ($this->col < 1) {
994
            throw new invalidArgumentException('* To create Numphp/Vector col must be greater than 0!, Op Failed! * ');
995
        }
996
        parent::__construct($this->col, $dtype);
997
        return $this;
998
    }
999
1000
}
1001