text:
package org.leores.math;

import java.util.Arrays;
import java.util.Hashtable;

import org.leores.util.Logger;
import org.leores.util.U;

/**
 * Curve fitting class based on the Simplex method in the Minimizer class
 *
 *
 * Notes on fitting polynomial functions:
 * (i) The range of x values should not be too far from 0, especially for
 * higher-order polynomials.
 * For polynomials of 4th order, the average x value should fulfill |xMean| <
 * 2*(xMax-xMin).
 * For polynomials of 5th order or higher, the x range should encompass x=0; and
 * for
 * 7th and 8th order it is desirable to have x=0 near the center of the x range.
 * (ii) In contrast to some fitting algorithms using the normal equations and
 * matrix inversion, the
 * simplex algorithm used here can cope with parameters having very different
 * orders of magnitude,
 * as long as the coefficients of the polynomial are within a reasonable range
 * (say, 1e-80 to 1e80).
 * Thus, it is usually not needed to scale the x values, even for high-order
 * polynomials.
 *
 * Version history:
 *
 * 2008-01-21: Modified to do Gaussian fitting by Stefan Woerz (s.woerz at
 * dkfz.de).
 * 2012-01-30: Modified for external Minimizer class and Calculateable fit by
 * Michael Schmid.
 * - Also fixed incorrect equation string for 'Gamma Variate' & 'Rodbard (NIH
 * Image)',
 * - Added 'Inverse Rodbard', 'Exponential (linear regression)', 'Power (linear
 * regression)'
 * functions and polynomials of order 5-8. Added 'nicely' sorted list of types.
 * - Added absolute error for minimizer to avoid endless minimization if exact
 * fit is possible.
 * - Added 'initialParamVariations' (order of magnitude if parameter variations)
 * -
 * this is important for safer and better convergence.
 * - Linear regression for up to 2 linear parameters, reduces the number of
 * parameters handled
 * by the simplex Minimizer and improves convergence. These parameters can be an
 * offset and
 * either a linear slope or a factor that the full function is multiplied with.
 * 2012-10-07: added GAUSSIAN_NOOFFSET fit type
 * 2012-11-20: Bugfix: exception on Gaussian&Rodbard with initial params, bad
 * initial params for Gaussian
 * 2013-09-24: Added "Exponential Recovery (no offset)" and "Chapman-Richards"
 * (3-parameter) fit types.
 * 2013-10-11: bugfixes, added setStatusAndEsc to show iterations and enable
 * abort by ESC
 */

public class CurveFitter extends Logger implements Calculateable {
	/** Constants for the built-in fit functions */
	public static final int STRAIGHT_LINE = 0, POLY2 = 1, POLY3 = 2, POLY4 = 3, EXPONENTIAL = 4, POWER = 5, LOG = 6, RODBARD = 7, GAMMA_VARIATE = 8, LOG2 = 9, RODBARD2 = 10, EXP_WITH_OFFSET = 11,
			GAUSSIAN = 12, EXP_RECOVERY = 13, INV_RODBARD = 14, EXP_REGRESSION = 15, POWER_REGRESSION = 16, POLY5 = 17, POLY6 = 18, POLY7 = 19, POLY8 = 20, GAUSSIAN_NOOFFSET = 21,
			EXP_RECOVERY_NOOFFSET = 22, CHAPMAN = 23;

	/** Nicer sequence of the built-in function types */
	public static final int[] sortedTypes = { STRAIGHT_LINE, POLY2, POLY3, POLY4, POLY5, POLY6, POLY7, POLY8, POWER, POWER_REGRESSION, EXPONENTIAL, EXP_REGRESSION, EXP_WITH_OFFSET, EXP_RECOVERY,
			EXP_RECOVERY_NOOFFSET, LOG, LOG2, GAUSSIAN, GAUSSIAN_NOOFFSET, RODBARD, RODBARD2, INV_RODBARD, GAMMA_VARIATE, CHAPMAN };

	/** Names of the built-in fit functions */
	public static final String[] fitList = { "Straight Line", "2nd Degree Polynomial", "3rd Degree Polynomial", "4th Degree Polynomial", "Exponential", "Power", "Log", "Rodbard", "Gamma Variate",
			"y = a+b*ln(x-c)", "Rodbard (NIH Image)", "Exponential with Offset", "Gaussian", "Exponential Recovery", "Inverse Rodbard", "Exponential (linear regression)", "Power (linear regression)",
			"5th Degree Polynomial", "6th Degree Polynomial", "7th Degree Polynomial", "8th Degree Polynomial", "Gaussian (no offset)", "Exponential Recovery (no offset)", "Chapman-Richards" }; // fList, doFit(), getNumParams() and makeInitialParamsAndVariations() must also be updated

	/** Equations of the built-in fit functions */
	public static final String[] fList = { "y = a+bx",
			"y = a+bx+cx^2", //STRAIGHT_LINE,POLY2
			"y = a+bx+cx^2+dx^3", "y = a+bx+cx^2+dx^3+ex^4", "y = a*exp(bx)", "y = a*x^b",
			"y = a*ln(bx)", //EXPONENTIAL,POWER,LOG
			"y = d+(a-d)/(1+(x/c)^b)",
			"y = b*(x-a)^c*exp(-(x-a)/d)", //RODBARD,GAMMA_VARIATE
			"y = a+b*ln(x-c)",
			"x = d+(a-d)/(1+(y/c)^b) [y = c*((x-a)/(d-x))^(1/b)]", //LOG2,RODBARD2
			"y = a*exp(-bx) + c",
			"y = a + (b-a)*exp(-(x-c)*(x-c)/(2*d*d))", //EXP_WITH_OFFSET,GAUSSIAN
			"y = a*(1-exp(-b*x)) + c",
			"y = c*((x-a)/(d-x))^(1/b)", //EXP_RECOVERY, INV_RODBARD
			"y = a*exp(bx)",
			"y = a*x^b", //EXP_REGRESSION, POWER_REGRESSION
			"y = a+bx+cx^2+dx^3+ex^4+fx^5", "y = a+bx+cx^2+dx^3+ex^4+fx^5+gx^6", "y = a+bx+cx^2+dx^3+ex^4+fx^5+gx^6+hx^7", "y = a+bx+cx^2+dx^3+ex^4+fx^5+gx^6+hx^7+ix^8",
			"y = a*exp(-(x-b)*(x-b)/(2*c*c)))", //GAUSSIAN_NOOFFSET
			"y = a*(1-exp(-b*x))", //EXP_RECOVERY_NOOFFSET
			"y = a*(1-exp(-b*x))^c" //CHAPMAN
	};

	public double[] p;
	public double x;
	public String sPatNumOut;

	private static final int CUSTOM = 100; // user function defined in macro or plugin
	private static final int GAUSSIAN_INTERNAL = 101; // Gaussian with separate offset & multiplier
	private static final int RODBARD_INTERNAL = 102; // Rodbard with separate offset & multiplier

	private int fitType = -1; // Number of curve type to fit
	private double[] xData, yData; // x,y data to fit
	private double[] xDataSave, yDataSave; //saved original data after fitting modified data
	private int numPoints; // number of data points in actual fit
	private double ySign = 0; // remember sign of y data for power-law fit via regression
	private double sumY = Double.NaN, sumY2 = Double.NaN; // sum(y), sum(y^2) of the data used for fitting
	private int numParams; // number of parameters
	private double[] initialParams; // user specified or estimated initial parameters
	private double[] initialParamVariations; // estimate of range of parameters
	private double[] minimizerInitialParams; // modified initialParams of the minimizer
	private double[] minimizerInitialParamVariations; // modified initialParamVariations of the minimizer
	private double maxRelError = 1e-10;// maximum relative deviation of sum of residuals^2 from minimum
	private long time; // elapsed time in ms
	private int customParamCount; // number of parameters of user-supplied function (macro or plugin)
	private String customFormula; // equation defined in macro or text
	private Calculateable userFunction; // plugin with custom fit function
	private int numRegressionParams;// number of parameters that can be calculated by linear regression
	private int offsetParam = -1; // parameter number: function has this parameter as offset
	private int factorParam = -1; // index of parameter that is slope or multiplicative factor of the function
	private boolean hasSlopeParam; // whether the 'factorParam' is the slope of the function
	private double[] finalParams; // parameters obtained by fit
	private boolean linearRegressionUsed; // whether linear regression alone was used instead of the minimizer
	private boolean restrictPower; // power via linear regression fit: (0,0) requires positive power
	private Minimizer minimizer = new Minimizer();
	private int minimizerStatus = Minimizer.INITIALIZATION_FAILURE; // status of the minimizer after minimizing
	private String errorString; // in case of error before invoking the minimizer
	private static String[] sortedFitList; // names like fitList, but in more logical sequence
	private static Hashtable<String, Integer> namesTable; // converts fitList String into number

	/** Construct a new CurveFitter. */
	public CurveFitter(double[] xData, double[] yData) {
		this.xData = xData;
		this.yData = yData;
		numPoints = xData.length;
	}

	public double p(int i) {
		return p[i];
	}

	public double p(String sI) {
		int i = Integer.parseInt(sI);
		return p[i];
	}

	/**
	 * Perform curve fitting with one of the built-in functions
	 * doFit(fitType) does the fit quietly
	 * Use getStatus() and/or getStatusString() to see whether fitting was
	 * (probably) successful and
	 * getParams() to access the result.
	 */
	public void doFit(int fitType) {
		doFit(fitType, false);
	}

	public void logSettings() {
		log("Simplex Fitting Options");
		log("Function name: " + getName() + "\n" + "Formula: " + getFormula());
		for (int i = 0; i < numParams; i++)
			log("p" + i + ":" + U.valToStr(initialParams[i], sPatNumOut));
		log("Maximum iterations:" + minimizer.getMaxIterations());
		log("Number of restarts:" + minimizer.getMaxRestarts());
		log("Error tolerance [1*10^(-x)]:" + (-(Math.log(maxRelError) / Math.log(10))));
	}

	/**
	 * Perform curve fitting with one of the built-in functions
	 * doFit(fitType, true) pops up a dialog allowing the user to set the
	 * initial
	 * fit parameters and various numbers controlling the Minimizer
	 * Use getStatus() and/or getStatusString() to see whether fitting was
	 * (probably) successful and
	 * getParams() to access the result.
	 */
	public void doFit(int fitType, boolean bLogSettings) {
		if (!(fitType >= STRAIGHT_LINE && fitType < fitList.length || fitType == CUSTOM))
			throw new IllegalArgumentException("Invalid fit type");
		if (fitType == CUSTOM && customFormula == null && userFunction == null)
			throw new IllegalArgumentException("No custom formula!");
		this.fitType = fitType;
		if (isModifiedFitType(fitType)) // these fits don't use the original data and a different fit type (this.fitType)
			if (!prepareModifiedFitType(fitType))
				return;
		numParams = getNumParams();
		if (fitType != CUSTOM)
			getOffsetAndFactorParams();
		//IJ.log("special params: off="+offsetParam+(hasSlopeParam ? " slo=" : " fac=")+factorParam+" numPar="+numParams+" numRegressPar="+numRegressionParams);
		calculateSumYandY2(); // sumY, sumY2 needed for regression, abs Error; R, goodness of modified fit functions
		long startTime = System.currentTimeMillis();
		if (this.fitType == STRAIGHT_LINE) { // no minimizer needed
			finalParams = new double[] { 0, 0, 0 }; // (does not work with 0 initial slope)
			doRegression(finalParams); // fit by regression; save sum(Residuals^2) as last array element
			linearRegressionUsed = true;
		} else { // use simplex minimizer
			minimizer.setFunction(this, numParams - numRegressionParams);
			minimizer.setExtraArrayElements(numRegressionParams); // reserve space for extra parameters if minimizer has fewer paramters
			if (customFormula != null)
				minimizer.setMaximumThreads(1); // macro interpreter does not allow multithreading
			if (!makeInitialParamsAndVariations(fitType)) // also includes some data checking
				return; // initialization failure
			if (bLogSettings) {
				logSettings();
			}
			if (numRegressionParams > 0)
				modifyInitialParamsAndVariations();
			else {
				minimizerInitialParams = initialParams;
				minimizerInitialParamVariations = initialParamVariations;
			}
			startTime = System.currentTimeMillis();
			// The maximum absolute error of the fit must be specified in case the
			// fit function fits perfectly, i.e. the sume of residuals approaches 0.
			// In such a case, the maximum relative error is meaningless and the
			// minimizer would run until it reaches the maximum iteration count.
			double maxAbsError = Math.min(1e-6, maxRelError) * Math.sqrt(sumY2);
			minimizer.setMaxError(maxRelError, maxAbsError);
			//{String s="initVariations:";for(int ii=0;ii<numParams;ii++)s+=" ["+ii+"]:"+IJ.d2s(initialParamVariations[ii],5,9);IJ.log(s);}
			//{String s="minInitVariations:";for(int ii=0;ii<numParams;ii++)s+=" ["+ii+"]:"+IJ.d2s(minimizerInitialParamVariations[ii],5,9);IJ.log(s);}
			//{String s="minInitPars:";for(int ii=0;ii<numParams;ii++)s+=" ["+ii+"]:"+IJ.d2s(minimizerInitialParams[ii],5,9);IJ.log(s);}
			// m i n i m i z a t i o n	of squared residuals
			minimizerStatus = minimizer.minimize(minimizerInitialParams, minimizerInitialParamVariations);
			finalParams = minimizer.getParams();
			if (numRegressionParams > 0)
				minimizerParamsToFullParams(finalParams, false);
		}
		if (isModifiedFitType(fitType)) //params of actual fit to user params
			postProcessModifiedFitType(fitType);

		switch (fitType) { //postprocessing for nicer output:
		case GAUSSIAN: //Gaussians: width (std deviation) should be >0
			finalParams[3] = Math.abs(finalParams[3]);
			break;
		case GAUSSIAN_NOOFFSET:
			finalParams[2] = Math.abs(finalParams[2]);
			break;
		}
		time = System.currentTimeMillis() - startTime;
		p = getParams();
	}

	/**
	 * Fit a function defined as a evaltion String like
	 * "#$p(0)$+$p(1)$*$x$+$p(2)$*LOG($x$)#". Each $p(i)$ should only occur
	 * once. *
	 *
	 * For good performance, it is advisable to set also the typical variation
	 * range of the initial parameters by the
	 * getMinimizer().setInitialParamVariations(double[]) method (especially if
	 * one or more of the initialParams are zero).
	 * Use getStatus() and/or getStatusString() to see whether fitting was
	 * (probably) successful and
	 * getParams() to access the result.
	 */
	public void doCustomFit(String formula, int numParams, double[] initialParams) {
		doCustomFit(null, formula, numParams, initialParams, null, false);
	}

	/**
	 * Fit a function defined in a user plugin implementing the Calculateable
	 * interface.
	 *
	 * Use getStatus() and/or getStatusString() to see whether fitting was
	 * (probably) successful and getParams() to access the result.
	 *
	 * @param userFunction
	 *            A plugin where the fit function is defined by the
	 *            calculate(params, x) method. This function must allow
	 *            simultaneous calls in multiple threads.
	 * @param numParams
	 *            Number of parameters of the fit function.
	 * @param initialParams
	 *            Starting point for the parameters; may be null (than values
	 *            of 0 are used). The fit function with these parameters must
	 *            not return NaN for any of the data points given in the
	 *            constructor (xData).
	 * @param showSettings
	 *            whether log initial parameters and a few numbers controlling
	 *            the minimizer.
	 */
	public void doCustomFit(Calculateable userFunction, int numParams, double[] initialParams) {
		doCustomFit(userFunction, null, numParams, initialParams, null, false);
	}

	/**
	 * Fit a function defined in a user plugin implementing the Calculateable
	 * interface
	 *
	 * Use getStatus() and/or getStatusString() to see whether fitting was
	 * (probably) successful and
	 * getParams() to access the result.
	 *
	 * @param userFunction
	 *            A plugin where the fit function is defined by the
	 *            calculate(params, x) method.
	 *            This function must allow simultaneous calls in multiple
	 *            threads.
	 * @param numParams
	 *            Number of parameters of the fit function.
	 * @param formula
	 *            A String describing the fit formula, may be null.
	 * @param initialParams
	 *            Starting point for the parameters; may be null (than values
	 *            of 0 are used). The fit function with these parameters must
	 *            not return NaN for any of the data points given in the
	 *            constructor (xData).
	 * @param initialParamVariations
	 *            Each parameter is initially varied by up to +/- this value.
	 *            If not given (null), initial variations are taken as
	 *            10% of initial parameter value or 0.01 for parameters that are
	 *            zero.
	 *            When this array is given, all elements must be positive
	 *            (nonzero).
	 *            See Minimizer.minimize for details.
	 * @param showSettings
	 *            whether log initial parameters and a few numbers controlling
	 *            the minimizer.
	 */
	public void doCustomFit(Calculateable userFunction, String formula, int numParams, double[] initialParams, double[] initialParamVariations, boolean showSettings) {
		this.userFunction = userFunction;
		this.customParamCount = numParams;
		this.customFormula = formula;
		this.initialParams = initialParams;
		this.initialParamVariations = initialParamVariations;
		doFit(CUSTOM, showSettings);
	}

	/**
	 * Sets the initial parameters, which override the default initial
	 * parameters.
	 */
	public void setInitialParameters(double[] initialParams) {
		this.initialParams = initialParams;
	}

	/**
	 * Returns a reference to the Minimizer used, for accessing Minimizer
	 * methods directly.
	 * Note that no Minimizer is used if fitType is any of STRAIGHT_LINE,
	 * EXP_REGRESSION,
	 * and POWER_REGRESSION.
	 */
	public Minimizer getMinimizer() {
		return minimizer;
	}

	/**
	 * For improved fitting performance when using a custom fit formula, one may
	 * specify parameters that can be calculated directly by linear regression.
	 * For values not used, set the index to -1
	 *
	 * @param offsetParam
	 *            Index of a parameter that is a pure offset:
	 *            E.g. '0' if f(p0, p1, p2...) = p0 + function(p1, p2, ...).
	 * @param multiplyParam
	 *            Index of a parameter that is purely multiplicative.
	 *            E.g. multiplyParams=1 if f(p0, p1, p2, p3...) can be expressed
	 *            as
	 *            p1*func(p0, p2, p3, ...) or p0 +p1*func(p0, p2, p3, ...) with
	 *            '0' being
	 *            the offsetparam.
	 * @param slopeParam
	 *            Index of a parameter that is multiplied with x and then summed
	 *            to the function.
	 *            E.g. '1' for f(p0, p1, p2, p3...) = p1*x + func(p0, p2, p3,
	 *            ...)
	 *            Only one, multiplyParam and slopeParam can be used (ie.e, the
	 *            other
	 *            should be set to -1)
	 */
	public void setOffsetMultiplySlopeParams(int offsetParam, int multiplyParam, int slopeParam) {
		this.offsetParam = offsetParam;
		hasSlopeParam = slopeParam >= 0;
		factorParam = hasSlopeParam ? slopeParam : multiplyParam;
		numRegressionParams = 0;
		if (offsetParam >= 0)
			numRegressionParams++;
		if (factorParam >= 0)
			numRegressionParams++;
	}

	/**
	 * Get number of parameters for current fit formula
	 * Do not use before 'doFit', because the fit function would be undefined.
	 */
	public int getNumParams() {
		switch (fitType) {
		case STRAIGHT_LINE:
			return 2;
		case POLY2:
			return 3;
		case POLY3:
			return 4;
		case POLY4:
			return 5;
		case POLY5:
			return 6;
		case POLY6:
			return 7;
		case POLY7:
			return 8;
		case POLY8:
			return 9;
		case EXPONENTIAL:
		case EXP_REGRESSION:
			return 2;
		case POWER:
		case POWER_REGRESSION:
			return 2;
		case EXP_RECOVERY_NOOFFSET:
			return 2;
		case LOG:
			return 2;
		case LOG2:
			return 3;
		case GAUSSIAN_NOOFFSET:
			return 3;
		case EXP_RECOVERY:
			return 3;
		case CHAPMAN:
			return 3;
		case EXP_WITH_OFFSET:
			return 3;
		case RODBARD:
		case RODBARD2:
		case INV_RODBARD:
		case RODBARD_INTERNAL:
			return 4;
		case GAMMA_VARIATE:
			return 4;
		case GAUSSIAN:
		case GAUSSIAN_INTERNAL:
			return 4;
		case CUSTOM:
			return customParamCount;
		}
		return 0;
	}

	/**
	 * Returns the formula value for parameters 'p' at 'x'.
	 * Do not use before 'doFit', because the fit function would be undefined.
	 */
	public final double f(double[] p, double x) {
		double rtn = Double.NaN;
		this.p = p;
		this.x = x;
		if (fitType != CUSTOM)
			rtn = f(fitType, p, x);
		else {
			if (userFunction != null) { // function defined in plugin
				rtn = userFunction.calculate(p, x);
			} else if (customFormula != null) { // function defined in macro
				rtn = Double.parseDouble(U.eval("#" + customFormula + "#", this));
			}
		}
		return rtn;
	}

	/**
	 * Returns value of built-in 'fitType' formula value for parameters "p" at
	 * "x"
	 */
	public static double f(int fitType, double[] p, double x) {
		switch (fitType) {
		case STRAIGHT_LINE:
			return p[0] + x * p[1];
		case POLY2:
			return p[0] + x * (p[1] + x * p[2]);
		case POLY3:
			return p[0] + x * (p[1] + x * (p[2] + x * p[3]));
		case POLY4:
			return p[0] + x * (p[1] + x * (p[2] + x * (p[3] + x * p[4])));
		case POLY5:
			return p[0] + x * (p[1] + x * (p[2] + x * (p[3] + x * (p[4] + x * p[5]))));
		case POLY6:
			return p[0] + x * (p[1] + x * (p[2] + x * (p[3] + x * (p[4] + x * (p[5] + x * p[6])))));
		case POLY7:
			return p[0] + x * (p[1] + x * (p[2] + x * (p[3] + x * (p[4] + x * (p[5] + x * (p[6] + x * p[7]))))));
		case POLY8:
			return p[0] + x * (p[1] + x * (p[2] + x * (p[3] + x * (p[4] + x * (p[5] + x * (p[6] + x * (p[7] + x * p[8])))))));
		case EXPONENTIAL:
		case EXP_REGRESSION:
			return p[0] * Math.exp(p[1] * x);
		case EXP_WITH_OFFSET:
			return p[0] * Math.exp(-p[1] * x) + p[2];
		case EXP_RECOVERY:
			return p[0] * (1 - Math.exp(-p[1] * x)) + p[2];
		case EXP_RECOVERY_NOOFFSET:
			return p[0] * (1 - Math.exp(-p[1] * x));
		case CHAPMAN: // a*(1-exp(-b*x))^c
			double value = p[0] * (Math.pow((1 - (Math.exp(-p[1] * x))), p[2]));
			//	Log.e("test", "values = " + value);
			return value;
		case GAUSSIAN:
			return p[0] + (p[1] - p[0]) * Math.exp(-(x - p[2]) * (x - p[2]) / (2.0 * p[3] * p[3]));
		case GAUSSIAN_INTERNAL: // replaces GAUSSIAN for the fitting process
			return p[0] + p[1] * Math.exp(-(x - p[2]) * (x - p[2]) / (2.0 * p[3] * p[3]));
		case GAUSSIAN_NOOFFSET:
			return p[0] * Math.exp(-(x - p[1]) * (x - p[1]) / (2.0 * p[2] * p[2]));
		case POWER: // ax^b
		case POWER_REGRESSION:
			return p[0] * Math.pow(x, p[1]);
		case LOG:
			if (x == 0.0)
				return -1000 * p[0];
			return p[0] * Math.log(p[1] * x);
		case RODBARD: { // d+(a-d)/(1+(x/c)^b)
			double ex = Math.pow(x / p[2], p[1]); //(x/c)^b
			return p[3] + (p[0] - p[3]) / (1.0 + ex);
		}
		case RODBARD_INTERNAL: { // d+a/(1+(x/c)^b) , replaces RODBARD of the fitting process
			double ex = Math.pow(x / p[2], p[1]); //(x/c)^b
			return p[3] + p[0] / (1.0 + ex);
		}
		case GAMMA_VARIATE: // b*(x-a)^c*exp(-(x-a)/d)
			if (p[0] >= x)
				return 0.0;
			if (p[1] <= 0)
				return Double.NaN;
			if (p[2] <= 0)
				return Double.NaN;
			if (p[3] <= 0)
				return Double.NaN;

			double pw = Math.pow((x - p[0]), p[2]);
			double e = Math.exp((-(x - p[0])) / p[3]);
			return p[1] * pw * e;
		case LOG2:
			double tmp = x - p[2];
			if (tmp <= 0)
				return Double.NaN;
			return p[0] + p[1] * Math.log(tmp);
		case INV_RODBARD: // c*((x-a)/(d-x))^(1/b), the inverse Rodbard function
		case RODBARD2: // also used after the 'Rodbard NIH Image' fit
			double y;
			if (p[3] - x < 2 * Double.MIN_VALUE || x < p[0]) // avoid x>=d (singularity) and x<a (negative exponent)
				y = fitType == INV_RODBARD ? Double.NaN : 0.0;
			else {
				y = (x - p[0]) / (p[3] - x); //(x-a)/(d-x) = ( (a-d)/(x-d) -1 )
				y = Math.pow(y, 1.0 / p[1]); //y=y**(1/b)
				y = y * p[2];
			}
			return y;
		default:
			return 0.0;
		}
	}

	/**
	 * Get the result of fitting, i.e. the set of parameter values for the best
	 * fit.
	 * Note that the array returned may have more elements than numParams;
	 * ignore the rest.
	 * May return an array with only NaN values if the minimizer could not start
	 * properly,
	 * i.e., if getStatus() returns Minimizer.INITILIZATION_FAILURE.
	 * See Minimizer.getParams() for details.
	 */
	public double[] getParams() {
		return finalParams == null ? minimizer.getParams() : finalParams; //if we have no result, take all_NaN result from the Minimizer
	}

	/**
	 * Returns residuals array, i.e., differences between data and curve.
	 * The residuals are with respect to the real data, also for fit types where
	 * the data are
	 * modified before fitting (power&exp fit by linear regression, 'Rodbard NIH
	 * Image' ).
	 * This is in contrast to sum of squared residuals, which is for the fit
	 * that was actually done.
	 */
	public double[] getResiduals() {
		double[] params = getParams();
		double[] residuals = new double[xData.length];
		for (int i = 0; i < xData.length; i++)
			residuals[i] = yData[i] - f(params, xData[i]);
		return residuals;
	}

	/*
	 * Get the sum of the residuals (may be NaN if the minimizer could not start
	 * properly
	 * i.e., if getStatus() returns Minimizer.INITILIZATION_FAILURE).
	 */
	public double getSumResidualsSqr() {
		return getParams()[numParams]; // value is stored as last element by the minimizer
	}

	/**
	 * Returns the standard deviation of the residuals.
	 * Here, the standard deviation is defined here as the root-mean-square of
	 * the residuals
	 * times sqrt(n/(n-1)); where n is the number of points.
	 */
	public double getSD() {
		double[] residuals = getResiduals();
		int n = residuals.length;
		double sum = 0.0, sum2 = 0.0;
		for (int i = 0; i < n; i++) {
			sum += residuals[i];
			sum2 += residuals[i] * residuals[i];
		}
		double stdDev = (sum2 - sum * sum / n); //sum of squared residuals
		return Math.sqrt(stdDev / (n - 1.0));
	}

	/**
	 * Returns R^2, where 1.0 is best.
	 *
	 * <pre>
	 * 	 r^2 = 1 - SSE/SSD
	 *
	 * 	 where:	 SSE = sum of the squared errors
	 * 				 SSD = sum of the squared deviations about the mean.
	 * </pre>
	 *
	 * For power, exp by linear regression and 'Rodbard NIH Image', this is
	 * calculated for the
	 * fit actually done, not for the residuals of the original data.
	 */
	public double getRSquared() {
		if (Double.isNaN(sumY))
			calculateSumYandY2();
		double sumMeanDiffSqr = sumY2 - sumY * sumY / numPoints;
		double rSquared = 0.0;
		if (sumMeanDiffSqr > 0.0)
			rSquared = 1.0 - getSumResidualsSqr() / sumMeanDiffSqr;
		return rSquared;
	}

	/**
	 * Get a measure of "goodness of fit" where 1.0 is best.
	 * Approaches R^2 if the number of points is much larger than the number of
	 * fit parameters.
	 * For power, exp by linear regression and 'Rodbard NIH Image', this is
	 * calculated for the
	 * fit actually done, not for the residuals of the original data.
	 */
	public double getFitGoodness() {
		if (Double.isNaN(sumY))
			calculateSumYandY2();
		double sumMeanDiffSqr = sumY2 - sumY * sumY / numPoints;
		double fitGoodness = 0.0;
		int degreesOfFreedom = numPoints - getNumParams();
		if (sumMeanDiffSqr > 0.0 && degreesOfFreedom > 0)
			fitGoodness = 1.0 - (getSumResidualsSqr() / sumMeanDiffSqr) * numPoints / (double) degreesOfFreedom;

		return fitGoodness;
	}

	public int getStatus() {
		return linearRegressionUsed ? Minimizer.SUCCESS : minimizerStatus;
	}

	/**
	 * Get a short text with a short description of the status. Should be
	 * preferred over
	 * Minimizer.STATUS_STRING[getMinimizer().getStatus()] because
	 * getStatusString()
	 * better explains the problem in some cases of initialization failure (data
	 * not
	 * compatible with the fit function chosen)
	 */
	public String getStatusString() {
		return errorString != null ? errorString : minimizer.STATUS_STRING[getStatus()];
	}

	/**
	 * Get a string with detailed description of the curve fitting results
	 * (several lines,
	 * including the fit parameters).
	 */
	public String getResultString() {
		String resultS = "\nFormula: " + getFormula() + "\nStatus: " + getStatusString();
		if (!linearRegressionUsed)
			resultS += "\nNumber of completed minimizations: " + minimizer.getCompletedMinimizations();
		resultS += "\nNumber of iterations: " + getIterations();
		if (!linearRegressionUsed)
			resultS += " (max: " + minimizer.getMaxIterations() + ")";
		resultS += "\nTime: " + time + " ms" + "\nSum of residuals squared: " + U.valToStr(getSumResidualsSqr(), sPatNumOut) + "\nStandard deviation: " + U.valToStr(getSD(), sPatNumOut) + "\nR^2: "
				+ U.valToStr(getRSquared(), sPatNumOut) + "\nParameters:";
		char pChar = 'a';
		double[] pVal = getParams();
		for (int i = 0; i < numParams; i++) {
			resultS += "\n	" + pChar + " = " + U.valToStr(pVal[i], sPatNumOut);
			pChar++;
		}
		return resultS;
	}

	/**
	 * Return the result formula when the fitting is done using customized
	 * formula (via doCustomFit(String formula, int numParams, double[]
	 * initialParams) or doCustomFit(Calculateable userFunction, String formula,
	 * int numParams, double[] initialParams, double[] initialParamVariations,
	 * boolean showSettings) with a not null formula). When customFormula==null,
	 * the function returns null.
	 */
	public String getResultFormula() {
		String rtn = customFormula;
		if (rtn != null) {
			rtn = rtn.replace("$x$", "x");
			rtn = U.eval(rtn, this, sPatNumOut);
		}
		return rtn;
	}

	/**
	 * Set maximum number of simplex restarts to do. See
	 * Minimizer.setMaxRestarts for details.
	 */
	public void setRestarts(int maxRestarts) {
		minimizer.setMaxRestarts(maxRestarts);
	}

	/**
	 * Set the maximum error. by which the sum of residuals may deviate from the
	 * true value
	 * (relative w.r.t. full sum of rediduals). Possible range: 0.1 ... 10^-16
	 */
	public void setMaxError(double maxRelError) {
		if (Double.isNaN(maxRelError))
			return;
		if (maxRelError > 0.1)
			maxRelError = 0.1;
		if (maxRelError < 1e-16)
			maxRelError = 1e-16; // can't be less than numerical accuracy
		this.maxRelError = maxRelError;
	}

	/**
	 * Create output on the number of iterations in the ImageJ Status line, e.g.
	 * "<ijStatusString> 50 (max 750); ESC to stop"
	 *
	 * @param ijStatusString
	 *            Displayed in the beginning of the status message. No display
	 *            if null.
	 *            E.g. "Curve Fit: Iteration "
	 * @param checkEscape
	 *            When true, the Minimizer stops if escape is pressed and the
	 *            status
	 *            becomes ABORTED. Note that checking for ESC does not work in
	 *            the Event Queue thread.
	 */
	public void setStatusAndEsc(String ijStatusString, boolean checkEscape) {
		minimizer.setStatusAndEsc(ijStatusString, checkEscape);
	}

	/**
	 * Get number of iterations performed. Returns 1 in case the fit was done by
	 * linear regression only.
	 */
	public int getIterations() {
		return linearRegressionUsed ? 1 : minimizer.getIterations();
	}

	/**
	 * Get maximum number of iterations allowed (sum of iteration count for all
	 * restarts)
	 */
	public int getMaxIterations() {
		return minimizer.getMaxIterations();
	}

	/**
	 * Set maximum number of iterations allowed (sum of iteration count for all
	 * restarts)
	 */
	public void setMaxIterations(int maxIter) {
		minimizer.setMaxIterations(maxIter);
	}

	/**
	 * Get maximum number of simplex restarts to do. See
	 * Minimizer.setMaxRestarts for details.
	 */
	public int getRestarts() {
		return minimizer.getMaxRestarts();
	}

	/**
	 * Returns the status of the Minimizer after doFit. Minimizer.SUCCESS
	 * indicates a
	 * successful completion. In case of Minimizer.INITIALIZATION_FAILURE,
	 * fitting could
	 * not be performed because the data and/or initial parameters are not
	 * compatible
	 * with the function value. In that case, getStatusString may explain the
	 * problem.
	 * For further status codes indicating problems during fitting, see the
	 * status codes
	 * of the Minimzer class.
	 */

	/** returns the array with the x data */
	public double[] getXPoints() {
		return xData;
	}

	/** returns the array with the y data */
	public double[] getYPoints() {
		return yData;
	}

	/** returns the code of the fit type of the fit performed */
	public int getFit() {
		return fitType;
	}

	/** returns the name of the fit function of the fit performed */
	public String getName() {
		if (fitType == CUSTOM)
			return "User-defined";
		if (fitType == GAUSSIAN_INTERNAL)
			fitType = GAUSSIAN;
		else if (fitType == RODBARD_INTERNAL)
			fitType = RODBARD;
		return fitList[fitType];
	}

	/** returns a String with the formula of the fit function used */
	public String getFormula() {
		if (fitType == CUSTOM)
			return customFormula;
		else
			return fList[fitType];
	}

	/** Returns an array of fit names with nicer sorting */
	public static String[] getSortedFitList() {
		if (sortedFitList == null) {
			String[] l = new String[fitList.length];
			for (int i = 0; i < fitList.length; i++)
				sortedFitList[i] = fitList[sortedTypes[i]];
			sortedFitList = l;
		}
		return sortedFitList;
	}

	/**
	 * Returns the code for a fit with given name as defined in fitList, or -1
	 * if not found
	 */
	public static int getFitCode(String fitName) {
		if (namesTable == null) {
			Hashtable<String, Integer> h = new Hashtable<String, Integer>();
			for (int i = 0; i < fitList.length; i++)
				h.put(fitList[i], new Integer(i));
			namesTable = h;
		}
		Integer i = (Integer) namesTable.get(fitName);
		return i != null ? i.intValue() : -1;
	}

	/**
	 * This function is called by the Minimizer and calculates the sum of
	 * squared
	 * residuals for given parameters.
	 * To improve the efficiency, simple linear dependencies are solved directly
	 * by linear regression; in that case the corresponding parameters are
	 * modified.
	 * This effectively reduces the number of free parameters by one or two and
	 * thereby
	 * significantly improves the performance of minimization.
	 */
	public final double calculate(double[] params, double dummy) {
		double sumResidualsSqr = 0.0;
		if (numRegressionParams == 0) { // simply calculate sum of residuals
			for (int i = 0; i < numPoints; i++) {
				double fValue = f(params, xData[i]);
				sumResidualsSqr += sqr(fValue - yData[i]);
			}
			//IJ.log(IJ.d2s(params[0],3,5)+","+IJ.d2s(params[1],3,5)+": r="+IJ.d2s(sumResidualsSqr,3,5)+Thread.currentThread().getName() );

		} else { // handle simple linear dependencies by linear regression:
			//if(getIterations()<1){String s="minimizerPar:";for(int ii=0;ii<=numParams;ii++)s+=" ["+ii+"]:"+IJ.d2s(params[ii],5,9);IJ.log(s);}
			minimizerParamsToFullParams(params, true);
			doRegression(params);
			sumResidualsSqr = fullParamsToMinimizerParams(params);
		}
		return sumResidualsSqr;
	}

	/**
	 * For fits where linear regression is used to reduce the number of
	 * parameters handled
	 * by the Minimizer, convert Minimizer parameters to the complete set of
	 * parameters.
	 * When not for calculating regression, we use the sum of squared residuals,
	 * offset and multiplication factor stored in the extra array elements:
	 * The Minimizer stores the sum of squared residuals directly behind its
	 * last parameter.
	 * The next element is the value of the offsetParam (if any).
	 * The final element is the value of the factorParam (if any).
	 */
	private void minimizerParamsToFullParams(double[] params, boolean forRegression) {
		boolean shouldTransformToSmallerParams = false;
		double offset = 0;
		double factor = hasSlopeParam ? 0 : 1; //for regression, calculate function value without x*slope, but multiplied with 1
		double sumResidualsSqr = 0;
		if (!forRegression) { // recover regression-calculated parameters from extra array elements
			int i = params.length - 1;
			if (factorParam >= 0)
				factor = params[i--];
			if (offsetParam >= 0)
				offset = params[i];
			sumResidualsSqr = params[numParams - numRegressionParams]; // sum of squared residuals has been calculated already
			params[numParams] = sumResidualsSqr; // ... and is now stored in its new (proper) place
		}
		// move array elements to position in array with full number of parameters
		for (int i = numParams - 1, iM = numParams - numRegressionParams - 1; i >= 0; i--) {
			if (i == offsetParam)
				params[i] = offset;
			else if (i == factorParam)
				params[i] = factor;
			else
				params[i] = params[iM--];
		}
		params[numParams] = sumResidualsSqr;
	}

	/**
	 * Determine sum of squared residuals with linear regression.
	 * The sum of squared residuals is written to the array element with index
	 * 'numParams',
	 * the offset and factor params (if any) are written to their proper
	 * positions in the
	 * params array
	 */
	private void doRegression(double[] params) {
		double sumX = 0, sumX2 = 0, sumXY = 0; //sums for regression; here 'x' are function values
		double sumY = 0, sumY2 = 0; //only calculated for 'slope', otherwise we use the values calculated already
		for (int i = 0; i < numPoints; i++) {
			double fValue = fitType == STRAIGHT_LINE ? 0 : f(params, xData[i]); // function value
			if (Double.isNaN(fValue)) { //check for NaN now; later we need NaN checking for division-by-zero check.
				params[numParams] = Double.NaN;
				return; //sum of squared residuals is NaN if any value is NaN
			}
			//if(getIterations()==0)IJ.log(xData[i]+"\t"+yData[i]+"\t"+fValue); //x,y,function
			if (hasSlopeParam) { // fit y = offset + slope*x + function(of other params)
				double x = xData[i];
				double y = yData[i] - fValue;
				sumX += x;
				sumX2 += x * x;
				sumXY += x * y;
				sumY2 += y * y;
				sumY += y;
			} else { // fit y = offset + factor * function(of other params)
				double x = fValue;
				double y = yData[i];
				sumX += fValue;
				sumX2 += fValue * fValue;
				sumXY += fValue * yData[i];
			}
		}
		if (!hasSlopeParam) {
			sumY = this.sumY;
			sumY2 = this.sumY2;
		}
		double factor = 0; // factor or slope
		double sumResidualsSqr = 0;
		if (offsetParam < 0) { // only 'factor' parameter, no offset:
			factor = sumXY / sumX2;
			if (Double.isNaN(factor) || Double.isInfinite(factor))
				factor = 0; // all 'x' values are 0, any factor (slope) will fit
			sumResidualsSqr = sumY2 + factor * (factor * sumX2 - 2 * sumXY);
			if (sumResidualsSqr < 2e-15 * sumY2)
				sumResidualsSqr = 2e-15 * sumY2;
		} else { // full linear regression or offset only. Slope is named 'factor' here
			if (factorParam >= 0) {
				factor = (sumXY - sumX * sumY / numPoints) / (sumX2 - sumX * sumX / numPoints);
				if (restrictPower & factor <= 0) // power-law fit with (0,0) point: power must be >0
					factor = 1e-100;
				else if (Double.isNaN(factor) || Double.isInfinite(factor))
					factor = 0; // all 'x' values are equal, any factor (slope) will fit
			}
			double offset = (sumY - factor * sumX) / numPoints;
			params[offsetParam] = offset;
			sumResidualsSqr = sqr(factor) * sumX2 + numPoints * sqr(offset) + sumY2 + 2 * factor * offset * sumX - 2 * factor * sumXY - 2 * offset * sumY;
			// check for accuracy problem: large difference of small numbers?
			// Don't report unrealistic or even negative values, otherwise minimization could lead
			// into parameters where we have a numeric problem
			if (sumResidualsSqr < 2e-15 * (sqr(factor) * sumX2 + numPoints * sqr(offset) + sumY2))
				sumResidualsSqr = 2e-15 * (sqr(factor) * sumX2 + numPoints * sqr(offset) + sumY2);
			//if(){IJ.log("sumX="+sumX+" sumX2="+sumX2+" sumXY="+sumXY+" factor="+factor+" offset=="+offset);}
		}
		params[numParams] = sumResidualsSqr;
		if (factorParam >= 0)
			params[factorParam] = factor;
	}

	/**
	 * Convert full set of parameters to minimizer parameters and returns the
	 * sum of residuals squared.
	 * The last array elements, not used by the minimizer, are the offset and
	 * factor parameters (if any)
	 */
	private double fullParamsToMinimizerParams(double[] params) {
		double offset = offsetParam >= 0 ? params[offsetParam] : 0;
		double factor = factorParam >= 0 ? params[factorParam] : 0;
		double sumResidualsSqr = params[numParams];

		for (int i = 0, iNew = 0; i < numParams; i++)
			// leave only the parameters for the minimizer in the beginning of the array
			if (i != factorParam && i != offsetParam)
				params[iNew++] = params[i];
		int i = params.length - 1;
		if (factorParam >= 0)
			params[i--] = factor;
		if (offsetParam >= 0)
			params[i--] = offset;
		params[i--] = sumResidualsSqr;
		return sumResidualsSqr;
	}

	/**
	 * In case one or two parameters are calculated by regression and not by the
	 * minimizer:
	 * Make modified initialParams and initialParamVariations for the Minimizer
	 */
	private void modifyInitialParamsAndVariations() {
		minimizerInitialParams = initialParams.clone();
		minimizerInitialParamVariations = initialParamVariations.clone();
		if (numRegressionParams > 0) // convert to shorter arrays with only the parameters used by the minimizer
			for (int i = 0, iNew = 0; i < numParams; i++)
				if (i != factorParam && i != offsetParam) {
					minimizerInitialParams[iNew] = minimizerInitialParams[i];
					minimizerInitialParamVariations[iNew] = minimizerInitialParamVariations[i];
					iNew++;
				}
	}

	/**
	 * Estimate values for initial parameters and their typical range for the
	 * built-in
	 * function types. For fits with modifications for regression, 'fitType' is
	 * still
	 * the type of the original (unmodified) fit.
	 * Also checks for x values being non-negative for fit types that require
	 * this,
	 * and returns false if the data cannot be fitted because of negative x.
	 * In such a case, 'errorString' contains a message about the problem.
	 */
	private boolean makeInitialParamsAndVariations(int fitType) {
		boolean hasInitialParams = initialParams != null;
		boolean hasInitialParamVariations = initialParamVariations != null;
		if (!hasInitialParams) {
			initialParams = new double[numParams];
			if (fitType == CUSTOM) {
				for (int i = 0; i < numParams; i++)
					initialParams[i] = 1.0;
			}
		}
		if (fitType == CUSTOM)
			return true; // no way to guess initial parameters or initialParamVariations
		if (!hasInitialParamVariations)
			initialParamVariations = new double[numParams];

		// Calculate some things that might be useful for predicting parameters
		double firstx = xData[0];
		double firsty = yData[0];
		double lastx = xData[numPoints - 1];
		double lasty = yData[numPoints - 1];
		double xMin = firstx, xMax = firstx; //with this initialization, the loop starts at 1, not 0
		double yMin = firsty, yMax = firsty;
		double xMean = firstx, yMean = firsty;
		double xOfMax = firstx;
		for (int i = 1; i < numPoints; i++) {
			xMean += xData[i];
			yMean += yData[i];
			if (xData[i] > xMax)
				xMax = xData[i];
			if (xData[i] < xMin)
				xMin = xData[i];
			if (yData[i] > yMax) {
				yMax = yData[i];
				xOfMax = xData[i];
			}
			if (yData[i] < yMin)
				yMin = yData[i];
		}
		xMean /= numPoints;
		yMean /= numPoints;

		double slope = (lasty - firsty) / (lastx - firstx);
		if (Double.isNaN(slope) || Double.isInfinite(slope))
			slope = 0;
		double yIntercept = yMean - slope * xMean;

		//We cannot fit the following cases because we would always get NaN function values
		if (xMin < 0 && (fitType == POWER || fitType == CHAPMAN)) {
			errorString = "Cannot fit " + fitList[fitType] + " when x<0";
			return false;
		} else if (xMin < 0 && xMax > 0 && fitType == RODBARD) {
			errorString = "Cannot fit " + fitList[fitType] + " to mixture of x<0 and x>0";
			return false;
		} else if (xMin <= 0 && fitType == LOG) {
			errorString = "Cannot fit " + fitList[fitType] + " when x<=0";
			return false;
		}

		if (!hasInitialParams) {
			switch (fitType) {
			//case POLY2: case POLY3: case POLY4: case POLY5: case POLY6: case POLY7: case POLY8:
			// offset&slope calculated via regression; leave the others at 0

			// also for the other cases, some initial parameters are unused; only to show them with 'showSettings'
			case EXPONENTIAL: // a*exp(bx)   assuming change by factor of e between xMin & xMax
				initialParams[1] = 1.0 / (xMax - xMin + 1e-100) * Math.signum(yMean) * Math.signum(slope);
				initialParams[0] = yMean / Math.exp(initialParams[1] * xMean); //don't care, done by regression
				break;
			case EXP_WITH_OFFSET: // a*exp(-bx) + c	assuming b>0, change by factor of e between xMin & xMax
			case EXP_RECOVERY: // a*(1-exp(-bx)) + c
				initialParams[1] = 1. / (xMax - xMin + 1e-100);
				initialParams[0] = (yMax - yMin) / Math.exp(initialParams[1] * xMean) * Math.signum(slope) * fitType == EXP_RECOVERY ? 1 : -1; // don't care, we will do this via regression
				initialParams[2] = 0.5 * yMean; // don't care, we will do this via regression
				break;
			case EXP_RECOVERY_NOOFFSET: // a*(1-exp(-bx))
				initialParams[1] = 1.0 / (xMax - xMin + 1e-100) * Math.signum(yMean) * Math.signum(slope);
				initialParams[0] = yMean / Math.exp(initialParams[1] * xMean); //don't care, done by regression
				break;
			case POWER: // ax^b, assume linear for the beginning
				initialParams[0] = yMean / (Math.abs(xMean + 1e-100)); // don't care, we will do this via regression
				initialParams[1] = 1.0;
				break;
			case LOG: // a*ln(bx), assume b=e/xMax
				initialParams[0] = yMean; // don't care, we will do this via regression
				initialParams[1] = Math.E / (xMax + 1e-100);
				break;
			case LOG2: // y = a+b*ln(x-c)
				initialParams[0] = yMean; // don't care, we will do this via regression
				initialParams[1] = (yMax - yMin) / (xMax - xMin + 1e-100); // don't care, we will do this via regression
				initialParams[2] = Math.min(0., -xMin - 0.1 * (xMax - xMin) - 1e-100);
				break;
			case RODBARD: // d+(a-d)/(1+(x/c)^b)
				initialParams[0] = firsty; // don't care, we will do this via regression
				initialParams[1] = 1.0;
				initialParams[2] = xMin < 0 ? xMin : xMax; //better than xMean;
				initialParams[3] = lasty; // don't care, we will do this via regression
				break;
			case INV_RODBARD:
			case RODBARD2: // c*((x-a)/(d-x))^(1/b)
				initialParams[0] = xMin - 0.1 * (xMax - xMin);
				initialParams[1] = 1.0;
				initialParams[2] = yMax; // don't care, we will do this via regression
				initialParams[3] = xMax + (xMax - xMin);
				break;
			case GAMMA_VARIATE: // // b*(x-a)^c*exp(-(x-a)/d)
				//	First guesses based on following observations (naming the 'x' coordinate 't'):
				//	t0 [a] = time of first rise in gamma curve - so use the user specified first x value
				//	tmax = t0 + c*d where tmX is the time of the peak of the curve
				//	therefore an estimate for c and d is sqrt(tm-t0)
				//	K [a] can now be calculated from these estimates
				initialParams[0] = xMin;
				double cd = xOfMax - xMin;
				if (cd < 0.1 * (xMax - xMin))
					cd = 0.1 * (xMax - xMin);
				initialParams[2] = Math.sqrt(cd);
				initialParams[3] = Math.sqrt(cd);
				initialParams[1] = yMax / (Math.pow(cd, initialParams[2]) * Math.exp(-cd / initialParams[3])); // don't care, we will do this via regression
				break;
			case GAUSSIAN: // a + (b-a)*exp(-(x-c)^2/(2d^2))
				initialParams[0] = yMin; //actually don't care, we will do this via regression
				initialParams[1] = yMax; //actually don't care, we will do this via regression
				initialParams[2] = xOfMax;
				initialParams[3] = 0.39894 * (xMax - xMin) * (yMean - yMin) / (yMax - yMin + 1e-100);
				break;
			case GAUSSIAN_NOOFFSET: // a*exp(-(x-b)^2/(2c^2))
				initialParams[0] = yMax; //actually don't care, we will do this via regression
				initialParams[1] = xOfMax; //actually don't care, we will do this via regression
				initialParams[2] = 0.39894 * (xMax - xMin) * yMean / (yMax + 1e-100);
				break;
			case CHAPMAN: // a*(1-exp(-b*x))^c
				initialParams[0] = yMax;
				initialParams[2] = 1.5; // just assuming any reasonable value
				for (int i = 1; i < numPoints; i++)
					//find when we reach 50% of maximum
					if (yData[i] > 0.5 * yMax) { //approximately (1-exp(-1))^1.5 = 0.5
						initialParams[1] = 1. / xData[i];
						break;
					}
				if (Double.isNaN(initialParams[1]) || initialParams[1] > 1000. / xMax) //in case an outlier at the beginning has fooled us
					initialParams[1] = 10. / xMax;
				break;
			//no case CUSTOM: here, was done above
			}
		}
		if (!hasInitialParamVariations) { // estimate initial range for parameters
			for (int i = 0; i < numParams; i++)
				initialParamVariations[i] = 0.1 * initialParams[i]; //default, should be overridden if it can be zero
			switch (fitType) {
			case POLY2:
			case POLY3:
			case POLY4:
			case POLY5:
			case POLY6:
			case POLY7:
			case POLY8:
				double xFactor = 0.5 * Math.max(Math.abs(xMax + xMin), (xMax - xMin));
				initialParamVariations[numParams - 1] = (yMax - yMin) / (Math.pow(0.5 * (xMax - xMin), numParams - 1) + 1e-100);
				for (int i = numParams - 2; i >= 0; i--)
					initialParamVariations[i] = initialParamVariations[i + 1] * xFactor;
				break;
			case EXPONENTIAL: // a*exp(bx)		  a (and c) is calculated by regression
			case EXP_WITH_OFFSET: // a*exp(-bx) + c
			case EXP_RECOVERY: // a*(1-exp(-bx)) + c
				initialParamVariations[1] = 0.1 / (xMax - xMin + 1e-100);
				break;
			// case CHAPMAN:            // a*(1-exp(-b*x))^c use default (10% of value) for b, c
			// case POWER:				// ax^b; use default for b
			// case LOG:				// a*ln(bx); use default for b
			// case LOG2:				// y = a+b*ln(x-c); use default for c
			case RODBARD: // d+(a-d)/(1+(x/c)^b); a and d calculated by regression
				initialParamVariations[2] = 0.5 * Math.max((xMax - xMin), Math.abs(xMean));
				initialParamVariations[3] = 0.5 * Math.max(yMax - yMin, Math.abs(yMax));
				break;
			case INV_RODBARD: // c*((x-a)/(d-x))^(1/b); c calculated by regression
				initialParamVariations[0] = 0.01 * Math.max(xMax - xMin, Math.abs(xMax));
				initialParamVariations[2] = 0.1 * Math.max(yMax - yMin, Math.abs(yMax));
				initialParamVariations[3] = 0.1 * Math.max((xMax - xMin), Math.abs(xMean));
				break;
			case GAMMA_VARIATE: // // b*(x-a)^c*exp(-(x-a)/d); b calculated by regression
				//	First guesses based on following observations:
				//	t0 [b] = time of first rise in gamma curve - so use the user specified first limit
				//	tm = t0 + a*B [c*d] where tm is the time of the peak of the curve
				//	therefore an estimate for a and B is sqrt(tm-t0)
				//	K [a] can now be calculated from these estimates
				initialParamVariations[0] = 0.1 * Math.max(yMax - yMin, Math.abs(yMax));
				double ab = xOfMax - firstx + 0.1 * (xMax - xMin);
				initialParamVariations[2] = 0.1 * Math.sqrt(ab);
				initialParamVariations[3] = 0.1 * Math.sqrt(ab);
				break;
			case GAUSSIAN: // a + (b-a)*exp(-(x-c)^2/(2d^2)); a,b calculated by regression
				initialParamVariations[2] = 0.2 * initialParams[3]; //(and default for d)
				break;
			case GAUSSIAN_NOOFFSET: // a*exp(-(x-b)^2/(2c^2))
				initialParamVariations[1] = 0.2 * initialParams[2]; //(and default for c)
				break;
			}
		}
		return true;
	}

	/**
	 * Set multiplyParams and offsetParam for built-in functions. This allows us
	 * to use linear
	 * regression, reducing the number of parameters used by the Minimizer by up
	 * to 2, and
	 * improving the speed and success rate of the minimization process
	 */
	private void getOffsetAndFactorParams() {
		offsetParam = -1;
		factorParam = -1;
		hasSlopeParam = false;
		switch (fitType) {
		case STRAIGHT_LINE:
		case POLY2:
		case POLY3:
		case POLY4:
		case POLY5:
		case POLY6:
		case POLY7:
		case POLY8:
			offsetParam = 0;
			factorParam = 1;
			hasSlopeParam = true;
			break;
		case EXPONENTIAL: // a*exp(bx)
			factorParam = 0;
			break;
		case EXP_WITH_OFFSET: // a*exp(-bx) + c
		case EXP_RECOVERY: // a*(1-exp(-bx)) + c
			offsetParam = 2;
			factorParam = 0;
			break;
		case EXP_RECOVERY_NOOFFSET: // a*(1-exp(-bx))
			factorParam = 0;
			break;
		case CHAPMAN: // a*(1-exp(-b*x))^c
			factorParam = 0;
			break;
		case POWER: // ax^b
			factorParam = 0;
			break;
		case LOG: // a*ln(bx)
			factorParam = 0;
			break;
		case LOG2: // y = a+b*ln(x-c)
			offsetParam = 0;
			factorParam = 1;
			break;
		case RODBARD_INTERNAL: // d+a/(1+(x/c)^b)
			offsetParam = 3;
			factorParam = 0;
			break;
		case INV_RODBARD: // c*((x-a)/(d-x))^(1/b)
			factorParam = 2;
			break;
		case GAMMA_VARIATE: // b*(x-a)^c*exp(-(x-a)/d)
			factorParam = 1;
			break;
		case GAUSSIAN_INTERNAL: // a + b*exp(-(x-c)^2/(2d^2))
			offsetParam = 0;
			factorParam = 1;
			break;
		case GAUSSIAN_NOOFFSET: // a*exp(-(x-b)^2/(2c^2))
			factorParam = 0;
			break;
		}
		numRegressionParams = 0;
		if (offsetParam >= 0)
			numRegressionParams++;
		if (factorParam >= 0)
			numRegressionParams++;
	}

	/** calculates the sum of y and y^2 */
	private void calculateSumYandY2() {
		sumY = 0.0;
		sumY2 = 0.0;
		for (int i = 0; i < numPoints; i++) {
			double y = yData[i];
			sumY += y;
			sumY2 += y * y;
		}
	}

	/**
	 * returns whether this a fit type that acutally fits modified data with a
	 * modified function
	 */
	private boolean isModifiedFitType(int fitType) {
		return fitType == POWER_REGRESSION || fitType == EXP_REGRESSION || fitType == RODBARD2 || fitType == GAUSSIAN;
	}

	/**
	 * For fits don't use the original data, prepare modified data and fit type.
	 * Returns false if the data are incompatible with the fit type
	 * In that case, 'errorString' is set to a message explaining the problem
	 */
	private boolean prepareModifiedFitType(int fitType) {
		if (fitType == GAUSSIAN) {
			this.fitType = GAUSSIAN_INTERNAL; // different definition of parameters for using regression
			return true;
		} else if (fitType == RODBARD) {
			this.fitType = RODBARD_INTERNAL; // different definition of parameters for using regression
			return true;
		} else if (fitType == POWER_REGRESSION || fitType == EXP_REGRESSION) {
			if (fitType == POWER_REGRESSION) {
				xDataSave = xData;
				xData = new double[numPoints];
			}
			yDataSave = yData;
			yData = new double[numPoints];
			ySign = 0;
			numPoints = 0; // we may have lower number of points if there is a (0,0) point that we ignore
			for (int i = 0; i < xData.length; i++) {
				double y = yDataSave[i];
				if (fitType == POWER_REGRESSION) {
					double x = xDataSave[i];
					if (x == 0 && y == 0) {
						restrictPower = true;
						continue; // ignore (0,0) point in power law
					}
					if (x <= 0) {
						errorString = "Cannot fit x<=0";
						return false;
					}
					xData[numPoints] = Math.log(x);
				}
				if (ySign == 0)
					ySign = Math.signum(y); //if unknown, determine whether y data are positive or negative
				if (y * ySign <= 0) {
					errorString = "Cannot fit y=0 or mixture of y>0, y<0";
					return false;
				}
				yData[numPoints] = Math.log(y * ySign);
				numPoints++;
			}
			this.fitType = STRAIGHT_LINE;
		} else if (fitType == RODBARD2) { // 'Rodbard (NIH Image)' fit is inverse Rodbard function, by fitting x(y); for compatibility with NIH Image
			xDataSave = xData;
			yDataSave = yData;
			xData = yDataSave; //swap
			yData = xDataSave;
			this.fitType = RODBARD_INTERNAL;
		}
		return true;
	}

	/**
	 * Get correct params and revert xData, yData if fit has been done via
	 * another function
	 */
	private void postProcessModifiedFitType(int fitType) {
		if (fitType == POWER_REGRESSION || fitType == EXP_REGRESSION) // ln y = ln (a*x^b) = ln a + b ln x
			finalParams[0] = ySign * Math.exp(finalParams[0]); //or: ln (+,-)y = ln ((+,-)a*exp(bx)) = ln (+,-)a + bx
		if (fitType == GAUSSIAN) // a + b exp(-...) to  a + (b-a)*exp(-...)
			finalParams[1] += finalParams[0];
		else if (fitType == RODBARD || fitType == RODBARD2) //d+a/(1+(x/c)^b) to d+(a-d)/(1+(x/c)^b)
			finalParams[0] += finalParams[3];

		if (xDataSave != null) {
			xData = xDataSave;
			numPoints = xData.length;
		}
		if (yDataSave != null)
			yData = yDataSave;
		this.fitType = fitType;
	}

	private final double sqr(double d) {
		return d * d;
	}

	/**
	 *
	 * @param initialParams
	 * @param maxIterations
	 *            Maximum iterations
	 * @param maxRestarts
	 *            Number of restarts
	 * @param maxErrorCoefficient
	 *            Error tolerance [1*10^(-x)]
	 */
	private void settInitPars(double initialParams[], int maxIterations, int maxRestarts, int maxErrorCoefficient) {
		if (initialParamVariations == null)
			initialParamVariations = new double[numParams];
		if (initialParams != null) {
			for (int i = 0; i < numParams; i++) {
				double p = initialParams[i];
				if (!Double.isNaN(p)) {
					this.initialParams[i] = p;
					initialParamVariations[i] = Math.max(0.01 * p, 0.001 * initialParamVariations[i]); //assume user-set params are accurate
				}
			}
		}
		if (maxIterations > 0)
			minimizer.setMaxIterations(maxIterations);
		if (maxRestarts >= 0)
			minimizer.setMaxRestarts(maxRestarts);
		setMaxError(Math.pow(10.0, -maxErrorCoefficient));
	}

	/**
	 * Gets index of highest value in an array.
	 *
	 * @param array
	 *            the array.
	 * @return Index of highest value.
	 */
	public static int getMax(double[] array) {
		double max = array[0];
		int index = 0;
		for (int i = 1; i < array.length; i++) {
			if (max < array[i]) {
				max = array[i];
				index = i;
			}
		}
		return index;
	}

}


text:
Application::Application()
{

	window = new ModuleWindow(this,"Window");
	input = new ModuleInput(this,"Input");
	audio = new ModuleAudio(this,"Audio", true);
	scene_intro = new ModuleSceneIntro(this,"Scene_Intro");
	physics3D = new ModulePhysics3D(this,"Physics");
	renderer3D = new ModuleRenderer3D(this,"Renderer");
	camera = new ModuleCamera3D(this,"Camera");
	editor = new ModuleEditor(this,"Editor");
	meshes = new ModuleMesh(this,"Meshes");
	fs = new ModuleFileSystem(this,"File_System");
	tex = new ModuleTextures(this,"Textures");
	go_manager = new ModuleGOManager(this,"GameObject_Manager");

	// The order of calls is very important!
	// Modules will Init() Start() and Update in this order
	// They will CleanUp() in reverse order

	// Main Modules

	AddModule(fs);
	AddModule(window);
	AddModule(camera);
	AddModule(input);
	AddModule(audio);
	AddModule(tex);
	AddModule(physics3D);
	AddModule(meshes);
	AddModule(go_manager);
	AddModule(editor);
	AddModule(scene_intro);
	AddModule(renderer3D);

	//Random for ids
	random_id = new LCG();

	//Timer
	time_manager = new TimeManager();
}

Application::~Application()
{
	list<Module*>::reverse_iterator item = list_modules.rbegin();

	while (item != list_modules.rend())
	{
		delete (*item);
		++item;
	}

	list_modules.clear();

	delete random_id;
	random_id = nullptr;

	delete time_manager;
	time_manager = nullptr;
}

bool Application::Init()
{
	bool ret = true;

	//Load config file
	char* buff;
	if (App->fs->Load("Config.json",&buff) == 0)
	{
		//error
	}
	Json config(buff);
	delete[] buff;

	// Call Init() in all modules
	list<Module*>::iterator it = list_modules.begin();

	while(it != list_modules.end() && ret == true)
	{
		ret = (*it)->Init(config.GetJSON_object((*it)->name.data()));
		++it;
	}

	// After all Init calls we call Start() in all modules

	it = list_modules.begin();

	while(it != list_modules.end() && ret == true)
	{
		if((*it)->IsEnabled())
			ret = (*it)->Start();
		++it;
	}

	capped_ms = 1000 / fps;

	ms_timer.Start();
	last_second_frame_time.Start();
	return ret;
}

// ---------------------------------------------
void Application::PrepareUpdate()
{
	fps_counter++;

	dt = (float)ms_timer.Read() / 1000.0f;
	ms_timer.Start();

	time_manager->Update();
}

// ---------------------------------------------
void Application::FinishUpdate()
{
	// Recap on framecount and fps

	if(last_second_frame_time.Read() > 1000)
	{
		last_second_frame_time.Start();
		last_second_frame_count = fps_counter;
		fps_counter = 0;
	}

	uint32_t last_frame_ms = ms_timer.Read();
	// cap fps
	if(last_frame_ms < capped_ms && capped_ms >0)
	{
		SDL_Delay(capped_ms - last_frame_ms);
	}

	char t[50];
	sprintf_s(t, "Sahelanthropus Engine");
	window->SetTitle(t);
}

// Call PreUpdate, Update and PostUpdate on all modules
update_status Application::Update()
{
	update_status ret = UPDATE_CONTINUE;
	PrepareUpdate();

	list<Module*>::iterator it = list_modules.begin();

	while(it != list_modules.end() && ret == UPDATE_CONTINUE)
	{
		if((*it)->IsEnabled())
			ret = (*it)->PreUpdate(dt);
		++it;
	}

	it = list_modules.begin();

	while(it != list_modules.end() && ret == UPDATE_CONTINUE)
	{
		if((*it)->IsEnabled())
  			ret = (*it)->Update(dt);
		++it;
	}

	it = list_modules.begin();

	while(it != list_modules.end() && ret == UPDATE_CONTINUE)
	{
		if((*it)->IsEnabled())
			ret = (*it)->PostUpdate(dt);
		++it;
	}

	FinishUpdate();
	return ret;
}

bool Application::CleanUp()
{
	bool ret = true;

	list<Module*>::reverse_iterator it = list_modules.rbegin();

	while(it != list_modules.rend() && ret == true)
	{
		ret = (*it)->CleanUp();
		++it;
	}
	return ret;
}

void Application::AddModule(Module* mod)
{
	list_modules.push_back(mod);
}

int Application::GetLastFPS()
{
	return last_second_frame_count;
}

void Application::Log(const char * text)
{

			editor->Log(text);
}

void Application::SetMaxFPS(int max_fps)
{
	fps = max_fps;
	capped_ms = 1000 / fps;
}

bool Application::GameState(STATES state)
{
	bool ret = false;
	switch (state)
	{
	case PLAY:
		time_manager->Play();
		states = PLAY;
		ret = true;
		break;

	case PAUSE:
		time_manager->Pause();
		states = PAUSE;
		ret = true;
		break;

	case STOP:
		time_manager->Stop();
		states = STOP;
		ret = true;
		break;

	case UNKNOWN:
		ret = false;
		break;
	default:
		break;
	}

	return ret;
}

redpajama_set_name: RedPajamaGithub


text:
#pragma once

#include <vector>

#include <pdal/DbReader.hpp>
#include <pdal/StageFactory.hpp>

#include "OciCommon.hpp"

namespace pdal
{

class PDAL_DLL OciReader : public DbReader
{
public:
    OciReader()
    {}

    static void * create();
    static int32_t destroy(void *);
    std::string getName() const;

    Options getDefaultOptions();

private:
    virtual void initialize();
    virtual void processOptions(const Options& options);
    virtual void addDimensions(PointLayoutPtr layout);
    virtual void ready(PointTableRef table)
        { m_atEnd = false; }
    virtual point_count_t read(PointViewPtr view, point_count_t);
    virtual bool eof()
        { return m_atEnd; }

    void validateQuery();
    void defineBlock(Statement statement, BlockPtr block) const;
    pdal::SpatialReference fetchSpatialReference(Statement statement,
        BlockPtr block) const;

    void readBlob(Statement stmt, BlockPtr block);
    point_count_t readDimMajor(PointView& view, BlockPtr block,
        point_count_t numPts);
    point_count_t readPointMajor(PointView& view, BlockPtr block,
        point_count_t numPts);
    char *seekDimMajor(const DimType& d, BlockPtr block);
    char *seekPointMajor(BlockPtr block);
    bool readOci(Statement stmt, BlockPtr block);
    XMLSchema *findSchema(Statement stmt, BlockPtr block);

    Connection m_connection;
    Statement m_stmt;
    BlockPtr m_block;
    std::string m_query;
    std::string m_schemaFile;
    std::string m_connSpec;
    bool m_updatePointSourceId;
    SpatialReference m_spatialRef;
    bool m_atEnd;
    std::map<int32_t, XMLSchema> m_schemas;
    bool m_compression;

    OciReader& operator=(const OciReader&); // not implemented
    OciReader(const OciReader&); // not implemented
};

} // namespace pdal


text:
namespace Pentacorn.Captures.DirectShow.Internals
{
    using System;
    using System.Runtime.InteropServices;

    ///
    /// The IReferenceClock interface provides the reference time for the filter graph.
    ///
    /// Filters that can act as a reference clock can expose this interface. It is also exposed by the System Reference Clock.
    /// The filter graph manager uses this interface to synchronize the filter graph. Applications can use this interface to
    /// retrieve the current reference time, or to request notification of an elapsed time.
    ///
    [ComImport, System.Security.SuppressUnmanagedCodeSecurity,
    Guid( "56a86897-0ad4-11ce-b03a-0020af0ba770" ),
    InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
    internal interface IReferenceClock
    {
        ///
        /// The GetTime method retrieves the current reference time.
        ///
        ///
        /// <param name="pTime">Pointer to a variable that receives the current time, in 100-nanosecond units.</param>
        ///
        /// <returns>Return's HRESULT error code.</returns>
        ///
        [PreserveSig]
        int GetTime( [Out] out long pTime );

        ///
        /// The AdviseTime method creates a one-shot advise request.
        ///
        ///
        /// <param name="baseTime">Base reference time, in 100-nanosecond units. See Remarks.</param>
        /// <param name="streamTime">Stream offset time, in 100-nanosecond units. See Remarks.</param>
        /// <param name="hEvent">Handle to an event, created by the caller.</param>
        /// <param name="pdwAdviseCookie">Pointer to a variable that receives an identifier for the advise request.</param>
        ///
        /// <returns>Return's HRESULT error code.</returns>
        ///
        [PreserveSig]
        int AdviseTime(
            [In] long baseTime,
            [In] long streamTime,
            [In] IntPtr hEvent,
            [Out] out int pdwAdviseCookie );

        ///
        /// The AdvisePeriodic method creates a periodic advise request.
        ///
        ///
        /// <param name="startTime">Time of the first notification, in 100-nanosecond units. Must be greater than zero and less than MAX_TIME.</param>
        /// <param name="periodTime">Time between notifications, in 100-nanosecond units. Must be greater than zero.</param>
        /// <param name="hSemaphore">Handle to a semaphore, created by the caller.</param>
        /// <param name="pdwAdviseCookie">Pointer to a variable that receives an identifier for the advise request.</param>
        ///
        /// <returns>Return's HRESULT error code.</returns>
        ///
        [PreserveSig]
        int AdvisePeriodic(
            [In] long startTime,
            [In] long periodTime,
            [In] IntPtr hSemaphore,
            [Out] out int pdwAdviseCookie );

        ///
        /// The Unadvise method removes a pending advise request.
        ///
        ///
        /// <param name="dwAdviseCookie">Identifier of the request to remove. Use the value returned by IReferenceClock::AdviseTime  or IReferenceClock::AdvisePeriodic  in the pdwAdviseToken parameter.</param>
        ///
        /// <returns>Return's HRESULT error code.</returns>
        ///
        [PreserveSig]
        int Unadvise( [In] int dwAdviseCookie );
    }
}


text:
Extensão para Chrome e Firefox que incorpora novas funcionalidades ao Service Desk da Multidados.

## Histórico de versões

##### versão 1.0

* Filtro por status.

##### versão 1.1

* Correção na verificação das linhas que devem ser filtradas.

##### versão 1.2

* Correção na coluna utilizada para filtrar o status.
* Ajuste nas permissões.

##### versão 1.3

* Ajuste para exibir a quantidade de linhas de cada status.

##### versão 1.4

* Ajuste para adequar a uma correção na versão do Chrome 71 ([referência](https://bugs.chromium.org/p/chromium/issues/detail?id=912069)).


text:
using FluentValidation.Attributes;
using SOURCE.EspaceCandidature.Web.ViewModels.Validators.Candidature.Candidature.Details;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SOURCE.EspaceCandidature.Web.ViewModels.Pages.Candidature.Candidature.Details
{
    [Validator(typeof(CompetencesLinguistiquesViewModelValidator))]
    public class CompetencesLinguistiquesViewModel : ViewModelBase
    {
        public CompetencesLinguistiquesViewModel()
        {
            Competences = new List<CompetenceLinguistiqueViewModel>();
        }

        public long CandidatureID { get; set; }
        public string JustificationLangues { get; set; }
        public IEnumerable<CompetenceLinguistiqueViewModel> Competences { get; set; }
    }
}


text:
public List<Integer> doubling(List<Integer> nums) {
  nums.replaceAll(n -> n * 2);

  return nums;
}


text:
package org.apache.commons.collections4.set;

import java.util.Iterator;
import java.util.NavigableSet;
import org.apache.commons.collections4.set.AbstractSortedSetDecorator;

abstract public class AbstractNavigableSetDecorator<E> extends AbstractSortedSetDecorator<E> implements NavigableSet<E>
{
    protected AbstractNavigableSetDecorator(){}
    protected AbstractNavigableSetDecorator(NavigableSet<E> p0){}
    protected NavigableSet<E> decorated(){ return null; }
    public E ceiling(E p0){ return null; }
    public E floor(E p0){ return null; }
    public E higher(E p0){ return null; }
    public E lower(E p0){ return null; }
    public E pollFirst(){ return null; }
    public E pollLast(){ return null; }
    public Iterator<E> descendingIterator(){ return null; }
    public NavigableSet<E> descendingSet(){ return null; }
    public NavigableSet<E> headSet(E p0, boolean p1){ return null; }
    public NavigableSet<E> subSet(E p0, boolean p1, E p2, boolean p3){ return null; }
    public NavigableSet<E> tailSet(E p0, boolean p1){ return null; }
}


text:
#include "tensorflow/lite/kernels/internal/reference/arg_min_max.h"

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/micro_utils.h"
#include "tensorflow/lite/micro/micro_log.h"

namespace tflite {
namespace ops {
namespace micro {
namespace arg_min_max {

constexpr int kInputTensor = 0;
constexpr int kAxis = 1;
constexpr int kOutputTensor = 0;

template <typename T1, typename T2, typename T3>
inline void ArgMinMaxHelper(const RuntimeShape& input1_shape,
                            const T1* input1_data, const T3* input2_data,
                            const RuntimeShape& output_shape, T2* output_data,
                            bool is_arg_max) {
  if (is_arg_max) {
    reference_ops::ArgMinMax(input1_shape, input1_data, input2_data,
                             output_shape, output_data, micro::Greater());
  } else {
    reference_ops::ArgMinMax(input1_shape, input1_data, input2_data,
                             output_shape, output_data, micro::Less());
  }
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node, bool is_arg_max) {
  const TfLiteEvalTensor* input =
      tflite::micro::GetEvalInput(context, node, kInputTensor);
  const TfLiteEvalTensor* axis =
      tflite::micro::GetEvalInput(context, node, kAxis);
  TfLiteEvalTensor* output =
      tflite::micro::GetEvalOutput(context, node, kOutputTensor);

#define TF_LITE_ARG_MIN_MAX(data_type, axis_type, output_type)       \
  ArgMinMaxHelper(tflite::micro::GetTensorShape(input),              \
                  tflite::micro::GetTensorData<data_type>(input),    \
                  tflite::micro::GetTensorData<axis_type>(axis),     \
                  tflite::micro::GetTensorShape(output),             \
                  tflite::micro::GetTensorData<output_type>(output), \
                  is_arg_max)
  if (axis->type == kTfLiteInt32) {
    if (output->type == kTfLiteInt32) {
      switch (input->type) {
        case kTfLiteFloat32:
          TF_LITE_ARG_MIN_MAX(float, int32_t, int32_t);
          break;
        case kTfLiteInt8:
          TF_LITE_ARG_MIN_MAX(int8_t, int32_t, int32_t);
          break;
        default:
          MicroPrintf(
              "Only float32, uint8_t and int8_t are "
              "supported currently, got %s.",
              TfLiteTypeGetName(input->type));
          return kTfLiteError;
      }
    } else {
      MicroPrintf("Only int32_t are supported currently, got %s.",
                  TfLiteTypeGetName(output->type));
      return kTfLiteError;
    }
  } else {
    MicroPrintf("Only int32_t are supported currently, got %s.",
                TfLiteTypeGetName(axis->type));
    return kTfLiteError;
  }

#undef TF_LITE_ARG_MIN_MAX

  return kTfLiteOk;
}

TfLiteStatus ArgMinEval(TfLiteContext* context, TfLiteNode* node) {
  return Eval(context, node, false);
}

TfLiteStatus ArgMaxEval(TfLiteContext* context, TfLiteNode* node) {
  return Eval(context, node, true);
}

}  // namespace arg_min_max

TfLiteRegistration Register_ARG_MAX() {
  return tflite::micro::RegisterOp(nullptr, nullptr, arg_min_max::ArgMaxEval);
}

TfLiteRegistration Register_ARG_MIN() {
  return tflite::micro::RegisterOp(nullptr, nullptr, arg_min_max::ArgMinEval);
}

}  // namespace micro
}  // namespace ops
}  // namespace tflite


text:
from cement.utils.test import TestApp

class PrintApp(TestApp):
    class Meta:
        extensions = ['print']
        output_handler = 'print'

class PrintDictApp(TestApp):
    class Meta:
        extensions = ['print']
        output_handler = 'print_dict'

def test_print_dict_output_handler():
    with PrintDictApp() as app:
        app.run()
        res = app.render(dict(foo='bar'))
        assert res == 'foo: bar\n'

def test_print_output_handler():
    with PrintApp() as app:
        app.run()
        res = app.render(dict(out='this is the foo bar output'))
        assert res == 'this is the foo bar output\n'

        # coverage
        app.render({})

def test_print():
    with PrintApp() as app:
        app.run()
        app.print('This is a simple output message')
        assert app.last_rendered[1] == 'This is a simple output message\n'


text:
=========================
cASO multi-region support
=========================

* In case the monitored projects rely on a specific region, define the
  following variable in the /etc/caso/caso.conf

.. code-block:: bash

  [DEFAULT]
  region_name = <REGION>

* In case the monitored Project(s) rely on different regions, prepare different
  files /etc/caso/caso-<REGION>.conf

.. code-block:: bash

  [DEFAULT]
  region_name = <REGION>

* List the Project(s) in the /etc/caso/voms.json as from the documentation

.. code-block:: JSON

  {
    "Project1": {
      "projects": ["Project1"]
    },
    "Project2": {
      "projects": ["Project2"]
    }
  }

* Execute caso-extract for each Project (and related REGION) to be monitored (Project1-REGION1, Project2-REGION2)

.. code-block:: bash

    /usr/bin/caso-extract --projects "Project1" --config-file /etc/caso/caso-<REGION1>.conf
    /usr/bin/caso-extract --projects "Project2" --config-file /etc/caso/caso-<REGION2>.conf


text:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="72dp"
    android:paddingRight="16dp">

    <androidx.cardview.widget.CardView
        android:id="@+id/bubble"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        app:cardBackgroundColor="@color/default_bubble_color_send"
        app:cardCornerRadius="8dp"
        app:cardElevation="4dp"
        app:cardUseCompatPadding="true">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:orientation="vertical"
            android:padding="8dp"
            android:weightSum="1">

            <TextView
                android:id="@+id/title_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical|left"
                android:textColor="@color/default_message_color_send"
                android:textSize="@dimen/default_title_text_size"
                android:textStyle="bold" />

            <hani.momanii.supernova_emoji_library.Helper.EmojiconTextView
                android:id="@+id/message_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical|left"
                android:textColor="@color/default_message_color_send"
                android:textSize="@dimen/default_message_text_size"
                tools:text="My name is Timi and I am not a god. Inner places is not the atomic career of the doer." />

            <androidx.legacy.widget.Space
                android:layout_width="match_parent"
                android:layout_height="4dp" />

            <TextView
                android:id="@+id/timestamp_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical|left"
                android:textColor="@color/default_tstamp_color_send"
                android:textSize="@dimen/default_timestamp_text_size"
                tools:text="12:10 am" />

            <ImageView
                android:id="@+id/imageView"
                android:layout_width="34dp"
                android:layout_height="wrap_content"
                android:layout_gravity="right"

                app:srcCompat="@drawable/emoji_0023" />

        </LinearLayout>

    </androidx.cardview.widget.CardView>

</FrameLayout>


text:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
?>

    <link rel="stylesheet" href="<?php echo base_url();?>/assets/css/evaluation.css" type="text/css">

<?php echo $course[0]->Course_name.' Project'.$evaluation[0]->Project; ?>
                        <form action=<?php echo site_url('export/preview/'.$course[0]->Course_id.'/'.$evaluation[0]->Evaluation_number.'/'.$evaluation[0]->Project)?> method="post" target="_blank" id="FormularioExportacion">

                        </form>
                        <?php echo strtoupper($evaluation[0]->Type).' ASSESSMENT';?>

    <?php
    $i = 1;
    echo "
";
    echo "
";
    echo "

 #	REG. ID	FIRST NAME	LAST NAME	GROUP NUMBER";
    if($evaluation[0]->Type == 'Peer')
        echo "	PEER ASSESSMENT	WEIGHTING FACTOR";
    elseif($evaluation[0]->Type == 'Team')
        echo "	TEAM ASSESSMENT";
    elseif($evaluation[0]->Type == 'Self')
        echo "	SELF ASSESSMENT";
    echo "

";
    $evaluation_id = $evaluation[0]->Evaluation_id;
    echo "
";
    foreach($students as $student){
        if($student->Took == 1)
            echo "
";
        else
            echo "
";
        if($evaluation[0]->Type == 'Peer'){
            echo "$i	Registration_number,$evaluation_id)'>".$student->Registration_number."	".strtoupper($student->Names)."	".strtoupper($student->Surnames)."	$student->Group_number";
            echo "	$student->Avg_Peer";
            echo "	$student->Evaluation_WF";
        }
        elseif($evaluation[0]->Type == 'Team'){
            echo "$i	Registration_number,$evaluation_id)'>".$student->Registration_number."	".strtoupper($student->Names)."	".strtoupper($student->Surnames)."	$student->Group_number";
            echo "	$student->Avg_Team";
        }
        elseif($evaluation[0]->Type == 'Self') {
            echo "$i	".$student->Registration_number."	" . strtoupper($student->Names) . "	" . strtoupper($student->Surnames) . "	$student->Group_number";
            echo "	$student->Avg_Self";
        }
        echo "
";
        $i++;
    }
    echo "
";
    echo "
";
    echo "
";
    ?>


text:
<!--
This file is part of BenchExec, a framework for reliable benchmarking:
https://github.com/sosy-lab/benchexec

SPDX-FileCopyrightText: 2007-2020 Dirk Beyer <https://www.sosy-lab.org>

SPDX-License-Identifier: Apache-2.0
-->

# BenchExec: Container Mode

The container mode isolates the benchmarked process from other processes on the same system,
in a similar way as for example Docker isolates applications
(using namespaces for operating-level system virtualization).
This improves reliability of benchmarking and reproducibility of results.
Contrary to using a VM, the application is still executed with native performance,
because it is run directly on the host kernel, without any additional layers.
By using an overlay filesystem (if available), the benchmarked process can still read from the host filesystem,
but not modify any files except where specifically allowed.
You can read more about it in our paper
[Reliable Benchmarking: Requirements and Solutions](https://www.sosy-lab.org/research/pub/2019-STTT.Reliable_Benchmarking_Requirements_and_Solutions.pdf).
There is also an additional tool, `containerexec`,
which is similar to `runexec` but provides only isolation of an application in a container,
but no resource measurements and limitations.

Container mode is available since BenchExec 1.9
and enabled by default since BenchExec 2.0.
It can be disabled with the flag `--no-container` in case of problems,
but instead we recommend configuring and troubleshooting
the container appropriately as described below.

The features of container mode are:

- Processes in the container cannot see and kill processes outside the container.
- Network access is not possible from the container,
  not even communicating with processes on the same host (configurable).
- File-system access can be restricted,
  and write accesses are redirected such that they do not affect the host filesystem (configurable).
  By default, file writes in the container are kept in memory (in a "RAM disk")
  and are not written to disk and not visible outside of the container.
  This reduces disk I/O and increases reproducibility.
  Furthermore, data written to this RAM disk are counted towards the run's memory limit.
- Result files produced by the tool in the container can be collected and copied
  to an output directory afterwards.

Note that while BenchExec containers rely on the same kernel features as similar solutions,
they are not meant as a secure solution for restricting potentially malicious applications.
**Execution of untrusted applications in a BenchExec container is at your own risk.**

## Container Configuration

This section describes how BenchExec configures the container, and how it can be customized.

### Directory Access Modes
The directory tree in the container is based on the directory tree of the host system,
but BenchExec supports isolating the container by preventing read or write access to certain directories.
For each directory in the container one of the following four access modes can be given:

- **hidden**: This host directory is hidden in the container.
  Instead a fresh, empty, writable, memory-backed directory (i.e., an empty RAM disk)
  will be visible in the container in this place.
  Writes to this directory will not be visible on the host.
- **read-only**: This directory is visible in the container, but read-only.
- **overlay**: This directory is visible in the container and
  an [overlay filesystem](https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt)
  is layered on top of it that redirects all write accesses.
  This means that write accesses are possible in the container, but the effect of any write
  is not visible on the host, only inside the container, and not written to disk.
- **full-access**: This directory is visible and writable in the container,
  and writes will be directly visible on the host.

The respective mode can be specified with the command-line parameters
`--hidden-dir`, `--read-only-dir`, `--overlay-dir`, and `--full-access-dir`.
Directory modes are applied recursively,
i.e., for all subdirectories which do not have a mode specified explicitly.
For the overlay mode, please note the [system requirements](INSTALL.md#kernel-requirements).

The default configuration is `--overlay-dir / --hidden-dir /run --hidden-dir /tmp`,
i.e., to mount an overlay filesystem over all directories except for `/run` and `/tmp`,
which are replaced by empty directories.
Furthermore, all partitions with FAT or NTFS file systems
as well as all autofs and FUSE mount points are mounted read-only,
because overlay does not work for these.

To overwrite the default configuration,
simply specify other directory modes for one or more of these directories.
Note that if you specify a different directory mode for one of them,
the default configuration for the other directories will still be used.
Of course you can always specify additional directory modes for other directories.
So for example, to disable the overlay mount (e.g., on systems that do not support it)
and keep the default modes for `/run` and `/tmp`, simply specify `--read-only-dir /`,
and if additionally you need certain directories to be writable,
add `--full-access-dir ...` for them.

Writes to directories in the hidden and overlay modes will be stored in a fresh RAM disk
(a [tmpfs](https://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt) instance)
and the produced result files will be copied to an output directory after the run
(cf. below for how to customize the latter).
All data stored in such directories are measured as part of the memory consumption of the run
and are counted towards the memory limit:
The sum of the memory consumption of the process(es) of the run
and the sum of the sizes of the existing files written by the run
needs to be always less than the memory limit.
If this is not desired, specify the parameter `--no-tmpfs`.
Note, however, that this parameter has two disadvantages:
With it, writes performed by the tool will produce actual disk I/O,
which decreases reproducibility,
and the tool can fill up the host's filesystem.
Writes to directories in the full-access mode will be performed as if they were done outside of the container,
and thus the same disadvantages apply.

In general, for a good isolation of runs and reproducibility of results,
we advise to use directory access modes that are as restrictive as possible.
In particular, we recommend to use the full-access mode only when absolutely necessary
(maybe on systems that do not support overlays),
and to also hide any directories that might contain cache or configuration files
that could unintentionally influence the run (like the home directory).

### Network Access
By default, a container has no access to the network.
It has a loopback interface such that processes inside the container can communicate with each other,
but there is no connection to any interfaces that are visible outside of the container.
By using `--network-access`, the container can be given full access to the network
like any application running outside of the container has.

### User, Group, and Host Lookups
By default, a container uses its own list of users and groups.
This is done to avoid failures during user lookups if some remote user database is configured
on the system (e.g., NIS or LDAP), and network access is disabled in the container.
For the same reason, DNS lookups for host names are disabled.
All of these can be re-enabled with `--keep-system-config`,
which also lets the container use the same user list as the host.

## Retrieving Result Files
Files written by the executed tool to directories in the hidden or overlay modes
are not visible on the host filesystem.
In order to allow the user to access these files after the benchmarking,
BenchExec copies them into an output directory.

Note that files written to a directory in the full-access mode will not be affected by this
(they already exist on the host filesystem).
If you cannot use the hidden or overlay modes but still need to retrieve output files,
you need to mark some directory as writable with `--full-access-dir`.
But note that this has the disadvantage that the tool can then make arbitrary changes
to existing files and directories at this location,
so full isolation is no longer guaranteed.

Patterns matching the following rules can be given
to select only a subset of created files to be copied:
- A file is retrieved if any of the given patterns match it.
- If the pattern is a relative path (does not start with `/`),
  it is interpreted as relative to the working directory of the tool.
  If all given patterns are relative,
  the directory tree that is created in the output directory will also start at this point.
- Absolute paths are also valid as patterns,
  and in this case the directory tree in the output directory
  will start at the root of the filesystem.
- Relative patterns that traverse upwards out of the working directory (e.g., `..`) are not allowed.
- The shell wildcards `?` and `*` are supported,
  and also the recursive wildcard `**`.
- If a directory is matched by the pattern, all files in the directory will be copied recursively.
- Only regular files are copied; symlinks, empty directories, etc. are ignored.

This means that if you want to retrieve all files written by the tool below its working directory,
use the pattern `.` or `*` (this is the default).
If you want to retrieve all files written anywhere use `/`.
For disabling the retrieval of result files altogether, use the empty string as pattern.

For `containerexec` and `runexec`, the command-line parameters
`--result-files` and `--output-directory` can be used
to specify the pattern(s) for matching result files and the directory where they should be placed.
For `benchexec`, the patterns are given within `<resultfiles>` tags
in the benchmark-definition XML file,
and the result files are placed in a directory besides the result XML file.

## Using BenchExec in a Docker/Podman Container

It is possible to use BenchExec inside other container environments,
but we strongly recommend to use [Podman](https://podman.io/)
(which is compatible with Docker)
because it provides "rootless" containers
(containers started as a regular user without sudo just like BenchExec containers).
To use BenchExec within Podman,
start it as a regular user (not root) and use the following arguments:
```
podman run --security-opt unmask=/proc/* --security-opt seccomp=unconfined ...
```
You may additionally need the arguments documented for
[cgroup usage](INSTALL.md#setting-up-cgroups-in-a-dockerpodman-container).

Using Docker is also possible, but only using the `--privileged` argument.
However, this gives your Docker container *full root access* to the host,
so please also add the `--cap-drop=all` flag,
make sure to use this only with trusted images,
and configure your Docker container such that everything in it
is executed under a different user account, not as root.
BenchExec is not designed to run as root and does not provide
any safety guarantees regarding its container under this circumstances.
<!--
In principle, `--security-opt systempaths=unconfined --security-opt seccomp=unconfined`
should also be sufficient as Docker arguments,
but then mounting within the container still fails.
-->

## Common Problems

Note that for investigating container-related problems, it can be easier to start an interactive shell
in a container with `containerexec` than using `benchexec` or `runexec`.

#### `Cannot execute ...: Unprivileged user namespaces forbidden on this system...`
Unprivileged user namespaces are forbidden on your system
(this is the default on some distributions like Debian, Arch Linux, and CentOS).
Please check the [system requirements](INSTALL.md#kernel-requirements)
how to enable them.

#### `Cannot execute ...: Creating namespace for container mode failed`
It seems your kernel does not support unprivileged user namespaces.
Please check the [system requirements](INSTALL.md#kernel-requirements)
and make sure that the kernel is compiled with `CONFIG_USER_NS`.
Furthermore note that running BenchExec inside other container solutions
such as Docker may or may not work depending on how the outer container
is configured (for example for Docker, `--privileged` is necessary).
You can still use BenchExec if you completely disable the container mode with `--no-container`.

#### `Failed to configure container: [Errno 19] Creating overlay mount for '...' failed: No such device`
Your kernel does not support the overlay filesystem,
please check the [system requirements](INSTALL.md#kernel-requirements).
You can use a different access mode for directories, e.g., with `--read-only-dir /`.
If some directories need to be writable, specify other directory modes for these directories as described above.

#### `Failed to configure container: [Errno 1] Creating overlay mount for '...' failed: Operation not permitted`
Your kernel does not allow mounting the overlay filesystem inside a container.
For this you need either Ubuntu or kernel version 5.11 or newer.
Alternatively, if you cannot use either,
you can use a different access mode for directories, e.g., with `--read-only-dir /`.
If some directories need to be writable, specify other directory modes for these directories as described above.

#### `Failed to configure container: [Errno 22] Creating overlay mount for '...' failed: Invalid argument`
Your kernel does not allow mounting an overlay filesystem in this place.
Often an explanation appears in the system log,
so check for error messages with `journalctl -e -k -g overlayfs`.

One known problem is [this kernel regression](https://github.com/sosy-lab/benchexec/issues/776),
which prevents overlays from being used if there is another mountpoint somewhere below the target directory.
Another limitation of the kernel is that one can only nest overlays twice,
so if you want to run a container inside a container inside a container,
at least one of these needs to use a non-overlay mode for this path.

#### `Cannot change into working directory inside container: [Errno 2] No such file or directory`
Either you have specified an invalid directory as working directory with `--dir`,
or your current directory on the host is hidden inside the container
(note that by default everything below `/tmp` is hidden).
Specify a valid working directory for the container with `--dir`.

#### `Cannot start process: [Errno 2] No such file or directory`
The executable to start was not found in the container.
Make sure that the executable exists and it is visible inside the container
(note that by default everything below `/tmp` is hidden).

#### Problems when accessing files in container: process dies, `Operation not supported`, `No such device or address`
These are symptoms that occur when an overlay is mounted over an NFS share
with several versions of the Linux kernel, including at least kernel versions up to 4.5
([bug report](https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1566471)).
If a kernel upgrade does not help, please use a different access mode for NFS-mounted directories,
such as `--hidden-dir` or `--read-only-dir`.

### BenchExec sometimes hangs if many parallel runs are executed
This happens if we clone the Python process while it is in an inconsistent state.
Make sure to use BenchExec 3.14 or newer,
where [#435](https://github.com/sosy-lab/benchexec/issues/435) is fixed
and a workaround for [#656](https://github.com/sosy-lab/benchexec/issues/656) is present.
If it still occurs, please attach to all child process of BenchExec
with `sudo gdb -p <PID>`, get a stack trace with `bt`,
and [report an issue](https://github.com/sosy-lab/benchexec/issues/new) with as much information as possible.
BenchExec will usually be able to continue if the hanging child process is killed.


text: require File.expand_path 'spec_helper.rb', __dir__


text:
package jpl.ch02.ex16;

import static org.junit.Assert.*;

import org.junit.Test;

public class LinkedListTest {

	@Test
	public void testLength1() {
		LinkedList obj1 = new LinkedList("first", null);

		int actual = obj1.length();

		assertEquals(1, actual);
	}

	@Test
	public void testLength7() {
		LinkedList obj1 = new LinkedList("first", null);
		LinkedList obj2 = new LinkedList("second", obj1);
		LinkedList obj3 = new LinkedList("third", obj2);
		LinkedList obj4 = new LinkedList("third", obj3);
		LinkedList obj5 = new LinkedList("third", obj4);
		LinkedList obj6 = new LinkedList("third", obj5);
		LinkedList obj7 = new LinkedList("third", obj6);

		int actual = obj1.length();

		assertEquals(7, actual);
	}

}


text:
BOOST_AUTO_TEST_SUITE(PartitionSLL)

BOOST_AUTO_TEST_CASE(invalid_list)
{
    {
        NodeSLL<int>* sll = nullptr;
        Algo::DS::SLL::PartitionAroundValue::PartitionOnePass(&sll, 10);
        BOOST_CHECK(nullptr == sll);
        DeleteSLL(&sll);
    }

    {
        NodeSLL<int>* sll = nullptr;
        Algo::DS::SLL::PartitionAroundValue::PartitionTwoPass(sll, 10);
        BOOST_CHECK(nullptr == sll);
        DeleteSLL(&sll);
    }
}

BOOST_AUTO_TEST_CASE(one_elem)
{
    {
        NodeSLL<int>* sll = new NodeSLL<int>(10);
        Algo::DS::SLL::PartitionAroundValue::PartitionOnePass(&sll, 20);

        std::vector<int> expectedValues = {10};
        BOOST_CHECK(expectedValues == ValuesInSLL(&sll));
        DeleteSLL(&sll);
    }

    {
        NodeSLL<int>* sll = new NodeSLL<int>(10);
        Algo::DS::SLL::PartitionAroundValue::PartitionTwoPass(sll, 20);

        std::vector<int> expectedValues = {10};
        BOOST_CHECK(expectedValues == ValuesInSLL(&sll));
        DeleteSLL(&sll);
    }
}

BOOST_AUTO_TEST_CASE(all_less)
{
    {
        NodeSLL<int>* sll = CreateSLL<int>({10, 9, 8, 7});
        Algo::DS::SLL::PartitionAroundValue::PartitionOnePass(&sll, 20);

        std::vector<int> expectedValues = {10, 9, 8, 7};
        std::vector<int> result = ValuesInSLL(&sll);
        BOOST_CHECK(expectedValues == result);
        DeleteSLL(&sll);
    }

    {
        NodeSLL<int>* sll = CreateSLL<int>({10, 9, 8, 7});
        Algo::DS::SLL::PartitionAroundValue::PartitionTwoPass(sll, 20);

        std::vector<int> expectedValues = {7, 8, 9, 10};
        std::vector<int> result = ValuesInSLL(&sll);
        BOOST_CHECK(expectedValues == result);
        DeleteSLL(&sll);
    }
}

BOOST_AUTO_TEST_CASE(all_bigger)
{
    {
        NodeSLL<int>* sll = CreateSLL<int>({10, 9, 8, 7});
        Algo::DS::SLL::PartitionAroundValue::PartitionOnePass(&sll, 2);

        std::vector<int> expectedValues = {10, 9, 8, 7};
        std::vector<int> result = ValuesInSLL(&sll);
        BOOST_CHECK(expectedValues == result);
        DeleteSLL(&sll);
    }

    {
        NodeSLL<int>* sll = CreateSLL<int>({10, 9, 8, 7});
        Algo::DS::SLL::PartitionAroundValue::PartitionTwoPass(sll, 2);

        std::vector<int> expectedValues = {7, 8, 9, 10};
        std::vector<int> result = ValuesInSLL(&sll);
        BOOST_CHECK(expectedValues == result);
        DeleteSLL(&sll);
    }
}

BOOST_AUTO_TEST_CASE(middle)
{
    {
        NodeSLL<int>* sll = CreateSLL<int>({10, 9, 8, 7});
        Algo::DS::SLL::PartitionAroundValue::PartitionOnePass(&sll, 9);

        std::vector<int> expected = {8, 7, 10, 9};
        std::vector<int> result = ValuesInSLL(&sll);
        BOOST_CHECK(expected == result);
        DeleteSLL(&sll);
    }

    {
        NodeSLL<int>* sll = CreateSLL<int>({10, 9, 8, 7});
        Algo::DS::SLL::PartitionAroundValue::PartitionTwoPass(sll, 9);

        std::vector<int> expected = {7, 8, 9, 10};
        std::vector<int> result = ValuesInSLL(&sll);
        BOOST_CHECK(expected == result);
        DeleteSLL(&sll);
    }
}

BOOST_AUTO_TEST_SUITE_END()