<?xml version="1.0" encoding="UTF-8"?>
<DefineBehavior xmlns="Tethys"
       xmlns:Control="Tethys/Control"
       xmlns:BehaviorScripts="Tethys/BehaviorScripts" 
       xmlns:Units="Tethys/Units"
       xmlns:Universal="Tethys/Universal"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="Tethys http://okeanids.mbari.org/tethys/Xml/Tethys.xsd
                           Tethys/Control http://okeanids.mbari.org/tethys/Xml/Control.xsd
                           Tethys/BehaviorScripts ./BehaviorScripts.xsd
                           Tethys/Units http://okeanids.mbari.org/tethys/Xml/Units.xsd
                           Tethys/Universal http://okeanids.mbari.org/tethys/Xml/Universal.xsd"
       Name="FiniteDifference" Language="Lua">

    <Description>
        Given an input value and an order, calculate the backwards-looking
        finite difference.
    </Description>

    <DefineSetting Name="inputSet">
        <BehaviorScripts:FiniteDifference.input/>
        <Description>
            The value to be finite differenced
        </Description><Units:none/>
        <DefaultValue>NaN</DefaultValue>
    </DefineSetting>

    <DefineSetting Name="orderSet">
        <BehaviorScripts:FiniteDifference.order/>
        <Description>
            Order (#elements -1) for the finite difference operation
        </Description><Units:count/>
        <DefaultValue>1</DefaultValue>
    </DefineSetting>

    <Construct>
        <Description>
            Define functions for use in the behavior
        </Description>
        <Script><![CDATA[
	        function Binomial( k, m )
                if m > k then return nil end
			    if m > k/2 then m = k - m end
			    numer, denom = 1, 1
			    for i = 1, m do
			        numer = numer * ( k - i + 1 )
			        denom = denom * i
			    end
			    local bin = numer / denom
			    return bin
			end
			function BackwardDifference( buf, k )
			    n = table.getn(buf);
                if k >= n then return nil end
			    d = 0
			    for m=0,k do
                    d = d + math.pow(-1,m) * Binomial( k, m ) * buf[ n - m ]
                end
                return d
			end
			function AddValue( buf, k, value )
			    n = table.getn(buf)
			    if(n <= k ) then buf[n+1]=value return end
			    for i=1,k,1 do
			       buf[i]=buf[i+1]
			    end
			    buf[k+1]=value
			end
			return "Constructed FiniteDifference", "IMPORTANT"
	    ]]></Script>
    </Construct>

    <Initialize>
        <Description>
            Initialize global variables
        </Description>
        <Script><![CDATA[
           buffer={}
        ]]></Script>
    </Initialize>

    <Run>
        <OutputArg><BehaviorScripts:FiniteDifference.output/><Description>
            Result of the finite difference operation. Not written until the
            buffer is full
        </Description><Units:none/></OutputArg>
        <Script><![CDATA[
           AddValue(buffer,orderSet,inputSet)
           bd = BackwardDifference( buffer, orderSet )
           return bd
        ]]></Script>
    </Run>

</DefineBehavior>
