001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.units; 006 007import java.util.Objects; 008 009@FunctionalInterface 010public interface UnaryFunction { 011 /** 012 * Applies this function to the input value and returns the result. 013 * 014 * @param input the input value to the function 015 * @return the result 016 */ 017 double apply(double input); 018 019 /** 020 * Constructs a new function that first calls this function, then passes the result to another as 021 * input. 022 * 023 * <pre> 024 * f = x -> x + 1 // f(x) = x + 1 025 * g = x -> 2 * x // g(x) = 2x 026 * 027 * h = f.pipeTo(g) // h(x) = g(f(x)) 028 * </pre> 029 * 030 * @param next the next operation to pipe to 031 * @return the composite function g(f(x)) 032 */ 033 default UnaryFunction pipeTo(UnaryFunction next) { 034 Objects.requireNonNull(next, "The next operation in the chain must be provided"); 035 036 return x -> next.apply(this.apply(x)); 037 } 038 039 /** 040 * Creates a composite function h(x) such that h(x) = f(x) * g(x). 041 * 042 * @param multiplier the function to multiply this one by 043 * @return the composite function f(x) * g(x) 044 */ 045 default UnaryFunction mult(UnaryFunction multiplier) { 046 Objects.requireNonNull(multiplier, "A multiplier function must be provided"); 047 048 return x -> this.apply(x) * multiplier.apply(x); 049 } 050 051 /** 052 * Creates a composite function h(x) such that h(x) = k * f(x). 053 * 054 * @param multiplier the constant value to multiply this function's results by 055 * @return the composite function k * f(x) 056 */ 057 default UnaryFunction mult(double multiplier) { 058 return x -> this.apply(x) * multiplier; 059 } 060 061 /** 062 * Creates a composite function h(x) such that h(x) = f(x) / g(x). 063 * 064 * @param divisor the function to divide this one by 065 * @return the composite function f(x) / g(x) 066 */ 067 default UnaryFunction div(UnaryFunction divisor) { 068 Objects.requireNonNull(divisor, "A divisor function must be provided"); 069 070 return x -> { 071 double numerator = this.apply(x); 072 073 // fast-track to avoid another function call 074 // avoids returning NaN if divisor is also zero 075 if (numerator == 0) { 076 return 0; 077 } 078 079 double div = divisor.apply(x); 080 return numerator / div; // NOTE: returns +Infinity or -Infinity if div is zero 081 }; 082 } 083 084 /** 085 * Creates a composite function h(x) such that h(x) = 1/k * f(x). 086 * 087 * @param divisor the constant value to divide this function's results by 088 * @return the composite function 1/k * f(x) 089 */ 090 default UnaryFunction div(double divisor) { 091 return x -> this.apply(x) / divisor; 092 } 093 094 /** 095 * Creates a composite function h(x) such that h(x) = f(x) ^ g(x). 096 * 097 * @param exponent the function to exponentiate this function's results by 098 * @return the composite function f(x) ^ g(x) 099 */ 100 default UnaryFunction exp(UnaryFunction exponent) { 101 Objects.requireNonNull(exponent, "An exponent function must be provided"); 102 103 return x -> Math.pow(this.apply(x), exponent.apply(x)); 104 } 105 106 /** 107 * Creates a composite function h(x) such that h(x) = f(x) ^ k. 108 * 109 * @param exponent the constant value to exponentiate this function's results by 110 * @return the composite function f(x) ^ k 111 */ 112 default UnaryFunction exp(double exponent) { 113 return x -> Math.pow(this.apply(x), exponent); 114 } 115}