Passed
Push — main ( 16ad7b...83c0b8 )
by Shubham
01:42
created

vector   F

Complexity

Total Complexity 192

Size/Duplication

Total Lines 979
Duplicated Lines 0 %

Importance

Changes 9
Bugs 3 Features 0
Metric Value
eloc 315
c 9
b 3
f 0
dl 0
loc 979
rs 2
wmc 192

87 Methods

Rating   Name   Duplication   Size   Complexity  
A zeros() 0 6 2
A argMin() 0 2 1
A full() 0 6 2
A addScalar() 0 6 2
A divideScalar() 0 6 2
A linspace() 0 15 4
A ar() 0 7 3
A product() 0 6 2
A factory() 0 2 1
A gaussian() 0 13 3
A range() 0 2 1
A multiplyMatrix() 0 9 5
A copyVector() 0 2 1
A sum() 0 2 1
A multiplyScalar() 0 4 1
A multiply() 0 7 3
A dotVector() 0 3 2
A dotMatrix() 0 5 2
A divideVector() 0 7 4
A addVector() 0 7 4
A addMatrix() 0 9 5
A ones() 0 6 2
A null() 0 6 2
A add() 0 7 3
A argMx() 0 2 1
A multiplyVector() 0 7 4
A divide() 0 7 3
A poisson() 0 14 3
A uniform() 0 7 2
A divideMatrix() 0 9 5
A randn() 0 7 2
A powVector() 0 7 4
A minium() 0 7 4
A pow() 0 7 3
A powMatrix() 0 9 5
A maximum() 0 7 4
A mod() 0 7 3
A convolve() 0 2 1
A clipUpper() 0 9 3
A max() 0 2 1
A subtractMatrix() 0 9 5
A abs() 0 2 1
A sort() 0 3 1
A normL1() 0 2 1
A modScalar() 0 4 2
A radToDeg() 0 2 1
A modVector() 0 7 4
A substractScalar() 0 6 2
A normMax() 0 2 1
A tan() 0 2 1
A degToRad() 0 2 1
A normP() 0 5 2
A map() 0 6 2
A log() 0 6 2
A variance() 0 11 2
A subtract() 0 7 3
A inner() 0 2 1
A square() 0 2 1
A median() 0 10 2
A normL2() 0 2 1
A acos() 0 2 1
A subtractVector() 0 7 4
A atan() 0 2 1
A sqrt() 0 2 1
A powScalar() 0 6 2
A exp() 0 2 1
A exp1() 0 2 1
A cos() 0 2 1
A min() 0 2 1
A mean() 0 2 1
A ceil() 0 2 1
A floor() 0 2 1
A asin() 0 2 1
A reciprocal() 0 3 1
A sin() 0 2 1
A modMatrix() 0 9 5
A setData() 0 8 6
A log1p() 0 2 1
A clip() 0 19 5
A clipLower() 0 9 3
A reshape() 0 7 2
A asArray() 0 6 2
A getSize() 0 2 1
A printVector() 0 5 2
A __toString() 0 2 1
A __construct() 0 6 2
A getDtype() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like vector often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use vector, and based on these observations, apply Extract Interface, too.

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);
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) {
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
     * @return vector
564
     */
565
    protected function powScalar(int|float $s): vector {
566
        $v = $this->copyVector();
567
        for ($i = 0; $i < $this->col; ++$i) {
568
            $v->data[$i] = $v->data[$i] ** $s;
569
        }
570
        return $v;
571
    }
572
573
    /**
574
     * 
575
     * @param int|float|\Np\matrix|\Np\vector $d
576
     * @return matrix|vector
577
     */
578
    public function mod(int|float|\Np\matrix|\Np\vector $d): matrix|vector {
579
        if ($d instanceof matrix) {
580
            return $this->powMatrix($d);
581
        } elseif ($d instanceof vector) {
582
            return $this->powVector($d);
583
        } else {
584
            return $this->powScalar($d);
585
        }
586
    }
587
588
    /**
589
     * 
590
     * @param \Np\matrix $m
591
     * @return matrix
592
     */
593
    protected function modMatrix(\Np\matrix $m): matrix {
594
        if ($this->checkDimensions($this, $m) && $this->checkDtype($this, $m)) {
595
            $ar = matrix::factory($m->row, $m->col, $this->dtype);
596
            for ($i = 0; $i < $m->row; ++$i) {
597
                for ($j = 0; $j < $m->col; ++$j) {
598
                    $ar->data[$i * $m->col + $j] = $m->data[$i * $m->col + $j] % $this->data[$j];
599
                }
600
            }
601
            return $ar;
602
        }
603
    }
604
605
    /**
606
     * 
607
     * @param \Np\vector $vector
608
     * @return vector
609
     */
610
    protected function modVector(\Np\vector $vector): vector {
611
        if ($this->checkShape($this, $vector) && $this->checkDtype($this, $vector)) {
612
            $vr = self::factory($this->col, $this->dtype);
613
            for ($i = 0; $i < $this->col; ++$i) {
614
                $vr->data[$i] = $this->data[$i] % $vector->data[$i];
615
            }
616
            return $vr;
617
        }
618
    }
619
620
    /**
621
     * 
622
     * @param int|float $s
623
     */
624
    protected function modScalar(int|float $s) {
625
        $v = $this->copyVector();
626
        for ($i = 0; $i < $this->col; ++$i) {
627
            $v->data[$i] = $v->data[$i] % $s;
628
        }
629
    }
630
631
    /**
632
     * 
633
     * @param int|float|matrix|vector $d
634
     * @return matrix|vector
635
     */
636
    public function subtract(int|float|matrix|vector $d): matrix|vector {
637
        if ($d instanceof matrix) {
638
            return $this->subtractMatrix($d);
639
        } elseif ($d instanceof self) {
640
            return $this->subtractVector($d);
641
        } else {
642
            return $this->substractScalar($d);
643
        }
644
    }
645
646
    /**
647
     * 
648
     * @param \Np\matrix $m
649
     * @return matrix
650
     */
651
    protected function subtractMatrix(\Np\matrix $m): matrix {
652
        if ($this->checkShape($this, $m) && $this->checkDtype($this, $m)) {
653
            $vr = matrix::factory($m->row, $m->col, $m->dtype);
654
            for ($i = 0; $i < $m->row; ++$i) {
655
                for ($j = 0; $j < $m->col; ++$j) {
656
                    $vr->data[$i * $m->col + $j] = $this->data[$j] - $m->data[$i * $m->col + $j];
657
                }
658
            }
659
            return $vr;
660
        }
661
    }
662
663
    /**
664
     * 
665
     * @param \Np\vector $vector
666
     * @return vector
667
     */
668
    protected function subtractVector(\Np\vector $vector): vector {
669
        if ($this->checkShape($this, $vector) && $this->checkDtype($this, $vector)) {
670
            $vr = self::factory($this->col, $this->dtype);
671
            for ($i = 0; $i < $this->col; ++$i) {
672
                $vr->data[$i] = $this->data[$i] - $vector->data[$i];
673
            }
674
            return $vr;
675
        }
676
    }
677
678
    /**
679
     * 
680
     * @param \Np\vector $scalar
681
     * @return \Np\vector
682
     */
683
    protected function substractScalar(int|float $scalar): vector {
684
        $vr = self::factory($this->col, $this->dtype);
685
        for ($i = 0; $i < $this->col; ++$i) {
686
            $vr->data[$i] = $this->data[$i] - $scalar;
687
        }
688
        return $vr;
689
    }
690
691
    /**
692
     * 
693
     * @param \Np\vector $v
694
     * @param int $stride
695
     * @return vector
696
     */
697
    public function convolve(\Np\vector $v, int $stride = 1): vector {
698
        return convolve::conv1D($this, $v, $stride);
699
    }
700
701
    /**
702
     * Run a function over all of the elements in the vector. 
703
     * 
704
     * @param callable $func
705
     * @return vector
706
     */
707
    public function map(callable $func): vector {
708
        $vr = self::factory($this->col, $this->dtype);
709
        for ($i = 0; $i < $this->col; ++$i) {
710
            $vr->data[$i] = $func($this->data[$i]);
711
        }
712
        return $vr;
713
    }
714
715
    public function log(float $b = M_E): vector {
716
        $vr = $this->copyVector();
717
        for ($i = 0; $i < $vr->col; ++$i) {
718
            log($vr->data[$i], $b);
719
        }
720
        return $vr;
721
    }
722
723
    public function max() {
724
        return $this->data[blas::max($this)];
725
    }
726
727
    public function min() {
728
        $this->data[blas::min($this)];
729
    }
730
731
    public function abs(): vector {
732
        return $this->map('abs');
733
    }
734
735
    public function sqrt(): vector {
736
        return $this->map('sqrt');
737
    }
738
739
    public function exp(): vector {
740
        return $this->map('exp');
741
    }
742
743
    public function exp1(): vector {
744
        return $this->map('exp1');
745
    }
746
747
    public function log1p(): vector {
748
        return $this->map('log1p');
749
    }
750
751
    public function sin(): vector {
752
        return $this->map('sin');
753
    }
754
755
    public function asin(): vector {
756
        return $this->map('asin');
757
    }
758
759
    public function cos(): vector {
760
        return $this->map('cos');
761
    }
762
763
    public function acos(): vector {
764
        return $this->map('acos');
765
    }
766
767
    public function tan(): vector {
768
        return $this->map('tan');
769
    }
770
771
    public function atan(): vector {
772
        return $this->map('atan');
773
    }
774
775
    public function radToDeg(): vector {
776
        return $this->map('rad2deg');
777
    }
778
779
    public function degToRad(): vector {
780
        return $this->map('deg2rad');
781
    }
782
783
    public function floor(): vector {
784
        return $this->map('floor');
785
    }
786
787
    public function ceil(): vector {
788
        return $this->map('ceil');
789
    }
790
    
791
    /**
792
     * 
793
     * @param float $min
794
     * @param float $max
795
     * @return vector
796
     */
797
    public function clip(float $min, float $max) : vector {
798
        if ($min > $max) {
799
            self::_invalidArgument('Minimum cannot be greater than maximum.');
800
        }
801
802
        $vr = self::factory($this->col, $this->dtype);
803
        
804
        for($i = 0; $i < $this->col; ++$i) {
805
            if ($this->data[$i] > $max) {
806
                $vr->data[$i] = $max;
807
                continue;
808
            }
809
            if ($this->data[$i] < $min) {
810
                $vr->data[$i] = $min;
811
                continue;
812
            }
813
        }
814
815
        return $vr;
816
    }
817
    
818
    public function clipUpper(float $min) : vector {
819
        $vr = self::factory($this->col, $this->dtype);
820
        for($i = 0; $i < $this->col; ++$i) {
821
            if ($this->data[$i] > $min) {
822
                $vr->data[$i] = $min;
823
                continue;
824
            }
825
        }
826
        return $vr;
827
    }
828
    
829
    public function clipLower(float $min) : vector {
830
        $vr = self::factory($this->col, $this->dtype);
831
        for($i = 0; $i < $this->col; ++$i) {
832
            if ($this->data[$i] < $min) {
833
                $vr->data[$i] = $min;
834
                continue;
835
            }
836
        }
837
        return $vr;
838
    }
839
    
840
    /**
841
     * Return the inner product of two vectors.
842
     *
843
     * @param \Np\vector $vector
844
     * 
845
     */
846
    public function inner(\Np\vector $vector) {
847
        return $this->dotVector($vector);
848
    }
849
850
    /**
851
     * Calculate the L1 norm of the vector.
852
     * @return float
853
     */
854
    public function normL1(): float {
855
        return $this->abs()->sum();
856
    }
857
858
    public function normL2() {
859
        return sqrt($this->square()->sum());
860
    }
861
862
    public function normMax() {
863
        return $this->abs()->max();
864
    }
865
866
    public function normP(float $p = 2.5) {
867
        if ($p <= 0.0) {
868
            self::_invalidArgument('P must be greater than 0.0 !');
869
        }
870
        return $this->abs()->powScalar($p)->sum() ** (1.0 / $p);
871
    }
872
873
    /**
874
     * Return the reciprocal of the vector element-wise.
875
     *
876
     * @return self
877
     */
878
    public function reciprocal(): vector {
879
        return self::ones($this->col, $this->dtype)
880
                        ->divideVector($this);
881
    }
882
    
883
    /**
884
     * 
885
     * @return int|float
886
     */
887
    public function mean():int|float {
888
        return $this->sum()/ $this->col;
889
    }
890
    
891
    /**
892
     * 
893
     * @return int|float
894
     */
895
    public function median():int|float {
896
        $mid = intdiv($this->col, 2);
897
898
        $a = $this->copyVector()->sort();
899
        if ($this->col % 2 === 1) {
900
            $median = $a->data[$mid];
901
        } else {
902
            $median = ($a->data[$mid - 1] + $a->data[$mid]) / 2.;
903
        }
904
        return $median;
905
    }
906
    
907
    public function variance($mean = null)
908
    {
909
        if (is_null($mean)) {
910
            $mean = $this->mean();
911
        }
912
913
        $sd = $this->substractScalar($mean)
914
            ->square()
915
            ->sum();
916
917
        return $sd / $this->col;
918
    }
919
920
    /**
921
     * 
922
     * @return vector
923
     */
924
    public function square(): vector {
925
        return $this->multiplyVector($this);
926
    }
927
928
    /**
929
     * sort the vector 
930
     * @param string $type i or d
931
     * 
932
     */
933
    public function sort($type = 'i') {
934
        lapack::sort($this, $type);
935
        return $this;
936
    }
937
938
    /**
939
     * set data to vector
940
     * @param int|float|array $data
941
     */
942
    public function setData(int|float|array $data) {
943
        if (is_array($data) && !is_array($data[0])) {
944
            for ($i = 0; $i < $this->col; ++$i) {
945
                $this->data[$i] = $data[$i];
946
            }
947
        } elseif (is_numeric($data)) {
948
            for ($i = 0; $i < $this->col; ++$i) {
949
                $this->data[$i] = $data;
950
            }
951
        }
952
    }
953
954
    /**
955
     * Return a matrix in the shape specified.
956
     * @param int $row
957
     * @param int $col
958
     * @return matrix
959
     */
960
    public function reshape(int $row, int $col): matrix {
961
        if($this->col != $row * $col) {
962
            self::_dimensionaMisMatchErr('given dimenssion is not valid for current bufferData');
963
        }
964
        $ar = matrix::factory($row, $col, $this->dtype);
965
        $ar->data = $this->data;
966
        return $ar;
967
    }
968
969
    /**
970
     * get the size of vector
971
     * @return int
972
     */
973
    public function getSize(): int {
974
        return $this->col;
975
    }
976
977
    public function getDtype() {
978
        return $this->dtype;
979
    }
980
981
    public function asArray() {
982
        $ar = array_fill(0, $this->col, null);
983
        for ($i = 0; $i < $this->col; ++$i) {
984
            $ar[$i] = $this->data[$i];
985
        }
986
        return $ar;
987
    }
988
989
    public function printVector() {
990
        for ($j = 0; $j < $this->col; ++$j) {
991
            printf('%lf  ', $this->data[$j]);
992
        }
993
        echo PHP_EOL;
994
    }
995
996
    public function __toString() {
997
        return (string) $this->printVector();
998
    }
999
1000
    protected function __construct(public int $col, int $dtype = self::FLOAT) {
1001
        if ($this->col < 1) {
1002
            throw new invalidArgumentException('* To create Numphp/Vector col must be greater than 0!, Op Failed! * ');
1003
        }
1004
        parent::__construct($this->col, $dtype);
1005
        return $this;
1006
    }
1007
1008
}
1009