Package net.sourceforge.gpstools.math

Source Code of net.sourceforge.gpstools.math.PieceWiseFunction$SegmentFunction

package net.sourceforge.gpstools.math;

/* gpsdings
* Copyright (C) 2007 Moritz Ringler
* $Id: PieceWiseFunction.java 441 2010-12-13 20:04:20Z ringler $
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

import java.util.TreeSet;
import java.util.SortedSet;
import java.util.Comparator;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.analysis.UnivariateRealFunction;

public class PieceWiseFunction implements UnivariateRealFunction{
    transient SegmentFunction lastSegment;
    private final static Comparator<SegmentFunction> funcSorter = new Comparator<SegmentFunction>(){
        @Override
        public int compare(SegmentFunction f1, SegmentFunction f2){
            return f1.domain.compareTo(f2.domain);
        }
    };

    protected SortedSet<SegmentFunction> elements = new TreeSet<SegmentFunction>(funcSorter);

    public PieceWiseFunction(){
        // explicit default constructor.
    }

    /**  @return a sorted array of the intervals that jointly form the domain
    * of this function */
    public synchronized ClosedInterval[] getDomain(){
        final int n = elements.size();
        ClosedInterval[] result = new ClosedInterval[n];
        int i = 0;
        for(SegmentFunction f : elements){
            result[i++] = f.domain;
        }
        return result;
    }

    public synchronized boolean addSegmentFunction(SegmentFunction f){
        for(SegmentFunction other : elements){
            if(f.domain.overlaps(other.domain) && ! f.equals(other)){
                throw new IllegalArgumentException("The domain of this SegmentFunction overlaps with that of another one.");
            }
        }
        return elements.add(f);
    }

    public synchronized boolean addSegmentFunction(double xmin, double xmax, UnivariateRealFunction f){
        return addSegmentFunction(new SegmentFunction(xmin, xmax, f));
    }

    public UnivariateRealFunction getSegmentFor(double x) throws FunctionEvaluationException {
        // try the segment that contained the last x-value first
        if(lastSegment != null && lastSegment.domain.contains(x)){
            return lastSegment.func;
        }
        for(SegmentFunction segment : elements){
            if(segment.domain.contains(x)){
                lastSegment = segment;
                return segment.func;
            }
        }
        return null;
    }

    @Override
    public double value(double x) throws FunctionEvaluationException {
        UnivariateRealFunction seg = getSegmentFor(x);
        if(seg == null){
            throw new FunctionEvaluationException(x, "Argument outside domain: " + x);
        }
           
        return seg.value(x);
    }


    /* class segment function */
    public static class SegmentFunction{
        public final ClosedInterval domain;
        public final UnivariateRealFunction func;

        public SegmentFunction(ClosedInterval domain, UnivariateRealFunction func){
            this.domain = domain;
            this.func = func;
        }

        public SegmentFunction(double xmin, double xmax, UnivariateRealFunction func){
            this.domain = new ClosedInterval(xmin, xmax);
            this.func = func;
        }

        @Override
        public boolean equals(Object o){
            if(this == o){
                return true;
            }
            if(o instanceof SegmentFunction){
                SegmentFunction other = (SegmentFunction) o;
                return
                        func.equals(other.func) &&
                        domain.equals(other.domain);
            }
            return false;
        }

        @Override
        public int hashCode(){
            int result = 17;
            result = 37 * result + domain.hashCode();
            result = 37 * result + func.hashCode();
            return result;
        }
    }



    public final static class ClosedInterval implements Comparable<ClosedInterval>{
        public final double xmin;
        public final double xmax;

        public ClosedInterval(double xmin, double xmax){
            if (xmax < xmin){
                throw new IllegalArgumentException("xmax must be greater than or equal to xmin.");
            }
            this.xmin = xmin;
            this.xmax = xmax;
        }

        @Override
        public boolean equals(Object o){
            if(this == o){
                return true;
            }
            if(o instanceof ClosedInterval){
                ClosedInterval other = (ClosedInterval) o;
                return
                        this.xmin == other.xmin &&
                        this.xmax == other.xmax;
            }
            return false;
        }

        @Override
        public int hashCode(){
            int result = 17;
            long d = Double.doubleToLongBits(xmin);
            result = 37 * result + (int)(d ^ (d >>> 32));
            d =  Double.doubleToLongBits(xmax);
            result = 37 * result + (int)(d ^ (d >>> 32));
            return result;
        }

        @Override
        public int compareTo(ClosedInterval other){
            int result = Double.compare(xmin, other.xmin);
            return (result == 0)
                ? Double.compare(xmax, other.xmax)
                : result;
        }

        public boolean overlaps(ClosedInterval other){
            boolean isless = (compareTo(other) <= 0);
            ClosedInterval a =  isless? this : other;
            ClosedInterval b = isless? other : this;
            return a.xmax > b.xmin;
            //return a.xmax >= b.xmin;
        }

        public boolean contains(double x){
            return x >= xmin && x <= xmax;
        }
    }
}
TOP

Related Classes of net.sourceforge.gpstools.math.PieceWiseFunction$SegmentFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.