Skip to content

Commit

Permalink
Extract ACCRINT() and ACCRINTM() Financial functions into their own c…
Browse files Browse the repository at this point in the history
…lass (#1956)

* Extract ACCRINT() and ACCRINTM() Financial functions into their own class
Implement additional validations, with additional unit tests
Add support for the new calculation method argument for ACCRINT()
* Additional tests for Amortization functions
  • Loading branch information
Mark Baker authored Mar 26, 2021
1 parent d36f9d5 commit c699d14
Show file tree
Hide file tree
Showing 32 changed files with 621 additions and 366 deletions.
6 changes: 3 additions & 3 deletions src/PhpSpreadsheet/Calculation/Calculation.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,12 @@ class Calculation
],
'ACCRINT' => [
'category' => Category::CATEGORY_FINANCIAL,
'functionCall' => [Financial::class, 'ACCRINT'],
'argumentCount' => '4-7',
'functionCall' => [Financial\Securities\AccruedInterest::class, 'periodic'],
'argumentCount' => '4-8',
],
'ACCRINTM' => [
'category' => Category::CATEGORY_FINANCIAL,
'functionCall' => [Financial::class, 'ACCRINTM'],
'functionCall' => [Financial\Securities\AccruedInterest::class, 'atMaturity'],
'argumentCount' => '3-5',
],
'ACOS' => [
Expand Down
27 changes: 27 additions & 0 deletions src/PhpSpreadsheet/Calculation/Engineering/BaseValidations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering;

use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;

trait BaseValidations
{
protected static function validateFloat($value): float
{
if (!is_numeric($value)) {
throw new Exception(Functions::VALUE());
}

return (float) $value;
}

protected static function validateInt($value): int
{
if (!is_numeric($value)) {
throw new Exception(Functions::VALUE());
}

return (int) floor($value);
}
}
23 changes: 14 additions & 9 deletions src/PhpSpreadsheet/Calculation/Engineering/BesselI.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering;

use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;

class BesselI
{
use BaseValidations;

/**
* BESSELI.
*
Expand All @@ -32,18 +35,20 @@ public static function BESSELI($x, $ord)
$x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
$ord = ($ord === null) ? 0 : Functions::flattenSingleValue($ord);

if ((is_numeric($x)) && (is_numeric($ord))) {
$ord = (int) floor($ord);
if ($ord < 0) {
return Functions::NAN();
}

$fResult = self::calculate((float) $x, $ord);
try {
$x = self::validateFloat($x);
$ord = self::validateInt($ord);
} catch (Exception $e) {
return $e->getMessage();
}

return (is_nan($fResult)) ? Functions::NAN() : $fResult;
if ($ord < 0) {
return Functions::NAN();
}

return Functions::VALUE();
$fResult = self::calculate($x, $ord);

return (is_nan($fResult)) ? Functions::NAN() : $fResult;
}

private static function calculate(float $x, int $ord): float
Expand Down
23 changes: 14 additions & 9 deletions src/PhpSpreadsheet/Calculation/Engineering/BesselJ.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering;

use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;

class BesselJ
{
use BaseValidations;

/**
* BESSELJ.
*
Expand All @@ -30,18 +33,20 @@ public static function BESSELJ($x, $ord)
$x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
$ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord);

if ((is_numeric($x)) && (is_numeric($ord))) {
$ord = (int) floor($ord);
if ($ord < 0) {
return Functions::NAN();
}

$fResult = self::calculate((float) $x, $ord);
try {
$x = self::validateFloat($x);
$ord = self::validateInt($ord);
} catch (Exception $e) {
return $e->getMessage();
}

return (is_nan($fResult)) ? Functions::NAN() : $fResult;
if ($ord < 0) {
return Functions::NAN();
}

return Functions::VALUE();
$fResult = self::calculate($x, $ord);

return (is_nan($fResult)) ? Functions::NAN() : $fResult;
}

private static function calculate(float $x, int $ord): float
Expand Down
28 changes: 16 additions & 12 deletions src/PhpSpreadsheet/Calculation/Engineering/BesselK.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering;

use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;

class BesselK
{
use BaseValidations;

/**
* BESSELK.
*
Expand All @@ -28,25 +31,26 @@ public static function BESSELK($x, $ord)
$x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
$ord = ($ord === null) ? 0 : Functions::flattenSingleValue($ord);

if ((is_numeric($x)) && (is_numeric($ord))) {
$ord = (int) floor($ord);
$x = (float) $x;
if (($ord < 0) || ($x <= 0.0)) {
return Functions::NAN();
}

$fBk = self::calculate($x, $ord);
try {
$x = self::validateFloat($x);
$ord = self::validateInt($ord);
} catch (Exception $e) {
return $e->getMessage();
}

return (is_nan($fBk)) ? Functions::NAN() : $fBk;
if (($ord < 0) || ($x <= 0.0)) {
return Functions::NAN();
}

return Functions::VALUE();
$fBk = self::calculate($x, $ord);

return (is_nan($fBk)) ? Functions::NAN() : $fBk;
}

private static function calculate($x, $ord): float
private static function calculate(float $x, int $ord): float
{
// special cases
switch (floor($ord)) {
switch ($ord) {
case 0:
return self::besselK0($x);
case 1:
Expand Down
28 changes: 16 additions & 12 deletions src/PhpSpreadsheet/Calculation/Engineering/BesselY.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering;

use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;

class BesselY
{
use BaseValidations;

/**
* BESSELY.
*
Expand All @@ -27,25 +30,26 @@ public static function BESSELY($x, $ord)
$x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
$ord = ($ord === null) ? 0 : Functions::flattenSingleValue($ord);

if ((is_numeric($x)) && (is_numeric($ord))) {
$ord = (int) floor($ord);
$x = (float) $x;
if (($ord < 0) || ($x <= 0.0)) {
return Functions::NAN();
}

$fBy = self::calculate($x, $ord);
try {
$x = self::validateFloat($x);
$ord = self::validateInt($ord);
} catch (Exception $e) {
return $e->getMessage();
}

return (is_nan($fBy)) ? Functions::NAN() : $fBy;
if (($ord < 0) || ($x <= 0.0)) {
return Functions::NAN();
}

return Functions::VALUE();
$fBy = self::calculate($x, $ord);

return (is_nan($fBy)) ? Functions::NAN() : $fBy;
}

private static function calculate($x, $ord): float
private static function calculate(float $x, int $ord): float
{
// special cases
switch (floor($ord)) {
switch ($ord) {
case 0:
return self::besselY0($x);
case 1:
Expand Down
17 changes: 13 additions & 4 deletions src/PhpSpreadsheet/Calculation/Engineering/Compare.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering;

use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;

class Compare
{
use BaseValidations;

/**
* DELTA.
*
Expand All @@ -27,8 +30,11 @@ public static function DELTA($a, $b = 0)
$a = Functions::flattenSingleValue($a);
$b = Functions::flattenSingleValue($b);

if (!is_numeric($a) || !is_numeric($b)) {
return Functions::VALUE();
try {
$a = self::validateFloat($a);
$b = self::validateFloat($b);
} catch (Exception $e) {
return $e->getMessage();
}

return (int) ($a == $b);
Expand All @@ -54,8 +60,11 @@ public static function GESTEP($number, $step = 0)
$number = Functions::flattenSingleValue($number);
$step = Functions::flattenSingleValue($step);

if (!is_numeric($number) || !is_numeric($step)) {
return Functions::VALUE();
try {
$number = self::validateFloat($number);
$step = self::validateFloat($step);
} catch (Exception $e) {
return $e->getMessage();
}

return (int) ($number >= $step);
Expand Down
15 changes: 11 additions & 4 deletions src/PhpSpreadsheet/Calculation/Engineering/Complex.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@

use Complex\Complex as ComplexObject;
use Complex\Exception as ComplexException;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;

class Complex
{
use BaseValidations;

/**
* COMPLEX.
*
Expand All @@ -29,10 +32,14 @@ public static function COMPLEX($realNumber = 0.0, $imaginary = 0.0, $suffix = 'i
$imaginary = ($imaginary === null) ? 0.0 : Functions::flattenSingleValue($imaginary);
$suffix = ($suffix === null) ? 'i' : Functions::flattenSingleValue($suffix);

if (
((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
(($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))
) {
try {
$realNumber = self::validateFloat($realNumber);
$imaginary = self::validateFloat($imaginary);
} catch (Exception $e) {
return $e->getMessage();
}

if (($suffix == 'i') || ($suffix == 'j') || ($suffix == '')) {
$complex = new ComplexObject($realNumber, $imaginary, $suffix);

return (string) $complex;
Expand Down
6 changes: 3 additions & 3 deletions src/PhpSpreadsheet/Calculation/Engineering/Erf.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ class Erf
* Excel Function:
* ERF(lower[,upper])
*
* @param float $lower lower bound for integrating ERF
* @param float $upper upper bound for integrating ERF.
* @param mixed (float) $lower lower bound for integrating ERF
* @param mixed (float) $upper upper bound for integrating ERF.
* If omitted, ERF integrates between zero and lower_limit
*
* @return float|string
Expand Down Expand Up @@ -52,7 +52,7 @@ public static function ERF($lower, $upper = null)
* Excel Function:
* ERF.PRECISE(limit)
*
* @param float $limit bound for integrating ERF
* @param mixed (float) $limit bound for integrating ERF
*
* @return float|string
*/
Expand Down
Loading

0 comments on commit c699d14

Please sign in to comment.