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.generic; 025 026import java.util.Objects; 027 028import org.decimal4j.api.Decimal; 029import org.decimal4j.api.MutableDecimal; 030import org.decimal4j.base.AbstractMutableDecimal; 031import org.decimal4j.factory.Factories; 032import org.decimal4j.scale.ScaleMetrics; 033import org.decimal4j.scale.Scales; 034 035/** 036 * <code>GenericMutableDecimal</code> is an {@link MutableDecimal} implemented in a 037 * generic way, that is, different instances can have different scales. In 038 * contrast the classes defined in the {@code mutable} package have have no 039 * generic parameter as they have a fixed scale per class. 040 * 041 * @param <S> 042 * the scale metrics type associated with this Decimal 043 */ 044public final class GenericMutableDecimal<S extends ScaleMetrics> 045 extends AbstractMutableDecimal<S, GenericMutableDecimal<S>> implements Cloneable { 046 047 private static final long serialVersionUID = 1L; 048 049 private final S scaleMetrics; 050 051 /** 052 * Creates a new {@code GenericMutableDecimal} with value zero. 053 * 054 * @param scaleMetrics 055 * the metrics object defining the scale for the zero value 056 */ 057 public GenericMutableDecimal(S scaleMetrics) { 058 this(scaleMetrics, 0); 059 } 060 061 /** 062 * Creates a new {@code GenericMutableDecimal} with the same value and scale 063 * as the given {@code decimal} argument. 064 * 065 * @param decimal 066 * the numeric value to assign to the created mutable Decimal 067 */ 068 public GenericMutableDecimal(Decimal<S> decimal) { 069 this(decimal.getScaleMetrics(), decimal.unscaledValue()); 070 } 071 072 /** 073 * Creates a new {@code GenericMutableDecimal} with the scale specified by 074 * the given {@code scaleMetrics} argument. The numeric value of new the 075 * Decimal is <code>unscaledValue × 10<sup>-scale</sup></code> 076 * 077 * @param scaleMetrics 078 * the metrics object defining the scale for the new value 079 * @param unscaledValue 080 * the unscaled long value representing the new Decimal's 081 * numerical value before applying the scale factor 082 */ 083 public GenericMutableDecimal(S scaleMetrics, long unscaledValue) { 084 super(unscaledValue); 085 this.scaleMetrics = Objects.requireNonNull(scaleMetrics, "scaleMetrics cannot be null"); 086 } 087 088 /** 089 * Creates and returns a new {@code GenericMutableDecimal} with the same 090 * value and scale as the given {@code decimal} argument. 091 * 092 * @param decimal 093 * the numeric value to assign to the created mutable Decimal 094 * @param <S> 095 * the scale metrics type 096 * @return a new generic mutable Decimal value with scale and value copied 097 * from the {@code decimal} argument 098 */ 099 public static <S extends ScaleMetrics> GenericMutableDecimal<S> valueOf(Decimal<S> decimal) { 100 return new GenericMutableDecimal<S>(decimal); 101 } 102 103 /** 104 * Creates and returns a new {@code GenericMutableDecimal} with the scale 105 * specified by the given {@code scaleMetrics} argument. The numeric value 106 * of new the Decimal is 107 * <code>unscaledValue × 10<sup>-scale</sup></code> 108 * 109 * @param scaleMetrics 110 * the metrics object defining the scale for the new value 111 * @param unscaled 112 * the unscaled long value representing the new Decimal's 113 * numerical value before applying the scale factor 114 * @param <S> 115 * the scale metrics type 116 * @return a new Decimal value representing 117 * <code>unscaledValue × 10<sup>-scale</sup></code> 118 */ 119 public static <S extends ScaleMetrics> GenericMutableDecimal<S> valueOfUnscaled(S scaleMetrics, long unscaled) { 120 return new GenericMutableDecimal<S>(scaleMetrics, unscaled); 121 } 122 123 /** 124 * Creates and returns a new {@code GenericMutableDecimal} with the 125 * specified {@code scale} and value. The numeric value of new the Decimal 126 * is <code>unscaledValue × 10<sup>-scale</sup></code> 127 * 128 * @param scale 129 * the scale for the new value 130 * @param unscaled 131 * the unscaled long value representing the new Decimal's 132 * numerical value before applying the scale factor 133 * @return a new Decimal value representing 134 * <code>unscaledValue × 10<sup>-scale</sup></code> 135 */ 136 public static GenericMutableDecimal<?> valueOfUnscaled(int scale, long unscaled) { 137 return valueOfUnscaled(Scales.getScaleMetrics(scale), unscaled); 138 } 139 140 @Override 141 protected GenericMutableDecimal<S> create(long unscaled) { 142 return new GenericMutableDecimal<S>(scaleMetrics, unscaled); 143 } 144 145 @SuppressWarnings("unchecked") 146 @Override 147 protected GenericMutableDecimal<S>[] createArray(int length) { 148 return new GenericMutableDecimal[length]; 149 } 150 151 @Override 152 protected GenericMutableDecimal<S> self() { 153 return this; 154 } 155 156 @Override 157 public S getScaleMetrics() { 158 return scaleMetrics; 159 } 160 161 @Override 162 public int getScale() { 163 return scaleMetrics.getScale(); 164 } 165 166 @Override 167 public GenericDecimalFactory<S> getFactory() { 168 return Factories.getGenericDecimalFactory(scaleMetrics); 169 } 170 171 @Override 172 public GenericMutableDecimal<S> clone() { 173 return new GenericMutableDecimal<S>(scaleMetrics, unscaledValue()); 174 } 175 176 @Override 177 public GenericImmutableDecimal<S> toImmutableDecimal() { 178 return new GenericImmutableDecimal<S>(this); 179 } 180 181 @Override 182 public GenericMutableDecimal<S> toMutableDecimal() { 183 return this; 184 } 185}