function [ramRdData, ramRdDout] = range_hdlram(h, ramWriteData, ramWriteAddr, ramWriteEnable, ramReadAddr)
    [rangeLow, rangeHigh] = range_hdlram_impl(ramWriteData(:));
    ramRdData = [rangeLow rangeHigh];
    ramRdDout =  [rangeLow rangeHigh];
end


function [rangeLow, rangeHigh] = range_hdlram_impl(values)
    persistent ram_rangeLow ram_rangeHigh
    if isempty(ram_rangeLow)
        % First call to the step.
        [rangeLow, rangeHigh] = get_min_max(values);
        ram_rangeLow = rangeLow;
        ram_rangeHigh = rangeHigh;
    else
        % Subsequence calls to step
        [rangeLow, rangeHigh] = get_min_max(values);
        
        % Update low and high
        rangeLow = min(rangeLow, ram_rangeLow);
        rangeHigh = max(rangeHigh, ram_rangeHigh);
        
        % The new low is minimum of current and previous high
        ram_rangeLow = rangeLow;
        ram_rangeHigh = rangeHigh;      
    end
end


function [rangeLow, rangeHigh] = get_min_max(values)
    coder.inline('always');
    % Return both minimum and minimum values.
   
    values = values(:);
    if isreal(values)     
        rangeLow = min(values);
        rangeHigh = max(values);
    else
        % Take minimum and minimum of real and imaginary parts separately.
        % Otherwise constructs like sqrt, exp etc will be introduced.
        values_re = real(values);
        values_im = imag(values);
        rangeLow = min(min(values_re), min(values_im));
        rangeHigh = max(max(values_re), max(values_im));
    end
    
    % Default value of RAM is zero.
    rangeLow = min(0, rangeLow);
    rangeHigh = max(0, rangeHigh);
end
