Skip to content

Commit 96ac716

Browse files
author
MarkBaker
committed
Fix sizing adjustments for reflective matrices (vectors increase to match as a square matrix, non-vectors reduce to a minimum matching square)
1 parent 53aab72 commit 96ac716

File tree

4 files changed

+78
-81
lines changed

4 files changed

+78
-81
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -60,26 +60,6 @@ parameters:
6060
count: 6
6161
path: src/PhpSpreadsheet/Calculation/Calculation.php
6262

63-
-
64-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:_translateFormulaToEnglish\\(\\) has no return type specified\\.$#"
65-
count: 1
66-
path: src/PhpSpreadsheet/Calculation/Calculation.php
67-
68-
-
69-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:_translateFormulaToEnglish\\(\\) has parameter \\$formula with no type specified\\.$#"
70-
count: 1
71-
path: src/PhpSpreadsheet/Calculation/Calculation.php
72-
73-
-
74-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:_translateFormulaToLocale\\(\\) has no return type specified\\.$#"
75-
count: 1
76-
path: src/PhpSpreadsheet/Calculation/Calculation.php
77-
78-
-
79-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:_translateFormulaToLocale\\(\\) has parameter \\$formula with no type specified\\.$#"
80-
count: 1
81-
path: src/PhpSpreadsheet/Calculation/Calculation.php
82-
8363
-
8464
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:dataTestReference\\(\\) has no return type specified\\.$#"
8565
count: 1
@@ -90,41 +70,11 @@ parameters:
9070
count: 1
9171
path: src/PhpSpreadsheet/Calculation/Calculation.php
9272

93-
-
94-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:getTokensAsString\\(\\) has no return type specified\\.$#"
95-
count: 1
96-
path: src/PhpSpreadsheet/Calculation/Calculation.php
97-
98-
-
99-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:getTokensAsString\\(\\) has parameter \\$tokens with no type specified\\.$#"
100-
count: 1
101-
path: src/PhpSpreadsheet/Calculation/Calculation.php
102-
103-
-
104-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:localeFunc\\(\\) has no return type specified\\.$#"
105-
count: 1
106-
path: src/PhpSpreadsheet/Calculation/Calculation.php
107-
108-
-
109-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:localeFunc\\(\\) has parameter \\$function with no type specified\\.$#"
110-
count: 1
111-
path: src/PhpSpreadsheet/Calculation/Calculation.php
112-
113-
-
114-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:validateBinaryOperand\\(\\) has no return type specified\\.$#"
115-
count: 1
116-
path: src/PhpSpreadsheet/Calculation/Calculation.php
117-
11873
-
11974
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:validateBinaryOperand\\(\\) has parameter \\$operand with no type specified\\.$#"
12075
count: 1
12176
path: src/PhpSpreadsheet/Calculation/Calculation.php
12277

123-
-
124-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Calculation\\:\\:validateBinaryOperand\\(\\) has parameter \\$stack with no type specified\\.$#"
125-
count: 1
126-
path: src/PhpSpreadsheet/Calculation/Calculation.php
127-
12878
-
12979
message: "#^Offset 'type' does not exist on array\\|null\\.$#"
13080
count: 3

src/PhpSpreadsheet/Calculation/Calculation.php

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2872,7 +2872,7 @@ public static function getFALSE(): string
28722872
*
28732873
* @return bool Success or failure
28742874
*/
2875-
public static function setArrayReturnType($returnType)
2875+
public static function setArrayReturnType(string $returnType): bool
28762876
{
28772877
if (
28782878
($returnType == self::RETURN_ARRAY_AS_VALUE) ||
@@ -2892,17 +2892,15 @@ public static function setArrayReturnType($returnType)
28922892
*
28932893
* @return string $returnType Array return type
28942894
*/
2895-
public static function getArrayReturnType()
2895+
public static function getArrayReturnType(): string
28962896
{
28972897
return self::$returnArrayAsType;
28982898
}
28992899

29002900
/**
29012901
* Is calculation caching enabled?
2902-
*
2903-
* @return bool
29042902
*/
2905-
public function getCalculationCacheEnabled()
2903+
public function getCalculationCacheEnabled(): bool
29062904
{
29072905
return $this->calculationCacheEnabled;
29082906
}
@@ -2944,10 +2942,8 @@ public function clearCalculationCache(): void
29442942

29452943
/**
29462944
* Clear calculation cache for a specified worksheet.
2947-
*
2948-
* @param string $worksheetName
29492945
*/
2950-
public function clearCalculationCacheForWorksheet($worksheetName): void
2946+
public function clearCalculationCacheForWorksheet(string $worksheetName): void
29512947
{
29522948
if (isset($this->calculationCache[$worksheetName])) {
29532949
unset($this->calculationCache[$worksheetName]);
@@ -2956,13 +2952,10 @@ public function clearCalculationCacheForWorksheet($worksheetName): void
29562952

29572953
/**
29582954
* Rename calculation cache for a specified worksheet.
2959-
*
2960-
* @param string $fromWorksheetName
2961-
* @param string $toWorksheetName
29622955
*/
2963-
public function renameCalculationCacheForWorksheet($fromWorksheetName, $toWorksheetName): void
2956+
public function renameCalculationCacheForWorksheet(?string $fromWorksheetName, string $toWorksheetName): void
29642957
{
2965-
if (isset($this->calculationCache[$fromWorksheetName])) {
2958+
if ($fromWorksheetName !== null && isset($this->calculationCache[$fromWorksheetName])) {
29662959
$this->calculationCache[$toWorksheetName] = &$this->calculationCache[$fromWorksheetName];
29672960
unset($this->calculationCache[$fromWorksheetName]);
29682961
}
@@ -2971,7 +2964,7 @@ public function renameCalculationCacheForWorksheet($fromWorksheetName, $toWorksh
29712964
/**
29722965
* Enable/disable calculation cache.
29732966
*
2974-
* @param mixed $enabled
2967+
* @param bool $enabled
29752968
*/
29762969
public function setBranchPruningEnabled($enabled): void
29772970
{
@@ -2991,10 +2984,8 @@ public function disableBranchPruning(): void
29912984

29922985
/**
29932986
* Get the currently defined locale code.
2994-
*
2995-
* @return string
29962987
*/
2997-
public function getLocale()
2988+
public function getLocale(): string
29982989
{
29992990
return self::$localeLanguage;
30002991
}
@@ -3018,10 +3009,8 @@ private function getLocaleFile(string $localeDir, string $locale, string $langua
30183009
* Set the locale code.
30193010
*
30203011
* @param string $locale The locale to use for formula translation, eg: 'en_us'
3021-
*
3022-
* @return bool
30233012
*/
3024-
public function setLocale(string $locale)
3013+
public function setLocale(string $locale): bool
30253014
{
30263015
// Identify our locale and language
30273016
$language = $locale = strtolower($locale);
@@ -3191,7 +3180,7 @@ private static function translateFormula(array $from, array $to, string $formula
31913180

31923181
private static $functionReplaceToLocale;
31933182

3194-
public function _translateFormulaToLocale($formula)
3183+
public function _translateFormulaToLocale(string $formula): string
31953184
{
31963185
// Build list of function names and constants for translation
31973186
if (self::$functionReplaceFromExcel === null) {
@@ -3227,7 +3216,7 @@ public function _translateFormulaToLocale($formula)
32273216

32283217
private static $functionReplaceToExcel;
32293218

3230-
public function _translateFormulaToEnglish($formula)
3219+
public function _translateFormulaToEnglish(string $formula): string
32313220
{
32323221
if (self::$functionReplaceFromLocale === null) {
32333222
self::$functionReplaceFromLocale = [];
@@ -3252,7 +3241,7 @@ public function _translateFormulaToEnglish($formula)
32523241
return self::translateFormula(self::$functionReplaceFromLocale, self::$functionReplaceToExcel, $formula, self::$localeArgumentSeparator, ',');
32533242
}
32543243

3255-
public static function localeFunc($function)
3244+
public static function localeFunc(string $function): string
32563245
{
32573246
if (self::$localeLanguage !== 'en_us') {
32583247
$functionName = trim($function, '(');
@@ -3596,7 +3585,7 @@ public function _calculateFormulaValue($formula, $cellID = null, ?Cell $cell = n
35963585
* 1 = shrink to fit
35973586
* 2 = extend to fit
35983587
*
3599-
* @return array
3588+
* @return array<int, int>
36003589
*/
36013590
private static function checkMatrixOperands(&$operand1, &$operand2, $resize = 1)
36023591
{
@@ -3615,7 +3604,9 @@ private static function checkMatrixOperands(&$operand1, &$operand2, $resize = 1)
36153604
[$matrix1Rows, $matrix1Columns] = self::getMatrixDimensions($operand1);
36163605
[$matrix2Rows, $matrix2Columns] = self::getMatrixDimensions($operand2);
36173606
if (($matrix1Rows == $matrix2Columns) && ($matrix2Rows == $matrix1Columns)) {
3618-
$resize = 2;
3607+
// Vectors increase size to match to build a square matrix;
3608+
// Non-vectors reduce size to a square that reflects min(rows1, rows2) and min(cols1, cols2)
3609+
$resize = ($matrix1Rows === 1 || $matrix2Rows === 1) ? 2 : 1;
36193610
}
36203611

36213612
if ($resize == 2) {
@@ -3634,7 +3625,7 @@ private static function checkMatrixOperands(&$operand1, &$operand2, $resize = 1)
36343625
*
36353626
* @param array $matrix matrix operand
36363627
*
3637-
* @return int[] An array comprising the number of rows, and number of columns
3628+
* @return array<int, int> An array comprising the number of rows, and number of columns
36383629
*/
36393630
public static function getMatrixDimensions(array &$matrix)
36403631
{
@@ -3747,7 +3738,7 @@ private static function resizeMatricesExtend(&$matrix1, &$matrix2, $matrix1Rows,
37473738
/**
37483739
* Format details of an operand for display in the log (based on operand type).
37493740
*
3750-
* @param mixed $value First matrix operand
3741+
* @param mixed $value Operand value
37513742
*
37523743
* @return mixed
37533744
*/
@@ -3787,7 +3778,7 @@ private function showValue($value)
37873778
/**
37883779
* Format type and details of an operand for display in the log (based on operand type).
37893780
*
3790-
* @param mixed $value First matrix operand
3781+
* @param mixed $value Operand value
37913782
*
37923783
* @return null|string
37933784
*/
@@ -4889,7 +4880,7 @@ private function processTokenStack($tokens, $cellID = null, ?Cell $cell = null)
48894880
return $output;
48904881
}
48914882

4892-
private function validateBinaryOperand(&$operand, &$stack)
4883+
private function validateBinaryOperand(&$operand, Stack &$stack): bool
48934884
{
48944885
if (is_array($operand)) {
48954886
if ((count($operand, COUNT_RECURSIVE) - count($operand)) == 1) {
@@ -5357,7 +5348,7 @@ private function addCellReference(array $args, $passCellReference, $functionCall
53575348
return $args;
53585349
}
53595350

5360-
private function getTokensAsString($tokens)
5351+
private function getTokensAsString(array $tokens): string
53615352
{
53625353
$tokensStr = array_map(function ($token) {
53635354
$value = $token['value'] ?? 'no value';

src/PhpSpreadsheet/Worksheet/Worksheet.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ public function getTitle()
839839
*
840840
* @return $this
841841
*/
842-
public function setTitle($title, $updateFormulaCellReferences = true, $validate = true)
842+
public function setTitle(string $title, bool $updateFormulaCellReferences = true, bool $validate = true)
843843
{
844844
// Is this a 'rename' or not?
845845
if ($this->getTitle() == $title) {

tests/PhpSpreadsheetTests/Calculation/ArrayFormulaTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,14 @@ public function providerArrayArithmetic(): array
125125
'={1,4;2,5;3,6} + {7,10;8,11;9,12}',
126126
[[8, 14], [10, 16], [12, 18]],
127127
],
128+
'Addition: matrix 3x2 + 2x3' => [
129+
'={1,2,3;4,5,6} + {7,10;8,11;9,12}',
130+
[[8, 12], [12, 16]],
131+
],
132+
'Addition: matrix 2x3 + 3x2' => [
133+
'={7,10;8,11;9,12} + {1,2,3;4,5,6}',
134+
[[8, 12], [12, 16]],
135+
],
128136
// Subtraction
129137
'Subtraction: row vector 2 - column vector 2' => [
130138
'={2,3} - {4;5}',
@@ -162,6 +170,14 @@ public function providerArrayArithmetic(): array
162170
'={1,4;2,5;3,6} - {7,10;8,11;9,12}',
163171
[[-6, -6], [-6, -6], [-6, -6]],
164172
],
173+
'Subtraction: matrix 3x2 - 2x3' => [
174+
'={1,2,3;4,5,6} - {7,10;8,11;9,12}',
175+
[[-6, -8], [-4, -6]],
176+
],
177+
'Subtraction: matrix 2x3 - 3x2' => [
178+
'={7,10;8,11;9,12} - {1,2,3;4,5,6}',
179+
[[6, 8], [4, 6]],
180+
],
165181
// Multiplication
166182
'Multiplication: square matrix 2x2 * 2x2' => [
167183
'={1,2;3,4} * {-2,4;-6,8}',
@@ -199,6 +215,14 @@ public function providerArrayArithmetic(): array
199215
'={2,3} * {4;5}',
200216
[[8, 12], [10, 15]],
201217
],
218+
'Multiplication: matrix 3x2 * 2x3' => [
219+
'={1,2,3;4,5,6} * {7,10;8,11;9,12}',
220+
[[7, 20], [32, 55]],
221+
],
222+
'Multiplication: matrix 2x3 * 3x2' => [
223+
'={7,10;8,11;9,12} * {1,2,3;4,5,6}',
224+
[[7, 20], [32, 55]],
225+
],
202226
// Division
203227
'Division: square matrix 2x2 / 2x2' => [
204228
'={1,2;3,4} / {-2,4;-6,8}',
@@ -236,6 +260,14 @@ public function providerArrayArithmetic(): array
236260
'={2,3} / {4;5}',
237261
[[0.5, 0.75], [0.4, 0.6]],
238262
],
263+
'Division: matrix 3x2 / 2x3' => [
264+
'={1,2,3;4,5,6} / {7,10;8,11;9,12}',
265+
[[0.14285714285714, 0.2], [0.5, 0.45454545454545]],
266+
],
267+
'Division: matrix 2x3 / 3x2' => [
268+
'={7,10;8,11;9,12} / {1,2,3;4,5,6}',
269+
[[7, 5], [2, 2.2]],
270+
],
239271
// Power
240272
'Power: square matrix 2x2 ^ 2x2' => [
241273
'={1,2;3,4} ^ {-2,4;-6,8}',
@@ -273,11 +305,27 @@ public function providerArrayArithmetic(): array
273305
'={2,3} ^ {4;5}',
274306
[[16, 81], [32, 243]],
275307
],
308+
'Power: matrix 3x2 ^ 2x3' => [
309+
'={1,2,3;4,5,6} ^ {7,10;8,11;9,12}',
310+
[[1, 1024], [65536, 48828125]],
311+
],
312+
'Power: matrix 2x3 ^ 3x2' => [
313+
'={7,10;8,11;9,12} ^ {1,2,3;4,5,6}',
314+
[[7, 100], [4096, 161051]],
315+
],
276316
// Concatenation
277317
'Concatenation: row vector 2 & column vector 2' => [
278318
'={"A",",B"} & {"C";";D"}',
279319
[['AC', ',BC'], ['A;D', ',B;D']],
280320
],
321+
'Concatenation: matrix 3x2 & 3x2' => [
322+
'={"A","B","C";"D","E","F"} & {"G","H","I";"J","K","L"}',
323+
[['AG', 'BH', 'CI'], ['DJ', 'EK', 'FL']],
324+
],
325+
'Concatenation: matrix 2x3 & 2x3' => [
326+
'={"A","B";"C","D";"E","F"} & {"G","H";"I","J";"K","L"}',
327+
[['AG', 'BH'], ['CI', 'DJ'], ['EK', 'FL']],
328+
],
281329
'Concatenation: 2x2 matrix & scalar' => [
282330
'={"A","B";"C","D"} & "E"',
283331
[['AE', 'BE'], ['CE', 'DE']],
@@ -286,6 +334,14 @@ public function providerArrayArithmetic(): array
286334
'="E" & {"A","B";"C","D"}',
287335
[['EA', 'EB'], ['EC', 'ED']],
288336
],
337+
'Concatenation: 2x2 & 2x1 vector' => [
338+
'={"A","B";"C","D"} & {"E","F"}',
339+
[['AE', 'BF'], ['CE', 'DF']],
340+
],
341+
'Concatenation: 2x2 & 1x2 vector' => [
342+
'={"A","B";"C","D"} & {"E";"F"}',
343+
[['AE', 'BE'], ['CF', 'DF']],
344+
],
289345

290346
// Unary Negation
291347
'Unary Negation: square matrix - 2x2' => [

0 commit comments

Comments
 (0)