local super = require "Regression"

LogarithmicRegression = super:new()

local _log = math.log

function LogarithmicRegression:init()
    super.init(self)
    self._coeff0 = nil
    self._coeff1 = nil
end

function LogarithmicRegression:finish()
    local n = self._n
    local xs = self._xs
    local ys = self._ys
    local x1 = 0
    local x2 = 0
    local y1 = 0
    local y2 = 0
    local y1x1 = 0
    
    for index = 1, self._n do
        local x = xs[index]
        local y = ys[index]
        x = _log(x)
        x1 = x1 + x
        x2 = x2 + x ^ 2
        y1 = y1 + y
        y2 = y2 + y ^ 2
        y1x1 = y1x1 + y * x
    end
    
    local det = n * x2 - x1 ^ 2
    if det ~= 0 then
        local inv11 = x2 / det
        local inv12 = -x1 / det
        local inv22 = n / det
        local coeff0 = inv11 * y1 + inv12 * y1x1
        local coeff1 = inv12 * y1 + inv22 * y1x1
        local r2 = ((n * y1x1 - x1 * y1) ^ 2) / ((n * x2 - x1 ^ 2) * (n * y2 - y1 ^ 2))
        
        self._coeff0 = coeff0
        self._coeff1 = coeff1
        self._r2 = r2
        return true
    end
end

function LogarithmicRegression:getEquation()
    local equation = 'y = '
    local empty = true
    if self._coeff1 == 1 then
        equation = equation .. 'ln(x)'
        empty = false
    elseif self._coeff1 == -1 then
        equation = equation .. '-ln(x)'
        empty = false
    elseif self._coeff1 ~= 0 then
        equation = equation .. string.format('%gln(x)', self._coeff1)
        empty = false
    end
    if empty then
        equation = equation .. string.format('%g', self._coeff0)
    else
        if self._coeff0 < 0 then
            equation = equation .. string.format(' - %g', -self._coeff0)
        elseif self._coeff0 > 0 then
            equation = equation .. string.format(' + %g', self._coeff0)
        end
    end
    return equation
end

function LogarithmicRegression:getValue(x)
    return self._coeff0 + self._coeff1 * _log(x)
end

return LogarithmicRegression
