Code Coverage for /src/SciPhp/NumPhp/FloatTrait.php

 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
FloatTrait
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
2 / 2
15
100.00% covered (success)
100.00%
1 / 1
 signbit
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 copysign
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
13
1 <?php
2
3 declare(strict_types=1);
4
5 namespace SciPhp\NumPhp;
6
7 use RecursiveArrayIterator;
8 use RecursiveIteratorIterator;
9 use SciPhp\Exception\Message;
10 use SciPhp\NdArray;
11 use SciPhp\NumPhp as np;
12 use Webmozart\Assert\Assert;
13
14 /**
15  * Floating point methods
16  */
17 trait FloatTrait
18 {
19     /**
20      * Returns element-wise true where signbit is set (less than zero).
21      *
22      * @param  \SciPhp\NdArray|array|int|float $m
23      * @return \SciPhp\NdArray|bool
24      * @link http://sciphp.org/numphp.signbit Documentation
25      * @api
26      */
27     final public static function signbit($m)
28     {
29         if (is_numeric($m)) {
30             return $m < 0;
31         }
32
33         static::transform($m, true);
34
35         $func = static function (&$element): void {
36             $element = $element < 0;
37         };
38
39         return $m->copy()->walk_recursive($func);
40     }
41
42     /**
43      * Change the sign of m-element to that of n-element, element-wise.
44      *
45      * @param  \SciPhp\NdArray|array|int|float $m
46      * @param  \SciPhp\NdArray|array|int|float $n
47      * @return \SciPhp\NdArray|int|float
48      * @link http://sciphp.org/numphp.copysign Documentation
49      * @api
50      */
51     final public static function copysign($m, $n)
52     {
53         if (static::allNumeric($m, $n)) {
54             return np::signbit($m) === np::signbit($n)
55                 ? $m : -$m;
56         }
57
58         static::transform($m);
59         static::transform($n);
60
61         // array / lamba
62         if (is_numeric($n) && $m instanceof NdArray) {
63             return $m->copysign(static::full_like($m, $n));
64             // return np::copysign($n, $m); //$m->copy()->copysign($n);
65         }
66
67         // lamba / array
68         if (is_numeric($m) && $n instanceof NdArray) {
69             return static::full_like($n, $m)->copysign($n);
70         }
71
72         // array / array
73         Assert::isInstanceof($m, NdArray::class);
74         Assert::isInstanceof($n, NdArray::class);
75
76         // n & m are vectors:
77         if (count($m->shape) === 1 && $m->ndim === $n->ndim) {
78             Assert::eq($m->shape, $n->shape, Message::MAT_NOT_ALIGNED);
79         }
80
81         // n is a vector
82         elseif (!isset($n->shape[1])) {
83             Assert::eq($m->shape[1], $n->shape[0], Message::MAT_NOT_ALIGNED);
84         }
85
86         // m is a vector
87         elseif (!isset($m->shape[1])) {
88             Assert::eq($m->shape[0], $n->shape[1], Message::MAT_NOT_ALIGNED);
89
90             $m = $m->resize($n->shape);
91         }
92
93         // array / array
94         elseif ($m->ndim === $n->ndim) {
95             Assert::eq($m->shape, $n->shape, Message::MAT_NOT_ALIGNED);
96         }
97
98         $iterator = new RecursiveIteratorIterator(
99             new RecursiveArrayIterator($n->data),
100             RecursiveIteratorIterator::LEAVES_ONLY
101         );
102
103         $func = static function(&$item) use (&$iterator, $n): void {
104             if (np::signbit($item) !== np::signbit($n->iterate($iterator))) {
105                 $item = -$item;
106             }
107         };
108
109         return $m->copy()->walk_recursive($func);
110     }
111 }