001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2018, Jean-Marie Dautelle, Werner Keil, Otavio Santana. 004 * 005 * All rights reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without modification, 008 * are permitted provided that the following conditions are met: 009 * 010 * 1. Redistributions of source code must retain the above copyright notice, 011 * this list of conditions and the following disclaimer. 012 * 013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 014 * and the following disclaimer in the documentation and/or other materials provided with the distribution. 015 * 016 * 3. Neither the name of JSR-385, Indriya nor the names of their contributors may be used to endorse or promote products 017 * derived from this software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package tech.units.indriya.function; 031 032import java.math.BigDecimal; 033import java.math.MathContext; 034import java.util.Objects; 035 036import javax.measure.UnitConverter; 037 038import tech.units.indriya.AbstractConverter; 039import tech.uom.lib.common.function.ValueSupplier; 040 041/** 042 * <p> 043 * This class represents a exponential converter of limited precision. Such converter is used to create inverse of logarithmic unit. 044 * 045 * <p> 046 * This class is package private, instances are created using the {@link LogConverter#inverse()} method. 047 * </p> 048 * 049 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 050 * @author <a href="mailto:units@catmedia.us">Werner Keil</a> 051 * @author Andi Huber 052 * @version 1.3, April 26, 2018 053 * @since 1.0 054 */ 055public final class ExpConverter extends AbstractConverter implements ValueSupplier<String> { 056 057 /** 058 * 059 */ 060 private static final long serialVersionUID = -8851436813812059827L; 061 062 /** 063 * Holds the logarithmic base. 064 */ 065 private final double base; 066 067 /** 068 * Holds the natural logarithm of the base. 069 */ 070 private final double logOfBase; 071 072 /** 073 * Creates a logarithmic converter having the specified base. 074 * 075 * @param base 076 * the logarithmic base (e.g. <code>Math.E</code> for the Natural Logarithm). 077 */ 078 public ExpConverter(double base) { 079 this.base = base; 080 this.logOfBase = Math.log(base); 081 } 082 083 /** 084 * Creates a logarithmic converter having the specified base. 085 * 086 * @param base 087 * the logarithmic base (e.g. <code>Math.E</code> for the Natural Logarithm). 088 */ 089 public static ExpConverter of(double base) { 090 return new ExpConverter(base); 091 } 092 093 /** 094 * Returns the exponential base of this converter. 095 * 096 * @return the exponential base (e.g. <code>Math.E</code> for the Natural Exponential). 097 */ 098 public double getBase() { 099 return base; 100 } 101 102 @Override 103 public boolean isIdentity() { 104 return false; 105 } 106 107 @Override 108 protected boolean isSimpleCompositionWith(AbstractConverter that) { 109 if(that instanceof LogConverter) { 110 return ((LogConverter)that).getBase() == base; // can compose with log to identity, provided it has same base 111 } 112 return false; 113 } 114 115 @Override 116 protected AbstractConverter simpleCompose(AbstractConverter that) { 117 return AbstractConverter.IDENTITY; 118 } 119 120 @Override 121 public AbstractConverter inverseWhenNotIdentity() { 122 return new LogConverter(base); 123 } 124 125 @Override 126 public final String transformationLiteral() { 127 if (base == Math.E) { 128 return "x -> e^x"; 129 } else { 130 if(base<0) { 131 return String.format("x -> (%s)^x", base); 132 } 133 return String.format("x -> %s^x", base); 134 } 135 } 136 137 @Override 138 public boolean equals(Object obj) { 139 if (this == obj) { 140 return true; 141 } 142 if (obj instanceof ExpConverter) { 143 ExpConverter that = (ExpConverter) obj; 144 return Objects.equals(base, that.base); 145 } 146 return false; 147 } 148 149 @Override 150 public int hashCode() { 151 return Objects.hash(base); 152 } 153 154 @Override 155 public double convertWhenNotIdentity(double amount) { 156 return Math.exp(logOfBase * amount); 157 } 158 159 @Override 160 public BigDecimal convertWhenNotIdentity(BigDecimal value, MathContext ctx) throws ArithmeticException { 161 return BigDecimal.valueOf(convert(value.doubleValue())); // Reverts to 162 // double 163 // conversion. 164 } 165 166 @Override 167 public boolean isLinear() { 168 return false; 169 } 170 171 @Override 172 public String getValue() { 173 return toString(); 174 } 175 176 @SuppressWarnings("rawtypes") 177 @Override 178 public int compareTo(UnitConverter o) { 179 if (this == o) { 180 return 0; 181 } 182 if (o instanceof ValueSupplier) { 183 return getValue().compareTo(String.valueOf(((ValueSupplier) o).getValue())); 184 } 185 return -1; 186 } 187 188 189}