001/*
002 * The MIT License (MIT)
003 *
004 * Copyright (c) 2015-2023 decimal4j (tools4j), Marco Terzer
005 *
006 * Permission is hereby granted, free of charge, to any person obtaining a copy
007 * of this software and associated documentation files (the "Software"), to deal
008 * in the Software without restriction, including without limitation the rights
009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010 * copies of the Software, and to permit persons to whom the Software is
011 * furnished to do so, subject to the following conditions:
012 *
013 * The above copyright notice and this permission notice shall be included in all
014 * copies or substantial portions of the Software.
015 *
016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022 * SOFTWARE.
023 */
024package org.decimal4j.arithmetic;
025
026import org.decimal4j.scale.ScaleMetrics;
027import org.decimal4j.scale.Scales;
028
029/**
030 * Contains static methods to compare unscaled decimals of different scales.
031 */
032final class Compare {
033
034        /**
035         * Compares the two unscaled values with possibly different scales.
036         * 
037         * @param unscaled
038         *            the first unscaled value to compare
039         * @param scale
040         *            the scale of the first value
041         * @param otherUnscaled
042         *            the second unscaled value to compare
043         * @param otherScale
044         *            the scale of the second value
045         * @return the value {@code 0} if {@code unscaled1 == unscaled2}; a value
046         *         less than {@code 0} if {@code unscaled1 < unscaled2}; and a value
047         *         greater than {@code 0} if {@code unscaled1 > unscaled2}
048         */
049        public static final int compareUnscaled(long unscaled, int scale, long otherUnscaled, int otherScale) {
050                if (scale == otherScale) {
051                        return Long.compare(unscaled, otherUnscaled);
052                }
053                if (scale < otherScale) {
054                        final ScaleMetrics diffMetrics = Scales.getScaleMetrics(otherScale - scale);
055                        final long otherRescaled = diffMetrics.divideByScaleFactor(otherUnscaled);
056                        final int cmp = Long.compare(unscaled, otherRescaled);
057                        if (cmp != 0) {
058                                return cmp;
059                        }
060                        // remainder must be zero for equality
061                        final long otherRemainder = otherUnscaled - diffMetrics.multiplyByScaleFactor(otherRescaled);
062                        return -Long.signum(otherRemainder);
063                } else {
064                        final ScaleMetrics diffMetrics = Scales.getScaleMetrics(scale - otherScale);
065                        final long rescaled = diffMetrics.divideByScaleFactor(unscaled);
066                        final int cmp = Long.compare(rescaled, otherUnscaled);
067                        if (cmp != 0) {
068                                return cmp;
069                        }
070                        // remainder must be zero for equality
071                        final long remainder = unscaled - diffMetrics.multiplyByScaleFactor(rescaled);
072                        return Long.signum(remainder);
073                }
074        }
075
076        // no instances
077        private Compare() {
078        }
079}