1<?php
2
3namespace PhpOffice\PhpSpreadsheet\Shared\Trend;
4
5class LogarithmicBestFit extends BestFit
6{
7    /**
8     * Algorithm type to use for best-fit
9     * (Name of this Trend class).
10     *
11     * @var string
12     */
13    protected $bestFitType = 'logarithmic';
14
15    /**
16     * Return the Y-Value for a specified value of X.
17     *
18     * @param float $xValue X-Value
19     *
20     * @return float Y-Value
21     */
22    public function getValueOfYForX($xValue)
23    {
24        return $this->getIntersect() + $this->getSlope() * log($xValue - $this->xOffset);
25    }
26
27    /**
28     * Return the X-Value for a specified value of Y.
29     *
30     * @param float $yValue Y-Value
31     *
32     * @return float X-Value
33     */
34    public function getValueOfXForY($yValue)
35    {
36        return exp(($yValue - $this->getIntersect()) / $this->getSlope());
37    }
38
39    /**
40     * Return the Equation of the best-fit line.
41     *
42     * @param int $dp Number of places of decimal precision to display
43     *
44     * @return string
45     */
46    public function getEquation($dp = 0)
47    {
48        $slope = $this->getSlope($dp);
49        $intersect = $this->getIntersect($dp);
50
51        return 'Y = ' . $intersect . ' + ' . $slope . ' * log(X)';
52    }
53
54    /**
55     * Execute the regression and calculate the goodness of fit for a set of X and Y data values.
56     *
57     * @param float[] $yValues The set of Y-values for this regression
58     * @param float[] $xValues The set of X-values for this regression
59     * @param bool $const
60     */
61    private function logarithmicRegression($yValues, $xValues, $const)
62    {
63        foreach ($xValues as &$value) {
64            if ($value < 0.0) {
65                $value = 0 - log(abs($value));
66            } elseif ($value > 0.0) {
67                $value = log($value);
68            }
69        }
70        unset($value);
71
72        $this->leastSquareFit($yValues, $xValues, $const);
73    }
74
75    /**
76     * Define the regression and calculate the goodness of fit for a set of X and Y data values.
77     *
78     * @param float[] $yValues The set of Y-values for this regression
79     * @param float[] $xValues The set of X-values for this regression
80     * @param bool $const
81     */
82    public function __construct($yValues, $xValues = [], $const = true)
83    {
84        parent::__construct($yValues, $xValues);
85
86        if (!$this->error) {
87            $this->logarithmicRegression($yValues, $xValues, $const);
88        }
89    }
90}
91