Recursive calls in stored procedure and temporary tables
Drop the table if it exists before the next run.

...
begin
drop table if exists test;
create temp table test(up_link double precision, time_stamp timestamp without time zone) on commit drop;
a := endIndex - startIndex;
...


Or, as @dezso suggests, you could create the table only if it doesn't exist.

...
begin
create temp table IF NOT EXISTS test(up_link double precision, time_stamp timestamp without time zone) on commit drop;
TRUNCATE test;
a := endIndex - startIndex;
...


As far as efficiency goes, this function works about as well as it can (O=n).  That is, each statement is executed a single time and the flow is pretty linear.  It would take some knowledge of the underlying tables to make any significant improvements.  Those improvements are likely to be measured in small percentages, not geometric or exponential.