/**
 * Copyright (C) 2012 Brookhaven National Laboratory
 * All rights reserved. Use is subject to license terms.
 */
package org.epics.util.array;

/**
 * Math operations defined on lists of numbers.
 *
 * @author carcassi
 */
public class ListMath {

    private ListMath() {
    }
    
    /**
     * Returns a sublist of the given data.
     * 
     * @param data a list
     * @param start start point for the sublist
     * @param end end point (exclusive) for the sublist
     * @return the sublist
     */
    public static ListDouble limit(final ListDouble data, final int start, final int end) {
        return new ListDouble() {

            @Override
            public double getDouble(int index) {
                return data.getDouble(index + start);
            }

            @Override
            public int size() {
                return end - start;
            }
        };
    }
    
    /**
     * Returns a sublist of the given data.
     * <p>
     * TODO: this should go as a member method
     * 
     * @param data a list
     * @param start start point for the sublist
     * @param end end point (exclusive) for the sublist
     * @return the sublist
     */
    public static ListNumber limit(final ListNumber data, final int start, final int end) {
        return new ListDouble() {

            @Override
            public double getDouble(int index) {
                return data.getDouble(index + start);
            }

            @Override
            public int size() {
                return end - start;
            }
        };
    }
    
    /**
     * Returns a sublist of the given data.
     * 
     * @param data a list
     * @param start start point for the sublist
     * @param end end point (exclusive) for the sublist
     * @return the sublist
     */
    public static ListLong limit(final ListLong data, final int start, final int end) {
        return new ListLong() {

            @Override
            public long getLong(int index) {
                return data.getLong(index + start);
            }

            @Override
            public int size() {
                return end - start;
            }
        };
    }
    
    /**
     * Performs a linear transformation on the data.
     * 
     * @param data a list of numbers
     * @param factor the multiplicative constant
     * @param offset the additive constant
     * @return the computed data
     */
    public static ListDouble rescale(final ListNumber data, final double factor, final double offset) {
        if (offset == 1.0)
            return sum(data, offset);
        return new ListDouble() {

            @Override
            public double getDouble(int index) {
                return factor * data.getDouble(index) + offset;
            }

            @Override
            public int size() {
                return data.size();
            }
        };
    }
    
    /**
     * Returns a new list where all elements are added to a constant.
     * 
     * @param data a list of number
     * @param offset the additive constant
     * @return the computed data
     */
    public static ListDouble sum(final ListNumber data, final double offset) {
        return new ListDouble() {

            @Override
            public double getDouble(int index) {
                return data.getDouble(index) + offset;
            }

            @Override
            public int size() {
                return data.size();
            }
        };
    }
    
    /**
     * Returns a list where each element is the sum of the elements of the two
     * lists at the same index. The lists have to match in size.
     * 
     * @param data1 a list of numbers
     * @param data2 another list of numbers
     * @return the computed data
     */
    public static ListDouble sum(final ListNumber data1, final ListNumber data2) {
        if (data1.size() != data2.size())
            throw new IllegalArgumentException("Can't sum ListNumbers of different size (" + data1.size() + " - " + data2.size() + ")");
        return new ListDouble() {

            @Override
            public double getDouble(int index) {
                return data1.getDouble(index) + data2.getDouble(index);
            }

            @Override
            public int size() {
                return data1.size();
            }
        };
    }
    
}

@@ -142,16 +142,46 @@
 array;%0A%0A
+import java.math.BigInteger;%0A%0A
 /**%0A * M
@@ -2567,22 +2567,22 @@
     if (
-offset
+factor
  == 1.0)
@@ -4161,32 +4161,32 @@
 le(int index) %7B%0A
-
                 
@@ -4248,32 +4248,914 @@
 %0A            %7D%0A%0A
+            @Override%0A            public int size() %7B%0A                return data1.size();%0A            %7D%0A        %7D;%0A    %7D%0A    %0A    /**%0A     * Returns a list where each element is the difference of the elements of the two%0A     * lists at the same index. The lists have to match in size.%0A     * %0A     * @param data1 a list of numbers%0A     * @param data2 another list of numbers%0A     * @return the computed data%0A     */%0A    public static ListDouble subtract(final ListNumber data1, final ListNumber data2) %7B%0A        if (data1.size() != data2.size())%0A            throw new IllegalArgumentException(%22Can't subtract ListNumbers of different size (%22 + data1.size() + %22 - %22 + data2.size() + %22)%22);%0A        return new ListDouble() %7B%0A%0A            @Override%0A            public double getDouble(int index) %7B%0A                return data1.getDouble(index) - data2.getDouble(index);%0A            %7D%0A%0A
             @Ove

update to SNAPSHOT