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