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}