001/*
002 * Units of Measurement Reference Implementation
003 * Copyright (c) 2005-2023, 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}