001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2021, 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.spi; 031 032/** 033 * Provides arithmetic {@link Number} operations on an implementation specific set of 034 * {@link Number} types. 035 * <p> 036 * Let <em>S</em> be the set of possible {@link Number} values within the (given) set of 037 * {@link Number} types.<br> 038 * Then <em>S</em> is <a href="https://en.wikipedia.org/wiki/Closure_(mathematics)">closed</a> 039 * under the collection of {@link NumberSystem}'s methods. 040 * 041 * <dl> 042 * <dt><span class="strong">Implementation Note:</span></dt><dd>Given <em>S</em> the set of possible {@link Number} values within implementation specific 043 * set of (supported) {@link Number} types:<br> 044 * - implemented methods must support any {@link Number} arguments from <em>S</em><br> 045 * - implemented methods must also have their {@link Number} results to be in <em>S</em></dd> 046 * </dl> 047 * 048 * @author Andi Huber 049 * @author <a href="mailto:werner@units.tech">Werner Keil</a> 050 * @since 2.1, November 21, 2020 051 * @see <a href="https://en.wikipedia.org/wiki/Closure_(mathematics)">Closure (wikipedia)</a> 052 */ 053public interface NumberSystem { 054 055 /** 056 * Immutable value type, holder of 2 numbers. 057 */ 058 public final static class DivisionResult { 059 /** 060 * originating from x / y 061 */ 062 public final Number quotient; 063 /** 064 * originating from x % y 065 */ 066 public final Number remainder; 067 068 public static DivisionResult of(Number quotient, Number remainder) { 069 return new DivisionResult(quotient, remainder); 070 } 071 072 private DivisionResult(Number quotient, Number remainder) { 073 this.quotient = quotient; 074 this.remainder = remainder; 075 } 076 } 077 078 /** 079 * Returns the sum of given {@code x} and {@code y} as a {@link Number} that best 080 * represents the arithmetic result within the set of number types this NumberSystem 081 * supports. 082 * 083 * @param x 084 * @param y 085 * @return {@code x + y} 086 */ 087 Number add(Number x, Number y); 088 089 /** 090 * Returns the difference of given {@code x} and {@code y} as a {@link Number} that best 091 * represents the arithmetic result within the set of number types this NumberSystem 092 * supports. 093 * 094 * @param x 095 * @param y 096 * @return {@code x - y} 097 */ 098 Number subtract(Number x, Number y); 099 100 /** 101 * Returns the product of given {@code x} and {@code y} as a {@link Number} that best 102 * represents the arithmetic result within the set of number types this NumberSystem 103 * supports. 104 * 105 * @param x 106 * @param y 107 * @return {@code x * y} 108 */ 109 Number multiply(Number x, Number y); 110 111 /** 112 * Returns the division of given {@code x} and {@code y} as a {@link Number} that best 113 * represents the arithmetic result within the set of number types this NumberSystem 114 * supports. 115 * 116 * @param x 117 * @param y 118 * @return {@code x / y} 119 */ 120 Number divide(Number x, Number y); 121 122 /** 123 * Returns a two-element Number array containing {x / y, x % y} 124 * @param x 125 * @param y 126 * @param roundRemainderTowardsZero - whether the division remainder should be rounded towards zero 127 * @return 128 */ 129 Number[] divideAndRemainder(Number x, Number y, boolean roundRemainderTowardsZero); 130 131 /** 132 * Returns given {@code number} to the power of {@code exponent} as a {@link Number} that best 133 * represents the arithmetic result within the set of number types this NumberSystem 134 * supports. 135 * 136 * @param number 137 * @param exponent - an integer 138 * @return number^exponent 139 * @throws ArithmeticException if {@code number} and {@code exponent} are ZERO 140 */ 141 Number power(Number number, int exponent); 142 143 /** 144 * Returns the reciprocal of given {@code number} as a {@link Number} that best 145 * represents the arithmetic result within the set of number types this NumberSystem 146 * supports. 147 * 148 * @param number 149 * @return {@code number^-1} 150 */ 151 Number reciprocal(Number number); 152 153 /** 154 * Returns the negation of given {@code number} as a {@link Number} that best 155 * represents the arithmetic result within the set of number types this NumberSystem 156 * supports. 157 * 158 * @param number 159 * @return {@code -number} 160 */ 161 Number negate(Number number); 162 163 /** 164 * Returns the signum function of given {@code number}. 165 * 166 * @param number 167 * @return {@code signum(number)} 168 */ 169 int signum(Number number); 170 171 /** 172 * Returns the absolute of given {@code number} as a {@link Number} that best 173 * represents the arithmetic result within the set of number types this NumberSystem 174 * supports. 175 * 176 * @param number 177 * @return {@code abs(number)} 178 */ 179 Number abs(Number number); 180 181 /** 182 * Returns Euler's Constant to the power of of given {@code number} as a {@link Number} that best 183 * represents the arithmetic result within the set of number types this NumberSystem 184 * supports. 185 * 186 * @param number 187 * @return {@code e}^number, with {@code e} Euler's Constant) 188 */ 189 Number exp(Number number); 190 191 /** 192 * Returns the natural logarithm of given {@code number} as a {@link Number} that best 193 * represents the arithmetic result within the set of number types this NumberSystem 194 * supports. 195 * 196 * @param number 197 * @return natural logarithm of number 198 */ 199 Number log(Number number); 200 201 202 /** 203 * 'Narrows' given {@code number} as a {@link Number} that best 204 * represents the numeric value within the set of number types this NumberSystem 205 * supports. 206 * <p> 207 * eg. A BigInteger that is within range of Java's {@code Long} type can be narrowed to 208 * Long w/o loss of precision. 209 * 210 * @param number 211 * @return 'best' representation of {@code number} w/o loss of precision 212 */ 213 Number narrow(Number number); 214 215 /** 216 * Compares two {@code Number} values numerically. 217 * 218 * @param x 219 * @param y 220 * @return the value {@code 0} if {@code x == y}; 221 * a value less than {@code 0} if {@code x < y}; and 222 * a value greater than {@code 0} if {@code x > y} 223 */ 224 int compare(Number x, Number y); 225 226 boolean isZero(Number number); 227 boolean isOne(Number number); 228 boolean isLessThanOne(Number number); 229 230 /** 231 * Checks whether given {@code number} has fractional parts or not. 232 * @param number 233 * @return whether {@code number} represents a whole number 234 */ 235 boolean isInteger(Number number); 236 237 /** 238 * 239 * @param x 240 * @param y 241 * @return 242 */ 243 default boolean equals(Number x, Number y) { 244 if(x == y) { 245 return true; 246 } 247 if(!x.getClass().equals(y.getClass())) { 248 return false; 249 } 250 return x.equals(y); 251 } 252 253 254 255 256 257}