@@ -22,12 +22,12 @@ class Ceiling
2222 * Excel Function:
2323 * CEILING(number[,significance])
2424 *
25- * @param array|float $number the number you want the ceiling
25+ * @param array<mixed> |float $number the number you want the ceiling
2626 * Or can be an array of values
27- * @param array|float $significance the multiple to which you want to round
27+ * @param array<mixed> |float $significance the multiple to which you want to round
2828 * Or can be an array of values
2929 *
30- * @return array|float|string Rounded Number, or a string containing an error
30+ * @return array<mixed> |float|string Rounded Number, or a string containing an error
3131 * If an array of numbers is passed as an argument, then the returned result will also be an array
3232 * with the same dimensions
3333 */
@@ -63,14 +63,14 @@ public static function ceiling($number, $significance = null)
6363 * Or can be an array of values
6464 * @param mixed $significance Significance
6565 * Or can be an array of values
66- * @param array|int $mode direction to round negative numbers
66+ * @param array<mixed> |int $mode direction to round negative numbers
6767 * Or can be an array of values
6868 *
69- * @return array|float|string Rounded Number, or a string containing an error
69+ * @return array<mixed> |float|string Rounded Number, or a string containing an error
7070 * If an array of numbers is passed as an argument, then the returned result will also be an array
7171 * with the same dimensions
7272 */
73- public static function math (mixed $ number , mixed $ significance = null , $ mode = 0 ): array |string |float
73+ public static function math (mixed $ number , mixed $ significance = null , $ mode = 0 , bool $ checkSigns = false ): array |string |float
7474 {
7575 if (is_array ($ number ) || is_array ($ significance ) || is_array ($ mode )) {
7676 return self ::evaluateArrayArguments ([self ::class, __FUNCTION__ ], $ number , $ significance , $ mode );
@@ -87,6 +87,11 @@ public static function math(mixed $number, mixed $significance = null, $mode = 0
8787 if (empty ($ significance * $ number )) {
8888 return 0.0 ;
8989 }
90+ if ($ checkSigns ) {
91+ if (($ number > 0 && $ significance < 0 ) || ($ number < 0 && $ significance > 0 )) {
92+ return ExcelError::NAN ();
93+ }
94+ }
9095 if (self ::ceilingMathTest ((float ) $ significance , (float ) $ number , (int ) $ mode )) {
9196 return floor ($ number / $ significance ) * $ significance ;
9297 }
@@ -104,10 +109,10 @@ public static function math(mixed $number, mixed $significance = null, $mode = 0
104109 *
105110 * @param mixed $number the number you want to round
106111 * Or can be an array of values
107- * @param array|float $significance the multiple to which you want to round
112+ * @param array<mixed> |float $significance the multiple to which you want to round
108113 * Or can be an array of values
109114 *
110- * @return array|float|string Rounded Number, or a string containing an error
115+ * @return array<mixed> |float|string Rounded Number, or a string containing an error
111116 * If an array of numbers is passed as an argument, then the returned result will also be an array
112117 * with the same dimensions
113118 */
@@ -132,6 +137,23 @@ public static function precise(mixed $number, $significance = 1): array|string|f
132137 return ceil ($ result ) * $ significance * (($ significance < 0 ) ? -1 : 1 );
133138 }
134139
140+ /**
141+ * CEILING.ODS, pseudo-function - CEILING as implemented in ODS.
142+ *
143+ * ODS Function (theoretical):
144+ * CEILING.ODS(number[,significance[,mode]])
145+ *
146+ * @param mixed $number Number to round
147+ * @param mixed $significance Significance
148+ * @param array<mixed>|int $mode direction to round negative numbers
149+ *
150+ * @return array<mixed>|float|string Rounded Number, or a string containing an error
151+ */
152+ public static function mathOds (mixed $ number , mixed $ significance = null , $ mode = 0 ): array |string |float
153+ {
154+ return self ::math ($ number , $ significance , $ mode , true );
155+ }
156+
135157 /**
136158 * Let CEILINGMATH complexity pass Scrutinizer.
137159 */
@@ -148,7 +170,12 @@ private static function argumentsOk(float $number, float $significance): float|s
148170 if (empty ($ number * $ significance )) {
149171 return 0.0 ;
150172 }
151- if (Helpers::returnSign ($ number ) == Helpers::returnSign ($ significance )) {
173+ $ signSig = Helpers::returnSign ($ significance );
174+ $ signNum = Helpers::returnSign ($ number );
175+ if (
176+ ($ signSig === 1 && ($ signNum === 1 || Functions::getCompatibilityMode () !== Functions::COMPATIBILITY_GNUMERIC ))
177+ || ($ signSig === -1 && $ signNum === -1 )
178+ ) {
152179 return ceil ($ number / $ significance ) * $ significance ;
153180 }
154181
0 commit comments