1 /* 2 * Copyright (C) 2023 Alberto Irurueta Carro (alberto@irurueta.com) 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.irurueta.numerical; 17 18 /** 19 * Estimates factorial values as double precision floating point values. 20 */ 21 public class DoubleFactorialEstimator { 22 23 /** 24 * Cache size for factorial values that can be represented without overflowing with double 25 * precision. 26 * Values up to 170! are representable, 171! overflows. 27 */ 28 public static final int CACHE_SIZE = 171; 29 30 /** 31 * Cache of values. 32 */ 33 private final double[] cache; 34 35 /** 36 * Constructor with default cache size. 37 */ 38 public DoubleFactorialEstimator() { 39 this(CACHE_SIZE); 40 } 41 42 /** 43 * Constructor. 44 * 45 * @param cacheSize size of cache. 46 * @throws IllegalArgumentException if provided value is less than 1 or exceeds 171. 47 */ 48 public DoubleFactorialEstimator(final int cacheSize) { 49 if (cacheSize < 1) { 50 throw new IllegalArgumentException("Cache size must be at least 1"); 51 } 52 if (cacheSize > CACHE_SIZE) { 53 throw new IllegalArgumentException("Maximum allowed cache size is 171"); 54 } 55 56 // initialize cache 57 cache = new double[cacheSize]; 58 cache[0] = 1.0; 59 for (var i = 1; i < cacheSize; i++) { 60 cache[i] = i * cache[i - 1]; 61 } 62 } 63 64 /** 65 * Gets current cache size. 66 * 67 * @return cache size. 68 */ 69 public int getCacheSize() { 70 return cache.length; 71 } 72 73 /** 74 * Gets factorial of provided value represented with double precision. 75 * 76 * @param value value to compute factorial for. 77 * @return computed factorial value. 78 * 79 * @throws IllegalArgumentException if provided value exceeds cache size. 80 */ 81 public double factorial(final int value) { 82 if (value < 0) { 83 throw new IllegalArgumentException("Minimum supported value is 0"); 84 } 85 if (value >= cache.length) { 86 throw new IllegalArgumentException("Maximum supported value is " + (cache.length - 1)); 87 } 88 89 return cache[value]; 90 } 91 }