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

 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.16% covered (success)
95.16%
59 / 62
50.00% covered (danger)
50.00%
3 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
TriangleTrait
95.16% covered (success)
95.16%
59 / 62
50.00% covered (danger)
50.00%
3 / 6
22
0.00% covered (danger)
0.00%
0 / 1
 triu
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
3.01
 itemTriu
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 tril
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
3.01
 itemTril
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 tri
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
3.01
 itemTri
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
1 <?php
2
3 declare(strict_types=1);
4
5 namespace SciPhp\NumPhp;
6
7 use SciPhp\NdArray;
8 use Webmozart\Assert\Assert;
9
10 trait TriangleTrait
11 {
12     /**
13      * Upper triangle of an array
14      *
15      * @param  \SciPhp\NdArray|array $m
16      * @param  int $k Offset
17      * @link http://sciphp.org/numphp.triu Documentation
18      * @api
19      */
20     final public static function triu($m, $k = 0): NdArray
21     {
22         Assert::integer($k);
23
24         static::transform($m, true);
25
26         if (!isset($m->data[0])) {
27             return static::ar([[]]);
28         }
29
30         $col = $k > 0
31             ? $k
32             : 0;
33         $count = count($m->data[0]);
34
35         return static::ar(
36             array_map(
37                 self::itemTriu($col, $k, $count),
38                 $m->data
39             )
40         );
41     }
42
43     /**
44      * Fill zeros from first item to a position
45      *
46      * @param  int $col Stop column position
47      * @param  int $k   Offset
48      * @param  int $count Max column position
49      * @param  int $line Start line for negative offsets
50      */
51     final protected static function itemTriu($col, $k, $count, $line = 1): callable
52     {
53         return static function($item) use (&$col, &$line, $k, $count) {
54             if ($k >= 0 || ($k < 0 && $line++ > -$k)) {
55                 $num = $col++;
56             }
57
58             if (isset($num)) {
59                 return array_replace(
60                     $item,
61                     array_fill(0, min($num, $count), 0)
62                 );
63             }
64
65             return $item;
66         };
67     }
68
69     /**
70      * Lower triangle of an array
71      *
72      * @param  \SciPhp\NdArray|array $m
73      * @param  int $k Offset
74      * @link http://sciphp.org/numphp.tril Documentation
75      * @api
76      */
77     final public static function tril($m, $k = 0): NdArray
78     {
79         Assert::integer($k);
80
81         static::transform($m, true);
82
83         if (! isset($m->data[0])) {
84             return static::ar([[]]);
85         }
86
87         $col = $k > 0
88             ? $k
89             : 0;
90         $count = count($m->data[0]);
91
92         return static::ar(
93             array_map(
94                 self::itemTril($col, $k, $count),
95                 $m->data
96             )
97         );
98     }
99
100     /**
101      * Fill zeros from a position to the end of the array
102      *
103      * @param  int $col Start column position
104      * @param  int $k   Offset
105      * @param  int $count Last column position
106      * @param  int $line Start line for negative offsets
107      */
108     final protected static function itemTril($col, $k, $count, $line = 1): callable
109     {
110         return static function($item) use (&$col, &$line, $k, $count) {
111             if ($k >= 0) {
112                 $col++;
113                 $num = $count - $col;
114             } else {
115                 if ($line > -$k) {
116                     $col++;
117                     $num = $count - $col;
118                 } else {
119                     $num = $count;
120                 }
121                 $line++;
122             }
123
124             if ($num > 0) {
125                 return array_replace(
126                     $item,
127                     array_fill($col, $num, 0)
128                 );
129             }
130
131             return $item;
132         };
133     }
134
135     /**
136      * Construct an array with ones at and below the given diagonal
137      * and zeros elsewhere
138      *
139      * @param  int $rows Number of rows
140      * @param  int $cols Number of columns
141      * @param  int $k Offset
142      * @link http://sciphp.org/numphp.tri Documentation
143      * @api
144      */
145     final public static function tri($rows, $cols = null, $k = 0): NdArray
146     {
147         Assert::integer($rows);
148         Assert::greaterThan($rows, 0);
149
150         if (is_null($cols)) {
151             $cols = $rows;
152         }
153
154         Assert::integer($cols);
155         Assert::greaterThan($cols, 0);
156
157         Assert::integer($k);
158
159         $col = $k > 0 ? $k : 0;
160
161         return static::ar(
162             array_map(
163                 self::itemTri($col, $k, $cols),
164                 static::zeros($rows, $cols)->data
165             )
166         );
167     }
168
169     /**
170      * Return a closure that fill a line item with ones
171      *
172      * @param int $col Position until which filling is done
173      * @param int $k Offset
174      * @param int $maxCols Max position to fill
175      * @param int $line Start at this line if offset is negative
176      */
177     final protected static function itemTri(int $col, int $k, int $maxCols, ?int $line = 1): callable
178     {
179         return static function($item) use (&$line, &$col, $k, $maxCols) {
180             if ($k >= 0 || ($k < 0 && $line++ > -$k)) {
181                 $num = min(++$col, $maxCols);
182
183                 return array_replace(
184                     $item,
185                     array_fill(0, $num, 1)
186                 );
187             }
188
189             return $item;
190         };
191     }
192 }