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.factory; 025 026import java.math.BigDecimal; 027import java.math.BigInteger; 028import java.math.RoundingMode; 029 030import org.decimal4j.api.Decimal; 031import org.decimal4j.api.ImmutableDecimal; 032import org.decimal4j.api.MutableDecimal; 033import org.decimal4j.scale.ScaleMetrics; 034 035/** 036 * Factory for {@link Decimal} values and Decimal arrays of the 037 * {@link #getScale() scale} defined by {@code <S>}. 038 * 039 * @param <S> 040 * the {@link #getScaleMetrics() scale metrics} type associated with 041 * decimals created by this factory 042 */ 043public interface DecimalFactory<S extends ScaleMetrics> { 044 /** 045 * Returns the scale metrics type associated with Decimal values created by 046 * this factory. 047 * 048 * @return the scale metrics defining the scale for Decimal values created 049 * by this factory 050 */ 051 S getScaleMetrics(); 052 053 /** 054 * Returns the scale of values created by this factory. 055 * 056 * @return the scale for Decimal values created by this factory 057 */ 058 int getScale(); 059 060 /** 061 * Returns the implementing class for immutable values. 062 * 063 * @return the implementation type for immutable Decimal values 064 */ 065 Class<? extends ImmutableDecimal<S>> immutableType(); 066 067 /** 068 * Returns the implementing class for mutable values. 069 * 070 * @return the implementation type for mutable Decimal values 071 */ 072 Class<? extends MutableDecimal<S>> mutableType(); 073 074 /** 075 * Returns a factory for the given {@code scale}. 076 * 077 * @param scale 078 * the scale of Decimal numbers created by the returned factory 079 * @return a decimal factory for numbers with the given scale 080 */ 081 DecimalFactory<?> deriveFactory(int scale); 082 083 /** 084 * Returns a factory for the given {@code scaleMetrics}. 085 * 086 * @param scaleMetrics 087 * the metrics defining the scale of the Decimal numbers created 088 * by the returned factory 089 * @param <S> 090 * the generic type for {@code scaleMetrics} 091 * @return a decimal factory for numbers with the scale specified by 092 * {@code scaleMetrics} 093 */ 094 @SuppressWarnings("hiding") 095 <S extends ScaleMetrics> DecimalFactory<S> deriveFactory(S scaleMetrics); 096 097 /** 098 * Returns a new immutable Decimal whose value is numerically equal to that 099 * of the specified {@code long} value. An exception is thrown if the 100 * specified value is too large to be represented as a Decimal of this 101 * factory's {@link #getScale() scale}. 102 * 103 * @param value 104 * long value to convert into an immutable Decimal value 105 * @return a Decimal value numerically equal to the specified {@code long} 106 * value 107 * @throws IllegalArgumentException 108 * if {@code value} is too large to be represented as a Decimal 109 * with the scale of this factory 110 */ 111 ImmutableDecimal<S> valueOf(long value); 112 113 /** 114 * Returns a new immutable Decimal whose value is calculated by rounding the 115 * specified {@code float} argument to the {@link #getScale() scale} of this 116 * factory using {@link RoundingMode#HALF_UP HALF_UP} rounding. An exception 117 * is thrown if the specified value is too large to be represented as a 118 * Decimal of this factory's scale. 119 * 120 * @param value 121 * float value to convert into an immutable Decimal value 122 * @return a Decimal calculated as: <code>round<sub>HALF_UP</sub>(value)</code> 123 * @throws IllegalArgumentException 124 * if {@code value} is NaN or infinite or if the magnitude is 125 * too large for the float to be represented as a 126 * {@code Decimal} with the scale of this factory 127 */ 128 ImmutableDecimal<S> valueOf(float value); 129 130 /** 131 * Returns a new immutable Decimal whose value is calculated by rounding the 132 * specified {@code float} argument to the {@link #getScale() scale} of this 133 * factory using the specified {@code roundingMode}. An exception is thrown 134 * if the specified value is too large to be represented as a Decimal of 135 * this factory's scale. 136 * 137 * @param value 138 * float value to convert into an immutable Decimal value 139 * @param roundingMode 140 * the rounding mode to apply during the conversion if necessary 141 * @return a Decimal calculated as: <code>round(value)</code> 142 * @throws IllegalArgumentException 143 * if {@code value} is NaN or infinite or if the magnitude is 144 * too large for the float to be represented as a 145 * {@code Decimal} with the scale of this factory 146 * @throws ArithmeticException 147 * if {@code roundingMode==UNNECESSARY} and rounding is 148 * necessary 149 */ 150 ImmutableDecimal<S> valueOf(float value, RoundingMode roundingMode); 151 152 /** 153 * Returns a new immutable Decimal whose value is calculated by rounding the 154 * specified {@code double} argument to the {@link #getScale() scale} of 155 * this factory using {@link RoundingMode#HALF_UP HALF_UP} rounding. An 156 * exception is thrown if the specified value is too large to be represented 157 * as a Decimal of this factory's scale. 158 * 159 * @param value 160 * double value to convert into an immutable Decimal value 161 * @return a Decimal calculated as: <code>round<sub>HALF_UP</sub>(value)</code> 162 * @throws IllegalArgumentException 163 * if {@code value} is NaN or infinite or if the magnitude is 164 * too large for the double to be represented as a 165 * {@code Decimal} with the scale of this factory 166 */ 167 ImmutableDecimal<S> valueOf(double value); 168 169 /** 170 * Returns a new immutable Decimal whose value is calculated by rounding the 171 * specified {@code double} argument to the {@link #getScale() scale} of 172 * this factory using the specified {@code roundingMode}. An exception is 173 * thrown if the specified value is too large to be represented as a Decimal 174 * of this factory's scale. 175 * 176 * @param value 177 * double value to convert into an immutable Decimal value 178 * @param roundingMode 179 * the rounding mode to apply during the conversion if necessary 180 * @return a Decimal calculated as: <code>round(value)</code> 181 * @throws IllegalArgumentException 182 * if {@code value} is NaN or infinite or if the magnitude is 183 * too large for the double to be represented as a 184 * {@code Decimal} with the scale of this factory 185 * @throws ArithmeticException 186 * if {@code roundingMode==UNNECESSARY} and rounding is 187 * necessary 188 */ 189 ImmutableDecimal<S> valueOf(double value, RoundingMode roundingMode); 190 191 /** 192 * Returns a new immutable Decimal whose value is numerically equal to that 193 * of the specified {@link BigInteger} value. An exception is thrown if the 194 * specified value is too large to be represented as a Decimal of this 195 * factory's {@link #getScale() scale}. 196 * 197 * @param value 198 * {@code BigInteger} value to convert into an immutable Decimal 199 * value 200 * @return a Decimal value numerically equal to the specified big integer 201 * value 202 * @throws IllegalArgumentException 203 * if {@code value} is too large to be represented as a Decimal 204 * with the scale of this factory 205 */ 206 ImmutableDecimal<S> valueOf(BigInteger value); 207 208 /** 209 * Returns a new immutable Decimal whose value is calculated by rounding the 210 * specified {@link BigDecimal} argument to the {@link #getScale() scale} of 211 * this factory using {@link RoundingMode#HALF_UP HALF_UP} rounding. An 212 * exception is thrown if the specified value is too large to be represented 213 * as a Decimal of this factory's scale. 214 * 215 * @param value 216 * {@code BigDecimal} value to convert into an immutable Decimal 217 * value 218 * @return a Decimal calculated as: <code>round<sub>HALF_UP</sub>(value)</code> 219 * @throws IllegalArgumentException 220 * if {@code value} too large to be represented as a Decimal 221 * with the scale of this factory 222 */ 223 ImmutableDecimal<S> valueOf(BigDecimal value); 224 225 /** 226 * Returns a new immutable Decimal whose value is calculated by rounding the 227 * specified {@link BigDecimal} argument to the {@link #getScale() scale} of 228 * this factory using the specified {@code roundingMode}. An exception is 229 * thrown if the specified value is too large to be represented as a Decimal 230 * of this factory's scale. 231 * 232 * @param value 233 * {@code BigDecimal} value to convert into an immutable Decimal 234 * value 235 * @param roundingMode 236 * the rounding mode to apply during the conversion if necessary 237 * @return a Decimal calculated as: <code>round(value)</code> 238 * @throws IllegalArgumentException 239 * if {@code value} too large to be represented as a Decimal 240 * with the scale of this factory 241 * @throws ArithmeticException 242 * if {@code roundingMode==UNNECESSARY} and rounding is 243 * necessary 244 */ 245 ImmutableDecimal<S> valueOf(BigDecimal value, RoundingMode roundingMode); 246 247 /** 248 * Returns a new immutable Decimal whose value is calculated by rounding the 249 * specified {@link Decimal} argument to the {@link #getScale() scale} of 250 * this factory using {@link RoundingMode#HALF_UP HALF_UP} rounding. An 251 * exception is thrown if the specified value is too large to be represented 252 * as a Decimal of this factory's scale. 253 * 254 * @param value 255 * Decimal value to convert into an immutable Decimal value of 256 * this factory's scale 257 * @return a Decimal calculated as: <code>round<sub>HALF_UP</sub>(value)</code> 258 * @throws IllegalArgumentException 259 * if {@code value} too large to be represented as a Decimal 260 * with the scale of this factory 261 */ 262 ImmutableDecimal<S> valueOf(Decimal<?> value); 263 264 /** 265 * Returns a new immutable Decimal whose value is calculated by rounding the 266 * specified {@link Decimal} argument to the {@link #getScale() scale} of 267 * this factory using the specified {@code roundingMode}. An exception is 268 * thrown if the specified value is too large to be represented as a Decimal 269 * of this factory's scale. 270 * 271 * @param value 272 * Decimal value to convert into an immutable Decimal value of 273 * this factory's scale 274 * @param roundingMode 275 * the rounding mode to apply during the conversion if necessary 276 * @return a Decimal calculated as: <code>round(value)</code> 277 * @throws IllegalArgumentException 278 * if {@code value} too large to be represented as a Decimal 279 * with the scale of this factory 280 * @throws ArithmeticException 281 * if {@code roundingMode==UNNECESSARY} and rounding is 282 * necessary 283 */ 284 ImmutableDecimal<S> valueOf(Decimal<?> value, RoundingMode roundingMode); 285 286 /** 287 * Translates the string representation of a {@code Decimal} into an 288 * immutable {@code Decimal}. The string representation consists of an 289 * optional sign, {@code '+'} or {@code '-'} , followed by a sequence of 290 * zero or more decimal digits ("the integer"), optionally followed by a 291 * fraction. 292 * <p> 293 * The fraction consists of a decimal point followed by zero or more decimal 294 * digits. The string must contain at least one digit in either the integer 295 * or the fraction. If the fraction contains more digits than this factory's 296 * {@link #getScale() scale}, the value is rounded using 297 * {@link RoundingMode#HALF_UP HALF_UP} rounding. An exception is thrown if 298 * the value is too large to be represented as a Decimal of this factory's 299 * scale. 300 * 301 * @param value 302 * String value to convert into an immutable Decimal value of 303 * this factory's scale 304 * @return a Decimal calculated as: <code>round<sub>HALF_UP</sub>(value)</code> 305 * @throws NumberFormatException 306 * if {@code value} does not represent a valid {@code Decimal} 307 * or if the value is too large to be represented as a Decimal 308 * with the scale of this factory 309 */ 310 ImmutableDecimal<S> parse(String value); 311 312 /** 313 * Translates the string representation of a {@code Decimal} into an 314 * immutable {@code Decimal}. The string representation consists of an 315 * optional sign, {@code '+'} or {@code '-'} , followed by a sequence of 316 * zero or more decimal digits ("the integer"), optionally followed by a 317 * fraction. 318 * <p> 319 * The fraction consists of a decimal point followed by zero or more decimal 320 * digits. The string must contain at least one digit in either the integer 321 * or the fraction. If the fraction contains more digits than this factory's 322 * {@link #getScale() scale}, the value is rounded using the specified 323 * {@code roundingMode}. An exception is thrown if the value is too large to 324 * be represented as a Decimal of this factory's scale. 325 * 326 * @param value 327 * String value to convert into an immutable Decimal value of 328 * this factory's scale 329 * @param roundingMode 330 * the rounding mode to apply if the fraction contains more 331 * digits than the scale of this factory 332 * @return a Decimal calculated as: <code>round(value)</code> 333 * @throws NumberFormatException 334 * if {@code value} does not represent a valid {@code Decimal} 335 * or if the value is too large to be represented as a Decimal 336 * with the scale of this factory 337 * @throws ArithmeticException 338 * if {@code roundingMode==UNNECESSARY} and rounding is 339 * necessary 340 */ 341 ImmutableDecimal<S> parse(String value, RoundingMode roundingMode); 342 343 /** 344 * Returns a new immutable Decimal whose value is numerically equal to 345 * <code>(unscaled × 10<sup>-scale</sup>)</code> where {@code scale} 346 * refers to this factory's {@link #getScale() scale}. 347 * 348 * @param unscaled 349 * unscaled value to convert into an immutable Decimal value 350 * @return a Decimal calculated as: 351 * <code>unscaled × 10<sup>-scale</sup></code> 352 */ 353 ImmutableDecimal<S> valueOfUnscaled(long unscaled); 354 355 /** 356 * Returns a new immutable Decimal whose value is numerically equal to 357 * <code>(unscaled × 10<sup>-scale</sup>)</code>. The result is rounded to 358 * the {@link #getScale() scale} of this factory using 359 * {@link RoundingMode#HALF_UP HALF_UP} rounding. An exception is thrown if 360 * the specified value is too large to be represented as a Decimal of this 361 * factory's scale. 362 * 363 * @param unscaled 364 * unscaled value to convert into an immutable Decimal value 365 * @param scale 366 * the scale to apply to the {@code unscaled} value 367 * @return a Decimal calculated as: 368 * <code>round<sub>HALF_UP</sub>(unscaled × 10<sup>-scale</sup>)</code> 369 * @throws IllegalArgumentException 370 * if {@code value} too large to be represented as a Decimal of 371 * this factory's scale 372 */ 373 ImmutableDecimal<S> valueOfUnscaled(long unscaled, int scale); 374 375 /** 376 * Returns a new immutable Decimal whose value is numerically equal to 377 * <code>(unscaled × 10<sup>-scale</sup>)</code>. The result is rounded to 378 * the {@link #getScale() scale} of this factory using the specified 379 * {@code roundingMode}. An exception is thrown if the specified value is 380 * too large to be represented as a Decimal of this factory's scale. 381 * 382 * @param unscaled 383 * unscaled value to convert into an immutable Decimal value 384 * @param scale 385 * the scale to apply to the {@code unscaled} value 386 * @param roundingMode 387 * the rounding mode to apply during the conversion if necessary 388 * @return a Decimal calculated as: 389 * <code>round(unscaled × 10<sup>-scale</sup>)</code> 390 * @throws IllegalArgumentException 391 * if {@code value} too large to be represented as a Decimal of 392 * this factory's scale 393 * @throws ArithmeticException 394 * if {@code roundingMode==UNNECESSARY} and rounding is 395 * necessary 396 */ 397 ImmutableDecimal<S> valueOfUnscaled(long unscaled, int scale, RoundingMode roundingMode); 398 399 /** 400 * Creates a one dimensional array of the specified {@code length} for 401 * immutable Decimal values. 402 * 403 * @param length 404 * the length of the returned array 405 * @return a new array of the specified length 406 */ 407 ImmutableDecimal<S>[] newArray(int length); 408 409 /** 410 * Creates a new mutable value initialized with zero. 411 * 412 * @return a new mutable Decimal value representing zero. 413 */ 414 MutableDecimal<S> newMutable(); 415 416 /** 417 * Creates a one dimensional array of the specified {@code length} for 418 * mutable Decimal values. 419 * 420 * @param length 421 * the length of the returned array 422 * @return a new array of the specified length 423 */ 424 MutableDecimal<S>[] newMutableArray(int length); 425}