All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.algart.math.functions.Func Maven / Gradle / Ivy

Go to download

Open-source Java libraries, supporting generalized smart arrays and matrices with elements of any types, including a wide set of 2D-, 3D- and multidimensional image processing and other algorithms, working with arrays and matrices.

The newest version!
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2007-2024 Daniel Alievsky, AlgART Laboratory (http://algart.net)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package net.algart.math.functions;

import net.algart.math.IPoint;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.DoublePredicate;

/**
 * 

Abstract mathematical function * f(x0, x1, ..., xn-1), * or f(x), where x is a point of the n-dimensional space.

* *

Implementations of this interface are usually immutable and * always thread-safe: get methods of this interface may be freely used * while simultaneous accessing to the same instance from several threads. * All implementations of this interface from this package are immutable.

* * @author Daniel Alievsky */ public interface Func { /** * Identity function, just returning its first argument: * f(x0, x1, ..., xn-1) = * x0. * The {@link #get} method of this object requires at least 1 argument * and throws IndexOutOfBoundsException if the number of arguments is 0. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func IDENTITY = new IdentityFunc(); /** * Updatable version of {@link #IDENTITY} function. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func.Updatable UPDATABLE_IDENTITY = new IdentityFunc.Updatable(); /** * Maximum from several numbers: * f(x0, x1, ..., xn-1) = * max(x0, x1, ..., xn-1). * The {@link #get} method of this object may process any number of arguments. * If the number of arguments is 0, it returns Double.NEGATIVE_INFINITY. * *

Unlike standard Math.max method, this function supposes that * max(x,y) = x>y ? x : y * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func MAX = new MaxFunc(); /** * Minimum from several numbers: * f(x0, x1, ..., xn-1) = * min(x0, x1, ..., xn-1). * The {@link #get} method of this object may process any number of arguments. * If the number of arguments is 0, it returns Double.POSITIVE_INFINITY. * *

Unlike standard Math.min method, this function supposes that * min(x,y) = x<y ? x : y * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func MIN = new MinFunc(); /** * Absolute value function: * f(x0) = * |x0|. * More precisely, the result of this function is * StrictMath.abs(x[0]). * The {@link #get} method of this object requires at least 1 argument * and throws IndexOutOfBoundsException if the number of arguments is 0. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func ABS = new AbsFunc(); /** * Absolute value of the difference of 2 numbers: * f(x0, x1) = * |x0-x1|. * The {@link #get} method of this object requires at least 2 arguments * and throws IndexOutOfBoundsException if the number of arguments is 0 or 1. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func ABS_DIFF = new AbsDiffFunc(); /** * Positive difference of 2 numbers: * f(x0, x1) = * max(x0-x1,0). * The {@link #get} method of this object requires at least 2 arguments * and throws IndexOutOfBoundsException if the number of arguments is 0 or 1. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func POSITIVE_DIFF = new PositiveDiffFunc(); /** * An instance of {@link LinearFunc} class, describing the linear function * x0 + x1: * {@link LinearFunc#getInstance(double, double...) LinearFunc.getInstance(0.0, 1.0, 1.0)}. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ LinearFunc X_PLUS_Y = LinearFunc.getInstance(0.0, 1.0, 1.0); /** * An instance of {@link LinearFunc} class, describing the linear function * x0 - x1: * {@link LinearFunc#getInstance(double, double...) LinearFunc.getInstance(0.0, 1.0, -1.0)}. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ LinearFunc X_MINUS_Y = LinearFunc.getInstance(0.0, 1.0, -1.0); /** * An instance of {@link LinearFunc} class, describing the linear function * x1 - x0: * {@link LinearFunc#getInstance(double, double...) LinearFunc.getInstance(0.0, -1.0, 1.0)}. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ LinearFunc Y_MINUS_X = LinearFunc.getInstance(0.0, -1.0, 1.0); /** * An instance of {@link LinearFunc} class, describing the linear function * (x0 + x1)/2: * {@link LinearFunc#getInstance(double, double...) LinearFunc.getInstance(0.0, 0.5, 0.5)}. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ LinearFunc HALF_X_PLUS_Y = LinearFunc.getInstance(0.0, 0.5, 0.5); /** * An instance of {@link LinearFunc} class, describing the linear function * (x0 - x1)/2: * {@link LinearFunc#getInstance(double, double...) LinearFunc.getInstance(0.0, 0.5, -0.5)}. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ LinearFunc HALF_X_MINUS_Y = LinearFunc.getInstance(0.0, 0.5, -0.5); /** * An instance of {@link LinearFunc} class, describing the linear function * (x1 - x0)/2: * {@link LinearFunc#getInstance(double, double...) LinearFunc.getInstance(0.0, -0.5, 0.5)}. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ LinearFunc HALF_Y_MINUS_X = LinearFunc.getInstance(0.0, -0.5, 0.5); /** * An instance of {@link LinearFunc} class, describing the linear function * 1.0 - x0: * {@link LinearFunc#getInstance(double, double...) LinearFunc.getInstance(1.0, -1.0)}. * This instance describes logical NOT operation in a case when the arguments are bits (0 and 1 values). * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ LinearFunc REVERSE = LinearFunc.getInstance(1.0, -1.0); /** * Select function: * f(x0, x1, ..., xn-1) = * xi+1, where i is x0 cast to integer type: * i=(int)x[0]. * The {@link #get} method of this object requires at least 2 arguments * and throws IndexOutOfBoundsException if the number of arguments is 0 or 1. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func SELECT = new SelectFunc(); /** * Select function: * f(x0, x1, x2, x3) = * x0 > x1 ? x2 : x3. * The {@link #get} method of this object requires at least 4 arguments * and throws IndexOutOfBoundsException if the number of arguments is 0, 1, 2 or 3. * *

Note: call of this function is almost equivalent to calling {@link #SELECT_IF_GREATER_OR_EQUAL} function * with another order of the arguments: * f(x1, x0, x3, x2), * that is * x1 >= x0 ? x3 : x2. * The only difference is connected with processing Double.NaN values of x0 and * x1: this function will choose x3, but the corresponding call of * {@link #SELECT_IF_GREATER_OR_EQUAL} will choose x2, because in Java any comparison with * Double.NaN returns false. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func SELECT_IF_GREATER = new SelectIfGreaterFunc(); /** * Select function: * f(x0, x1, x2, x3) = * x0 >= x1 ? x2 : x3. * The {@link #get} method of this object requires at least 4 arguments * and throws IndexOutOfBoundsException if the number of arguments is 0, 1, 2 or 3. * *

Note: call of this function is almost equivalent to calling {@link #SELECT_IF_GREATER} function * with another order of the arguments: * f(x1, x0, x3, x2), * that is * x1 > x0 ? x3 : x2. * The only difference is connected with processing Double.NaN values of x0 and * x1: this function will choose x3, but the corresponding call of * {@link #SELECT_IF_GREATER} will choose x2, because in Java any comparison with * Double.NaN returns false. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func SELECT_IF_GREATER_OR_EQUAL = new SelectIfGreaterOrEqualFunc(); /** * Selecting from 8 "integer" directions on 2D plane: * f(x0, x1) = integer code from 1 to 8. * The result of this function is the index of one of 8 sectors, where the 2-dimensional vector * (x0,x1) lies. * Namely, let φ=Math.atan2(x1,x0), more precisely, * an equivalent angle in 0°..360° range. * The result of this function is: *

    *
  • 0, if 337.5° < φ ≤ 22.5° and also in the special case * x0=x1=0.0;
  • *
  • 1, if 22.5° < φ ≤ 67.5°;
  • *
  • 2, if 67.5° < φ ≤ 112.5°;
  • *
  • 3, if 112.5° < φ ≤ 157.5°;
  • *
  • 4, if 157.5° < φ ≤ 202.5°;
  • *
  • 5, if 202.5° < φ ≤ 247.5°;
  • *
  • 6, if 247.5° < φ ≤ 292.5°;
  • *
  • 7, if 292.5° < φ ≤ 337.5°.
  • *
* *

(A strange formula "337.5° < φ ≤ 22.5°" just means that the direction lies * between 337.5°=-22.5° and +22.5° — in other words, "almost rightward" along X axis.) * *

This function is useful while processing 2-dimensional matrices, for example, in algorithms * like Canny edge detector. * *

The {@link #get} method of this object requires at least 2 arguments * and throws IndexOutOfBoundsException if the number of arguments is 0 or 1. * *

This instance is immutable and thread-safe: there are no ways to modify its settings. */ Func SELECT_FROM_8_DIRECTIONS_2D = new SelectFrom8Directions2DFunc(); /** * Vectors, corresponding to 8 directions recognized by {@link #SELECT_FROM_8_DIRECTIONS_2D} function. * More precisely, if is an unmodifiable list consisting of the following elements: *

    *
  1. {@link IPoint#valueOf(long...) IPoint.valueOf(1,0)},
  2. *
  3. {@link IPoint#valueOf(long...) IPoint.valueOf(1,1)},
  4. *
  5. {@link IPoint#valueOf(long...) IPoint.valueOf(0,1)},
  6. *
  7. {@link IPoint#valueOf(long...) IPoint.valueOf(-1,1)},
  8. *
  9. {@link IPoint#valueOf(long...) IPoint.valueOf(-1,0)},
  10. *
  11. {@link IPoint#valueOf(long...) IPoint.valueOf(-1,-1)},
  12. *
  13. {@link IPoint#valueOf(long...) IPoint.valueOf(0,-1)},
  14. *
  15. {@link IPoint#valueOf(long...) IPoint.valueOf(1,-1)}.
  16. *
* *

So, if the direction returned by {@link #SELECT_FROM_8_DIRECTIONS_2D} is n, then the corresponding * "rounding" direction is described by * {@link #SHIFTS_ALONG_8_DIRECTIONS_2D}.get(n). * *

This instance is immutable and thread-safe: there are no ways to modify it. */ List SHIFTS_ALONG_8_DIRECTIONS_2D = Collections.unmodifiableList( java.util.Arrays.asList( IPoint.valueOf(1, 0), IPoint.valueOf(1, 1), IPoint.valueOf(0, 1), IPoint.valueOf(-1, 1), IPoint.valueOf(-1, 0), IPoint.valueOf(-1, -1), IPoint.valueOf(0, -1), IPoint.valueOf(1, -1))); /** *

"Updatable" mathematical function: an extension of {@link Func} interface * allowing assigning values to the function result, that leads to * corresponding correction of arguments. * Usually can be implemented for one-argument functions, * where the {@link #set set(x[], newResult)} method assigns * to x[0] the result of the inverse function, called for newResult. *

* *

Implementations of this interface are usually immutable and * always thread-safe: get and set methods of this interface may be freely used * while simultaneous accessing the same instance from several threads.

*/ interface Updatable extends Func { /** * Correct some of x arguments so that * {@link #get get(x)} will be, as possible, equal to newResult. * For example, if this is one-argument function f(x), * and its inverse function is g(y) (g(f(x))=x), * then this method should assign x[0]=g(newResult). * *

This method does not guarantee the precise equality * {@link #get get(x)}==newResult. (Usually, it is impossible due to * limited precision of floating-point calculations.) But this method should try * to provide this equality (after its call) with, as possible, maximal possible precision. * * @param x the function arguments. * @param newResult the desired function result. * @throws IndexOutOfBoundsException may be thrown if the length of x array is less * than the required number of this function arguments. */ void set(double[] x, double newResult); } /** * Returns the result of this function for the given arguments: * f(x0, x1, ..., xx.length-1). * *

This method must not change the values of x elements! * * @param x the function arguments. * @return the function result. * @throws IndexOutOfBoundsException may be thrown if the number of passed arguments is less * than the required number of this function arguments. */ double get(double... x); /** * Equivalent to {@link #get(double...) get}(new double[0]). * Provides better performance because it does not require Java array creation. * * @return the function result. * @throws IndexOutOfBoundsException may be thrown this function requires at least 1 argument. */ double get(); /** * Equivalent to {@link #get(double...) get}(new double[] {x0}). * Provides better performance because it does not require Java array creation. * * @param x0 the function argument. * @return the function result. * @throws IndexOutOfBoundsException may be thrown this function requires at least 2 arguments. */ double get(double x0); /** * Equivalent to {@link #get(double...) get}(new double[] {x0, x1}). * Provides better performance because it does not require Java array creation. * * @param x0 the first function argument. * @param x1 the second function argument. * @return the function result. * @throws IndexOutOfBoundsException may be thrown this function requires at least 3 arguments. */ double get(double x0, double x1); /** * Equivalent to {@link #get(double...) get}(new double[] {x0, x1, x2}). * Provides better performance because it does not require Java array creation. * * @param x0 the first function argument. * @param x1 the second function argument. * @param x2 the third function argument. * @return the function result. * @throws IndexOutOfBoundsException may be thrown this function requires at least 4 arguments. */ double get(double x0, double x1, double x2); /** * Equivalent to {@link #get(double...) get}(new double[] {x0, x1, x2, x3}). * Provides better performance because it does not require Java array creation. * * @param x0 the first function argument. * @param x1 the second function argument. * @param x2 the third function argument. * @param x3 the fourth function argument. * @return the function result. * @throws IndexOutOfBoundsException may be thrown this function requires at least 5 arguments. */ double get(double x0, double x1, double x2, double x3); /** * Returns the function {@link Func1} that is based on the given predicate and returns * 1.0 for all values for which this predicate returns true, * and 0.0 for all values for which this predicate returns false. * Equivalent to *

     *     (Func1) x0 -> predicate.test(x0) ? 1.0 : 0.0;
     * 
* * @param predicate some predicate for double values. * @return equivalent AlgART function. * @throws NullPointerException if the argument is {@code null}. */ static Func1 of(DoublePredicate predicate) { Objects.requireNonNull(predicate, "Null predicate"); return x0 -> predicate.test(x0) ? 1.0 : 0.0; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy