From c563493b639c5182e27cbe1ff85754411036570d Mon Sep 17 00:00:00 2001 From: Miro Richard Eklund Date: Fri, 27 Jul 2018 14:45:33 +0300 Subject: [PATCH] Add new sysdyn functions details in issue 16 linked below Multiple functions said to be available in simantics sysdyn documentation were missing. I added those that I could add, leaving functions that "cannot be called from functions" unimplemented, such as "der, initial, terminal, sample, edge, change, reinit, cardinality, inStream, actualStream" gitlab #16 Change-Id: Ibd2932683f046e2ab11830fb6dd9f4f6b58c29cb --- .../semantum/sysdyn/solver/Environment.java | 2482 +++++++++-------- 1 file changed, 1339 insertions(+), 1143 deletions(-) diff --git a/bundles/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Environment.java b/bundles/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Environment.java index baf91ac6..74e2ffb7 100644 --- a/bundles/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Environment.java +++ b/bundles/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Environment.java @@ -1,1143 +1,1339 @@ -/******************************************************************************* - * Copyright (c) 2013 Semantum Oy. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Semantum Oy - initial API and implementation - * VTT Technical Research Centre of Finland - #4488 - *******************************************************************************/ -package fi.semantum.sysdyn.solver; - -import fi.semantum.sysdyn.solver.Array.Modifier; -import gnu.trove.list.array.TIntArrayList; -import gnu.trove.map.hash.TObjectIntHashMap; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.TreeMap; - -interface Fn { - public Object evaluate(IEnvironment environment, int argc); - public Object evaluateInput(IEnvironment environment, int argPosition); - public void setLocals(IEnvironment environment); - public int offset(); - public Variable[] parameters(int args); -} - -abstract class Fn1 implements Fn { - - Variable[] parameters; - - public Fn1(int pCount) { - if(pCount > 0) { - parameters = new Variable[pCount]; - for(int i=0;i named = new HashMap(); - - public Model model; - public double step; - public double time; - public boolean initial = true; - public int size; - - public Object[] valueTable; - - public TObjectIntHashMap keyIndexMap = new TObjectIntHashMap(); - - HashMap> history = new HashMap>(); - - public Environment(Model model, double step, double start) { - this.model = model; - this.step = step; - this.time = start; - - model.functions.put("sin", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.sin(x); - } - - }); - model.functions.put("cos", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.cos(x); - } - - }); - model.functions.put("tan", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.tan(x); - } - - }); - model.functions.put("asin", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.asin(x); - } - - }); - model.functions.put("acos", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.acos(x); - } - - }); - model.functions.put("atan", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.atan(x); - } - - }); - model.functions.put("toRadians", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.toRadians(x); - } - - }); - model.functions.put("toDegrees", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.toDegrees(x); - } - - }); - model.functions.put("exp", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.exp(x); - } - - }); - model.functions.put("log", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.log(x); - } - - }); - model.functions.put("log10", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.log10(x); - } - - }); - model.functions.put("sqrt", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.sqrt(x); - } - - }); - model.functions.put("cbrt", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.cbrt(x); - } - - }); - model.functions.put("mod", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - Double y = (Double)environment.getValue(1); - return mod(x, y); - } - - double mod(double x, double y) { - return x - Math.floor(x/y)*y; - } - - }); - model.functions.put("rem", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - Double y = (Double)environment.getValue(1); - return Math.IEEEremainder(x, y); - } - - }); - model.functions.put("ceil", new Fn1(1) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Object value = environment.getValue(0); - if(value instanceof Double) { - return Math.ceil((Double)value); - } else if(value instanceof Array) { - return ((Array)value).copy(new Modifier() { - - @Override - public Object modify(Object o) { - if(o instanceof Double) { - return Math.ceil((Double)o); - } else { - throw new IllegalStateException(); - } - } - - }); - } else { - throw new IllegalStateException(); - } - } - - }); - model.functions.put("floor", new Fn1(1) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Object value = environment.getValue(0); - if(value instanceof Double) { - return Math.floor((Double)value); - } else if(value instanceof Array) { - return ((Array)value).copy(new Modifier() { - - @Override - public Object modify(Object o) { - if(o instanceof Double) { - return Math.floor((Double)o); - } else { - throw new IllegalStateException(); - } - } - - }); - } else { - throw new IllegalStateException(); - } - } - - }); - model.functions.put("rint", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.rint(x); - } - - }); - model.functions.put("atan2", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - Double y = (Double)environment.getValue(1); - return Math.atan2(x, y); - } - - }); - model.functions.put("pow", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - Double y = (Double)environment.getValue(1); - return Math.pow(x, y); - } - - }); - model.functions.put("round", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - long result = Math.round(x); - return (int)result; - } - - }); - - model.functions.put("abs", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Object o = environment.getValue(0); - if(o instanceof Double) { - return Math.abs((Double)o); - } else if (o instanceof Integer) { - return Math.abs((Integer)o); - } else { - throw new IllegalStateException("Unsupported argument to abs: " + o); - } - } - - }); - - model.functions.put("min", new Fn1(5) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Object first = environment.getValue(0); - if(first instanceof Double) { - Double result = (Double)first; - for(int i=1;i result) result = d; - } - return result; - } else if (first instanceof Integer) { - Integer result = (Integer )first; - for(int i=1;i result) result = d; - } - return result; - } else { - throw new IllegalStateException("Unsupported argument to max: " + first); - } - } - - }); - - model.functions.put("ulp", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.ulp(x); - } - - }); - - model.functions.put("signum", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.signum(x); - } - - }); - - model.functions.put("sinh", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.sinh(x); - } - - }); - - model.functions.put("cosh", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.cosh(x); - } - - }); - - model.functions.put("tanh", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.tanh(x); - } - - }); - - model.functions.put("hypot", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - Double y = (Double)environment.getValue(1); - return Math.hypot(x, y); - } - - }); - - model.functions.put("expm1", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.expm1(x); - } - - }); - - model.functions.put("log1p", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.log1p(x); - } - - }); - - model.functions.put("copySign", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - Double y = (Double)environment.getValue(1); - return Math.copySign(x, y); - } - - }); - - model.functions.put("getExponent", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.getExponent(x); - } - - }); - - model.functions.put("nextAfter", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - Double y = (Double)environment.getValue(1); - return Math.nextAfter(x, y); - } - - }); - - model.functions.put("nextUp", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - return Math.nextUp(x); - } - - }); - - model.functions.put("scalb", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Double x = (Double)environment.getValue(0); - Integer y = (Integer)environment.getValue(1); - return Math.scalb(x, y); - } - - }); - - model.functions.put("size", new Fn1(2) { - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Array array = (Array)environment.getValue(0); - Double col = (Double)environment.getValue(1); - return Double.valueOf(array.size(col.intValue())); - } - - }); - model.functions.put("zidz", new Fn1(2) { - - private Object evaluate(Double p1, Double p2) { - if(Math.abs(p2) < 1e-12) return 0.0; - else return p1 / p2; - } - - @Override - public Object evaluate(IEnvironment environment, int argc) { - Object o1 = environment.getValue(0); - Object o2 = environment.getValue(1); - - if(o1 instanceof Double && o2 instanceof Double) { - return evaluate((Double)o1, (Double)o2); - } - if(o1 instanceof Array && o2 instanceof Array) { - Array la = (Array)o1; - Array ra = (Array)o2; - Collection lae = la.elements(); - Collection rae = ra.elements(); - if(lae.size() != rae.size()) throw new UnsupportedOperationException(); - Iterator li = lae.iterator(); - Iterator ri = rae.iterator(); - Array result = new Array(); - for(int i=0;i history = system.getHistory(ident); - double time = system.time(); - - history.put(time, value); - - Double key = history.ceilingKey(time-p1); - - return history.get(key); - - } - - }); - model.functions.put("cat", new Fn1(10) { - - @Override - public Object evaluate(IEnvironment _environment, int argc) { - - Double dim = (Double)_environment.getValue(0); - - Array array = new Array(); - for(int i=1;i getHistory(String ident) { - TreeMap result = history.get(ident); - if(result == null) { - result = new TreeMap(); - history.put(ident, result); - } - return result; - } - - @Override - public Object getValue(int key) { - return valueTable[key]; - } - - @Override - public void put(int key, Object value) { - valueTable[key] = value; - } - - public void put(String key, Object value) { - named.put(key, value); - } - - public void setSize(int size) { - this.size = size; - } - - @Override - public int offset() { - return size; - } - - @Override - public ISystem getSystem() { - return this; - } - - @Override - public boolean initial() { - return initial; - } - - public Object evaluateFunction(IEnvironment environment, String name, ArgumentList args) { - return model.evaluateFunction(environment, name, args); - } - - @Override - public double time() { - return time; - } - - double[] valueArray; - int[] valueIndices; - - public void addIndexed(int dimensions[], ArrayList keys, String prefix, int d) { - - if(d == dimensions.length) { - keys.add(prefix); - return; - } - - String prefix2 = prefix; - if(d== 0) prefix2 += "["; - if(d>0) prefix2 += ","; - - for(int i=0;i keys, TIntArrayList indices, Set used) { - - if(!used.add(name)) return; - - if(dimensions == null) { - keys.add(name); - indices.add(index); - } else { - addIndexed(dimensions, keys, name, 0); - for(int i=0;i keys, TIntArrayList indices, Set used) { - addVariable(var.base.name, var.base.index, var.base.dimensions, keys, indices, used); - } - - public String[] getValueKeyArray() { - - ArrayList keys = new ArrayList(); - TIntArrayList indices = new TIntArrayList(); - Set used = new HashSet(); - - for (int i = 0; i < model.assignmentArray.length; i++) { - addVariable(model.assignmentArray[i].target, keys, indices, used); - } - - for (int i = 0; i < model.derivativeArray.length; i++) { - addVariable(model.derivativeArray[i].target, keys, indices, used); - } - - // NOTE: there is room for optimization as parameter values that do not - // change should only be obtained once (and parameter values that do - // change are (possibly) included in assignments or derivatives) - for(int i = 0; i < model.parameterArray.length; i++) { - addVariable(model.parameterArray[i].variable, keys, indices, used); - } - - for(Map.Entry entry : model.copies.entrySet()) { - addVariable(entry.getKey(), entry.getValue().index, entry.getValue().dimensions, keys, indices, used); - } - - valueArray = new double[keys.size()]; - - keyIndexMap.clear(); - for(int i=0;i used = new HashSet(); - - for (int i = 0; i < model.assignmentArray.length; i++) { - Variable v = model.assignmentArray[i].target; - if(!used.add(v.base.name)) continue; - for(int index=0;index entry : model.copies.entrySet()) { - VariableBase base = entry.getValue(); - if(!used.add(entry.getKey())) continue; - for(int index=0;index used = new HashSet(); -// -// for (int i = 0; i < model.assignmentArray.length; i++) { -// Variable v = model.assignmentArray[i].target; -// if(!used.add(v.base.name)) continue; -// for(int index=0;index entry : model.copies.entrySet()) { -// VariableBase base = entry.getValue(); -// if(!used.add(entry.getKey())) continue; -// for(int index=0;index assigned = new HashSet(); - -} +/******************************************************************************* + * Copyright (c) 2013 Semantum Oy. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland - #4488 + *******************************************************************************/ +package fi.semantum.sysdyn.solver; + +import fi.semantum.sysdyn.solver.Array.Modifier; +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TObjectIntHashMap; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.TreeMap; + +interface Fn { + public Object evaluate(IEnvironment environment, int argc); + public Object evaluateInput(IEnvironment environment, int argPosition); + public void setLocals(IEnvironment environment); + public int offset(); + public Variable[] parameters(int args); +} + +abstract class Fn1 implements Fn { + + Variable[] parameters; + + public Fn1(int pCount) { + if(pCount > 0) { + parameters = new Variable[pCount]; + for(int i=0;i named = new HashMap(); + + public Model model; + public double step; + public double time; + public boolean initial = true; + public int size; + + public Object[] valueTable; + + public TObjectIntHashMap keyIndexMap = new TObjectIntHashMap(); + + HashMap> history = new HashMap>(); + + public Environment(Model model, double step, double start) { + this.model = model; + this.step = step; + this.time = start; + + model.functions.put("sin", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.sin(x); + } + + }); + model.functions.put("cos", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.cos(x); + } + + }); + model.functions.put("tan", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.tan(x); + } + + }); + model.functions.put("asin", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.asin(x); + } + + }); + model.functions.put("acos", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.acos(x); + } + + }); + model.functions.put("atan", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.atan(x); + } + + }); + model.functions.put("toRadians", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.toRadians(x); + } + + }); + model.functions.put("toDegrees", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.toDegrees(x); + } + + }); + model.functions.put("exp", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.exp(x); + } + + }); + model.functions.put("log", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.log(x); + } + + }); + model.functions.put("log10", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.log10(x); + } + + }); + model.functions.put("sqrt", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.sqrt(x); + } + + }); + model.functions.put("cbrt", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.cbrt(x); + } + + }); + model.functions.put("mod", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + Double y = (Double)environment.getValue(1); + return mod(x, y); + } + + double mod(double x, double y) { + return x - Math.floor(x/y)*y; + } + + }); + model.functions.put("rem", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + Double y = (Double)environment.getValue(1); + return Math.IEEEremainder(x, y); + } + + }); + model.functions.put("ceil", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Object value = environment.getValue(0); + if(value instanceof Double) { + return Math.ceil((Double)value); + } else if(value instanceof Array) { + return ((Array)value).copy(new Modifier() { + + @Override + public Object modify(Object o) { + if(o instanceof Double) { + return Math.ceil((Double)o); + } else { + throw new IllegalStateException(); + } + } + + }); + } else { + throw new IllegalStateException(); + } + } + + }); + model.functions.put("floor", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Object value = environment.getValue(0); + if(value instanceof Double) { + return Math.floor((Double)value); + } else if(value instanceof Array) { + return ((Array)value).copy(new Modifier() { + + @Override + public Object modify(Object o) { + if(o instanceof Double) { + return Math.floor((Double)o); + } else { + throw new IllegalStateException(); + } + } + + }); + } else { + throw new IllegalStateException(); + } + } + + }); + model.functions.put("rint", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.rint(x); + } + + }); + model.functions.put("atan2", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + Double y = (Double)environment.getValue(1); + return Math.atan2(x, y); + } + + }); + model.functions.put("pow", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + Double y = (Double)environment.getValue(1); + return Math.pow(x, y); + } + + }); + model.functions.put("round", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + long result = Math.round(x); + return (int)result; + } + + }); + + model.functions.put("abs", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Object o = environment.getValue(0); + if(o instanceof Double) { + return Math.abs((Double)o); + } else if (o instanceof Integer) { + return Math.abs((Integer)o); + } else { + throw new IllegalStateException("Unsupported argument to abs: " + o); + } + } + + }); + + model.functions.put("min", new Fn1(5) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Object first = environment.getValue(0); + if(first instanceof Double) { + Double result = (Double)first; + for(int i=1;i result) result = d; + } + return result; + } else if (first instanceof Integer) { + Integer result = (Integer )first; + for(int i=1;i result) result = d; + } + return result; + } else { + throw new IllegalStateException("Unsupported argument to max: " + first); + } + } + + }); + + model.functions.put("ulp", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.ulp(x); + } + + }); + + model.functions.put("signum", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.signum(x); + } + + }); + + model.functions.put("sinh", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.sinh(x); + } + + }); + + model.functions.put("cosh", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.cosh(x); + } + + }); + + model.functions.put("cross", new Fn1(2) { + + //Returns index 0 with input 1 as a Double + //index 1 with input 2 as a Double, etc. + private Double get(Array a, int crossIndex) { + return (Double)a.element(crossIndex - 1); + } + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Array X = (Array)environment.getValue(0); + Array Y = (Array)environment.getValue(1); + if(X.dimension() != 3 && Y.dimension() != 3) { + return null; + } else { + Array result = new Array(3); + Double a = (get( X,2 )*get( Y,3 )) - (get( X,3 )*get( Y,2 )); + Double b = (get( X,3 )*get( Y,1 )) - (get( X,1 )*get( Y,3 )); + Double c = (get( X,1 )*get( Y,2 )) - (get( X,2 )*get( Y,1 )); + result.addElement(a); + result.addElement(b); + result.addElement(c); + return result; + } + } + + }); + model.functions.put("tanh", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.tanh(x); + } + + }); + + model.functions.put("hypot", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + Double y = (Double)environment.getValue(1); + return Math.hypot(x, y); + } + + }); + + model.functions.put("expm1", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.expm1(x); + } + + }); + + model.functions.put("log1p", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.log1p(x); + } + + }); + + model.functions.put("copySign", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + Double y = (Double)environment.getValue(1); + return Math.copySign(x, y); + } + + }); + + model.functions.put("getExponent", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.getExponent(x); + } + + }); + + model.functions.put("nextAfter", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + Double y = (Double)environment.getValue(1); + return Math.nextAfter(x, y); + } + + }); + + model.functions.put("nextUp", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + return Math.nextUp(x); + } + + }); + + model.functions.put("scalb", new Fn1(2) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Double x = (Double)environment.getValue(0); + Integer y = (Integer)environment.getValue(1); + return Math.scalb(x, y); + } + + }); + + model.functions.put("ndims", new Fn1(1) { + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Array array = (Array)environment.getValue(0); + return Double.valueOf(array.elements().size()); + } + + }); + + model.functions.put("diagonal", new Fn1(1) { + + private Array make(int[] dims, int pos) { + Array result = new Array(); + int d = dims[pos]; + if(pos == dims.length - 1) { + for(int i=0;i findRecursive(Array array) { + int s = array.elements().size(); + List result = new ArrayList<>(); + result.add(s); + if(s > 0) { + Object e = array.element(0); + if(e instanceof Array) { + List found = findRecursive((Array)e); + result.addAll(found); + } + } + return result; + } + + @Override + public Object evaluate(IEnvironment environment, int argc) { + if(argc==1) { + Array array = (Array)environment.getValue(0); + List resultL = findRecursive(array); + Array result = new Array(); + for(Integer i : resultL) { + result.addElement(i); + } + return result; + } else if(argc==2) { + Array array = (Array)environment.getValue(0); + Double col = (Double)environment.getValue(1); + return Double.valueOf(array.size(col.intValue())); + } else { + return null; + } + } + + }); + + model.functions.put("zidz", new Fn1(2) { + + private Object evaluate(Double p1, Double p2) { + if(Math.abs(p2) < 1e-12) return 0.0; + else return p1 / p2; + } + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Object o1 = environment.getValue(0); + Object o2 = environment.getValue(1); + + if(o1 instanceof Double && o2 instanceof Double) { + return evaluate((Double)o1, (Double)o2); + } + if(o1 instanceof Array && o2 instanceof Array) { + Array la = (Array)o1; + Array ra = (Array)o2; + Collection lae = la.elements(); + Collection rae = ra.elements(); + if(lae.size() != rae.size()) throw new UnsupportedOperationException(); + Iterator li = lae.iterator(); + Iterator ri = rae.iterator(); + Array result = new Array(); + for(int i=0;i elements = a.elements(); + Double result = 1.0; + if(elements.size() > 0) { + if(elements.get(0) instanceof Array) { + for(Object e : elements) { + result = result * productRecursive((Array)e); + } + } else { + for(Object e : elements) { + result = result * (Double)e; + } + } + } + return result; + } + + @Override + public Object evaluate(IEnvironment environment, int argc) { + Array array = (Array)environment.getValue(0); + Double result = productRecursive(array); + return result; + } + }); + + model.functions.put("ones", new Fn1(-1) { + + private Array make(int[] dims, int pos) { + Array result = new Array(); + int d = dims[pos]; + if(pos == dims.length - 1) { + for(int i=0;i 0.0) return 1.0; + else if (x < 0.0) return -1.0; + else return 0.0; + } + }); + + model.functions.put("delay", new Fn1(4) { + + @Override + public Object evaluate(IEnvironment _environment, int argc) { + + String ident = (String)_environment.getValue(0); + Double value = (Double)_environment.getValue(1); + Double p1 = (Double)_environment.getValue(2); + + ISystem system = _environment.getSystem(); + + TreeMap history = system.getHistory(ident); + double time = system.time(); + + history.put(time, value); + + Double key = history.ceilingKey(time-p1); + + return history.get(key); + + } + + }); + model.functions.put("cat", new Fn1(10) { + + @Override + public Object evaluate(IEnvironment _environment, int argc) { + + Double dim = (Double)_environment.getValue(0); + + Array array = new Array(); + for(int i=1;i getHistory(String ident) { + TreeMap result = history.get(ident); + if(result == null) { + result = new TreeMap(); + history.put(ident, result); + } + return result; + } + + @Override + public Object getValue(int key) { + return valueTable[key]; + } + + @Override + public void put(int key, Object value) { + valueTable[key] = value; + } + + public void put(String key, Object value) { + named.put(key, value); + } + + public void setSize(int size) { + this.size = size; + } + + @Override + public int offset() { + return size; + } + + @Override + public ISystem getSystem() { + return this; + } + + @Override + public boolean initial() { + return initial; + } + + public Object evaluateFunction(IEnvironment environment, String name, ArgumentList args) { + return model.evaluateFunction(environment, name, args); + } + + @Override + public double time() { + return time; + } + + double[] valueArray; + int[] valueIndices; + + public void addIndexed(int dimensions[], ArrayList keys, String prefix, int d) { + + if(d == dimensions.length) { + keys.add(prefix); + return; + } + + String prefix2 = prefix; + if(d== 0) prefix2 += "["; + if(d>0) prefix2 += ","; + + for(int i=0;i keys, TIntArrayList indices, Set used) { + + if(!used.add(name)) return; + + if(dimensions == null) { + keys.add(name); + indices.add(index); + } else { + addIndexed(dimensions, keys, name, 0); + for(int i=0;i keys, TIntArrayList indices, Set used) { + addVariable(var.base.name, var.base.index, var.base.dimensions, keys, indices, used); + } + + public String[] getValueKeyArray() { + + ArrayList keys = new ArrayList(); + TIntArrayList indices = new TIntArrayList(); + Set used = new HashSet(); + + for (int i = 0; i < model.assignmentArray.length; i++) { + addVariable(model.assignmentArray[i].target, keys, indices, used); + } + + for (int i = 0; i < model.derivativeArray.length; i++) { + addVariable(model.derivativeArray[i].target, keys, indices, used); + } + + // NOTE: there is room for optimization as parameter values that do not + // change should only be obtained once (and parameter values that do + // change are (possibly) included in assignments or derivatives) + for(int i = 0; i < model.parameterArray.length; i++) { + addVariable(model.parameterArray[i].variable, keys, indices, used); + } + + for(Map.Entry entry : model.copies.entrySet()) { + addVariable(entry.getKey(), entry.getValue().index, entry.getValue().dimensions, keys, indices, used); + } + + valueArray = new double[keys.size()]; + + keyIndexMap.clear(); + for(int i=0;i used = new HashSet(); + + for (int i = 0; i < model.assignmentArray.length; i++) { + Variable v = model.assignmentArray[i].target; + if(!used.add(v.base.name)) continue; + for(int index=0;index entry : model.copies.entrySet()) { + VariableBase base = entry.getValue(); + if(!used.add(entry.getKey())) continue; + for(int index=0;index used = new HashSet(); +// +// for (int i = 0; i < model.assignmentArray.length; i++) { +// Variable v = model.assignmentArray[i].target; +// if(!used.add(v.base.name)) continue; +// for(int index=0;index entry : model.copies.entrySet()) { +// VariableBase base = entry.getValue(); +// if(!used.add(entry.getKey())) continue; +// for(int index=0;index assigned = new HashSet(); + +} -- 2.47.1