/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: MutableInterval.java * * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. * * Electric(tm) 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. * * Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.tool.simulation.interval; import com.sun.electric.util.math.MutableInterval; import java.math.BigDecimal; /** * * @author Dmitry Nadezhin */ public class UnivariateTaylorModel { private static double[] NULL_DOUBLE_ARRAY = {}; private static MutableInterval ENTIRE = new MutableInterval().assignEntire(); private final double coeff[]; private final MutableInterval remainder; private final MutableInterval evalRemainder; private UnivariateTaylorModel(double[] coeff, double inf, double sup) { this.coeff = coeff; remainder = new MutableInterval(inf, sup); double evalRound = 0; evalRemainder = new MutableInterval(-evalRound, evalRound); evalRemainder.add(remainder); } private UnivariateTaylorModel(double[] coeff) { this.coeff = coeff; remainder = evalRemainder = ENTIRE; } public static UnivariateTaylorModel newInstance(double x) { double[] coeff = NULL_DOUBLE_ARRAY; double inf = 0; double sup = 0; if (Double.NEGATIVE_INFINITY < x && x < Double.POSITIVE_INFINITY) { coeff = new double[] { x }; } else if (x == Double.POSITIVE_INFINITY) { coeff = new double[] { Double.MAX_VALUE }; sup = x; } else if (x == Double.NEGATIVE_INFINITY) { inf = x; coeff = new double[] { -Double.MAX_VALUE }; } else { inf = -Double.MAX_VALUE; sup = Double.MAX_VALUE; } return new UnivariateTaylorModel(coeff, inf, sup); } public static UnivariateTaylorModel newInstance(MutableInterval x) { return null; } public int size() { return coeff.length; } public double coeff(int k) { return k < coeff.length ? coeff[k] : 0; } public MutableInterval getRemainder() { return new MutableInterval(remainder); } public void eval(MutableInterval result, double t) { if (!(-1 <= t && t <= 1)) { result.assignEntire(); return; } double value = 0; double sumAbs = 0; for (int k = coeff.length - 1; k >= 0; k--) { value = value*t + coeff[k]; sumAbs += Math.abs(coeff[k]); } result.add(evalRemainder); } public void eval2(MutableInterval result, double t) { if (!(-1 <= t && t <= 1)) { result.assignEntire(); return; } result.assign(0); MutableInterval ti = new MutableInterval(t); for (int k = coeff.length - 1; k >= 0; k--) result.mul(ti).add(new MutableInterval(coeff[k])); result.add(remainder); } public void eval3(MutableInterval result, double t) { if (!(-1 <= t && t <= 1)) { result.assignEntire(); return; } BigDecimal tb = BigDecimal.valueOf(t); BigDecimal ib = BigDecimal.valueOf(0); BigDecimal sb = BigDecimal.valueOf(0); for (int k = coeff.length - 1; k >= 0; k--) { ib.multiply(tb); sb.multiply(tb); if (t < 0) { BigDecimal b = ib; ib = sb; sb = b; } BigDecimal cb = BigDecimal.valueOf(coeff[k]); ib.add(cb); sb.add(cb); } ib.add(new BigDecimal(remainder.inf())); sb.add(new BigDecimal(remainder.sup())); double inf = ib.doubleValue(); if (!ib.equals(BigDecimal.valueOf(inf))) inf = MutableInterval.prev(inf); double sup = sb.doubleValue(); if (!sb.equals(BigDecimal.valueOf(sup))) sup = MutableInterval.next(sup); result.assign(inf, sup); } public void eval3(MutableInterval[] results, double t) { if (!(-1 <= t && t <= 1)) { for (MutableInterval result: results) result.assignEntire(); return; } BigDecimal tb = BigDecimal.valueOf(t); BigDecimal[] lb = new BigDecimal[results.length]; BigDecimal[] hb = new BigDecimal[results.length]; for (int i = 0; i < results.length; i++) lb[i] = hb[i] = BigDecimal.valueOf(0); // for (int k = coeff.length - 1; k >= 0; k--) { // lb.multiply(tb); // hb.multiply(tb); // if (t < 0) { // BigDecimal b = lb; // lb = hb; // hb = b; // } // BigDecimal cb = BigDecimal.valueOf(coeff[k]); // lb.add(cb); // hb.add(cb); // } // lb.add(new BigDecimal(remainder.inf())); // hb.add(new BigDecimal(remainder.sup())); // double inf = lb.doubleValue(); // if (!lb.equals(BigDecimal.valueOf(inf))) // inf = MutableInterval.prev(inf); // double sup = hb.doubleValue(); // if (!hb.equals(BigDecimal.valueOf(sup))) // sup = MutableInterval.next(sup); // result.assign(inf, sup); } public void evalAtZero(MutableInterval result) { if (coeff.length >= 1) { result.assign(coeff[0]); result.add(remainder); } else { result.assignEmpty(); } } public void evalAtPlusOne(MutableInterval result) { result.assign(0); for (int k = coeff.length - 1; k >= 0; k--) result.add(coeff[k]); result.add(remainder); } public void evalAtMinusOne(MutableInterval result) { result.assign(0); for (int k = coeff.length - 1; k >= 0; k--) result.add((k & 1) == 0 ? coeff[k] : -coeff[k]); result.add(remainder); } public UnivariateTaylorModel negate() { double[] newCoeff = new double[coeff.length]; for (int k = 0; k < coeff.length; k++) newCoeff[k] = -coeff[k]; return new UnivariateTaylorModel(newCoeff, -remainder.sup(), -remainder.inf()); } public UnivariateTaylorModel multiplyNaive(double x) { double[] newCoeff = new double[size()]; for (int k = 0; k < newCoeff.length; k++) newCoeff[k] = coeff[k]*x; return new UnivariateTaylorModel(newCoeff); } public UnivariateTaylorModel addNaive(UnivariateTaylorModel x, int maxSize) { maxSize = Math.min(maxSize, Math.max(size(), x.size())); double[] newCoeff = new double[maxSize]; for (int k = 0; k < newCoeff.length; k++) newCoeff[k] = coeff(k) + x.coeff(k); return new UnivariateTaylorModel(newCoeff); } public UnivariateTaylorModel subtractNaive(UnivariateTaylorModel x, int maxSize) { maxSize = Math.min(maxSize, Math.max(size(), x.size())); double[] newCoeff = new double[maxSize]; for (int k = 0; k < newCoeff.length; k++) newCoeff[k] = coeff(k) + x.coeff(k); return new UnivariateTaylorModel(newCoeff); } public UnivariateTaylorModel multiplyNaive(UnivariateTaylorModel x, int maxSize) { maxSize = Math.min(maxSize, size() + x.size() - 1); if (x.size() < maxSize) return x.multiplyNaive(this, maxSize); double[] newCoeff = new double[maxSize]; for (int k = 0; k < newCoeff.length; k++) { double s = 0; for (int l = 0; l < size(); l++) s += coeff(l)*x.coeff(k - l); newCoeff[k] = s; } return new UnivariateTaylorModel(newCoeff); } private UnivariateTaylorModel check() { for (double c: coeff) assert -Double.MAX_VALUE <= c && c <= Double.MAX_VALUE; return this; } }