public Object acosh(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex) param).acosh(); } else if (param instanceof Number) { double val = ((Number) param).doubleValue(); if (val >= 1.0) { double res = Math.log(val + Math.sqrt(val * val - 1)); return new Double(res); } else { Complex temp = new Complex(((Number) param).doubleValue(), 0.0); return temp.acosh(); } } throw new ParseException("Invalid parameter type"); }
/** * Calculate the average value but removing outliers based on Median Absolute Deviation with a * fixed threshold of 3.0 TODO make the threshold be the first parameter in the list or make a * smarter analysis of method to use, not just MAD, based on the number of data in the set, * variance, etc */ @SuppressWarnings("unchecked") @Override public void run(Stack stack) throws ParseException { checkStack(stack); if (curNumberOfParameters < 1) { throw new ParseException("No arguments for Average MAD - median average deviation"); } // Get the first parameter that has to be the threshold // Double threshold = (Double) stack.pop(); Double threshold = 3.0; Object param; ArrayList<Double> orginalValues = new ArrayList<Double>(); int i = 0; while (i < (curNumberOfParameters)) { param = stack.pop(); if (!(supportNull && param instanceof Null)) { orginalValues.add((Double) param); } i++; } // calculate median Double median = median(orginalValues); ArrayList<Double> absMedianValues = new ArrayList<Double>(); // calculate mad by abs(median - value) for each for (Double value : orginalValues) { absMedianValues.add(Math.abs(value - median)); } Double mad = median(absMedianValues); // select only values in the range of the mad*threshold => removing the // outliers int count = 0; int index = 0; Double sum = new Double(0); while (index < absMedianValues.size()) { if (absMedianValues.get(index) < mad * threshold) { sum += orginalValues.get(index); count++; } index++; } if (index > 0) { stack.push(sum / count); } else { stack.push(new Null()); } }