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

 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.08% covered (success)
98.08%
51 / 52
90.91% covered (success)
90.91%
10 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
NumArrayTrait
98.08% covered (success)
98.08%
51 / 52
90.91% covered (success)
90.91%
10 / 11
20
0.00% covered (danger)
0.00%
0 / 1
 zeros
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 ones
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 nulls
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 full
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 createArray
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
2.03
 nulls_like
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 zeros_like
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 ones_like
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 full_like
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 broadcast_to
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 can_broadcast_to
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
7
1 <?php
2
3 declare(strict_types=1);
4
5 namespace SciPhp\NumPhp;
6
7 use SciPhp\Exception\Message;
8 use SciPhp\NdArray;
9 use Webmozart\Assert\Assert;
10
11 trait NumArrayTrait
12 {
13     /**
14      * Creates a NdArray with zero as default value
15      *
16      * @link http://sciphp.org/numphp.zeros
17      *    Documentation for zeros()
18      *
19      * @api
20      */
21     final public static function zeros(): NdArray
22     {
23         return self::full(
24             static::parseArgs(func_get_args()), 0
25         );
26     }
27
28     /**
29      * Creates a NdArray with one as default value
30      *
31      * @link http://sciphp.org/numphp.ones
32      *    Documentation for ones()
33      *
34      * @api
35      */
36     final public static function ones(): NdArray
37     {
38         return self::full(
39             static::parseArgs(func_get_args()), 1
40         );
41     }
42
43     /**
44      * Creates a NdArray with null as default value
45      * 'empty' can not be used in PHP
46      *
47      * @link http://sciphp.org/numphp.nulls
48      *    Documentation for nulls()
49      *
50      * @api
51      */
52     final public static function nulls(): NdArray
53     {
54         return self::full(
55             static::parseArgs(func_get_args()), null
56         );
57     }
58
59     /**
60      * Creates a NdArray with a default value
61      *
62      * @param  array $shape
63      * @param  mixed $value
64      *
65      * @link http://sciphp.org/numphp.full
66      *    Documentation for full()
67      *
68      * @api
69      */
70     final public static function full(array $shape, $value): NdArray
71     {
72         Assert::allInteger($shape);
73         Assert::allGreaterThan($shape, 0);
74
75         return static::ar(
76             self::createArray($shape, $value)
77         );
78     }
79
80     /**
81      * Construct a n-dim array with a default value
82      *
83      * @param  array $params
84      * @param  mixed $value
85      * @return mixed|array
86      */
87     final protected static function createArray(array $params, $value)
88     {
89         return isset($params[0])
90             ? array_fill(
91                     0,
92                     array_shift($params),
93                     self::createArray($params, $value)
94             ) : $value;
95     }
96
97     /**
98      * Construct a new array of nulls with the same shape and type
99      * as a given array.
100      *
101      * @param  array|\SciPhp\NdArray $matrix
102      *
103      * @link http://sciphp.org/numphp.nulls_like
104      *    Documentation for nulls_like()
105      *
106      * @api
107      */
108     final public static function nulls_like($matrix): NdArray
109     {
110         return self::full_like($matrix, null);
111     }
112
113     /**
114      * Construct a new array of zeros with the same shape and type
115      * as a given array.
116      *
117      * @param  array|\SciPhp\NdArray $matrix
118      *
119      * @link http://sciphp.org/numphp.zeros_like
120      *    Documentation for zeros_like()
121      *
122      * @api
123      */
124     final public static function zeros_like($matrix): NdArray
125     {
126         return self::full_like($matrix, 0);
127     }
128
129     /**
130      * Construct a new array of ones with the same shape and type
131      * as a given array.
132      *
133      * @param  array|\SciPhp\NdArray $matrix
134      *
135      * @link http://sciphp.org/numphp.ones_like
136      *    Documentation for ones_like()
137      *
138      * @api
139      */
140     final public static function ones_like($matrix): NdArray
141     {
142         return self::full_like($matrix, 1);
143     }
144
145     /**
146      * Construct a new array with the same shape and type as a given array,
147      * filled with a given value
148      *
149      * @param  array|\SciPhp\NdArray $matrix
150      *
151      * @link http://sciphp.org/numphp.full_like
152      *    Documentation for full_like()
153      *
154      * @api
155      */
156     final public static function full_like($matrix, $value = null): NdArray
157     {
158         if (\is_array($matrix)) {
159             $matrix = static::ar($matrix);
160         }
161
162         Assert::isInstanceOf($matrix, '\SciPhp\NdArray');
163
164         return self::full($matrix->shape, $value);
165     }
166
167     /**
168      * Broadcast an array to a new shape.
169      *
170      * @param  array|\SciPhp\NdArray $matrix
171      * @param  array $shape
172      *
173      * @link http://sciphp.org/numphp.broadcast_to
174      *    Documentation for broadcast_to()
175      *
176      * @since 0.3.0
177      * @api
178      */
179     final public static function broadcast_to($matrix, array $shape): NdArray
180     {
181         static::transform($matrix, true);
182
183         // Is broadcast allowed?
184         self::can_broadcast_to($matrix, $shape);
185
186         // 1 dim -> 2 dim
187         if ($matrix->ndim === 1) {
188             return $matrix->resize($shape);
189         }
190
191         $m = self::zeros($shape);
192
193         $row = 0;
194         $func = static function ($value) use (&$m, &$row): void {
195             $m["{$row}, :"] = $value;
196             $row++;
197         };
198
199         $matrix->walk_recursive($func);
200
201         return $m;
202     }
203
204     /**
205      * Checks that an array can be broadcast to a given shape
206      *
207      * @param  NdArray $m
208      * @param  array   $shape
209      * @throws \InvalidArgumentException when broadcast cannot be done
210      */
211     private static function can_broadcast_to(NdArray $m, array $shape): void
212     {
213         if (count($shape) > 2) {
214             throw new \InvalidArgumentException(
215                 Message::ARRAYS_BROADCAST_NDIM2_ONLY
216             );
217         }
218
219         if ($m->ndim > 2) {
220             throw new \InvalidArgumentException(
221                 Message::ARRAYS_BROADCAST_NDIM2_ONLY
222             );
223         }
224
225         $shape_m = $m->shape;
226         $m_index = $m->ndim;
227
228         $countShape = count($shape) - 1;
229         for ($i = $countShape; $i >= 0; $i--) {
230             $m_index--;
231             if (! isset($shape_m[$m_index])) {
232                 continue;
233             }
234             if ($shape[$i] === $shape_m[$m_index]) {
235                 continue;
236             }
237             if ($shape_m[$m_index] === 1) {
238                 continue;
239             }
240
241             $message = sprintf(
242                 Message::ARRAYS_BROADCAST_IMPOSSIBLE,
243                 trim(strval(static::ar($m->shape))),
244                 trim(strval(static::ar($shape)))
245             );
246
247             throw new \InvalidArgumentException($message);
248         }
249     }
250 }