001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2021, Jean-Marie Dautelle, Werner Keil, Otavio Santana. 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.internal.function.radix; 031 032import static org.apiguardian.api.API.Status.INTERNAL; 033 034import java.util.function.Consumer; 035 036import org.apiguardian.api.API; 037 038import tech.units.indriya.function.MixedRadix; 039import tech.units.indriya.internal.function.Calculator; 040 041/** 042 * Internal utility class to support {@link MixedRadix}. 043 * 044 * @author Andi Huber 045 * @since 2.0 046 */ 047@API(status=INTERNAL) 048public class MixedRadixSupport { 049 050 private final Radix[] radices; 051 052 /** 053 * 054 * @param radices - most significant first 055 */ 056 public MixedRadixSupport(Radix[] radices) { 057 this.radices = radices; 058 } 059 060 /** 061 * 062 * @param trailingRadixValue 063 * @param numberVisitor - gets past over the extracted numbers in least significant first order 064 */ 065 public void visitRadixNumbers(Number trailingRadixValue, Consumer<Number> numberVisitor) { 066 067 Number total = trailingRadixValue; 068 069 for(int i=0;i<radices.length;++i) { 070 071 Radix radix = radices[invertIndex(i)]; 072 073 boolean fractionalRemainder = i==0; 074 075 Number[] divideAndRemainder = radix.divideAndRemainder(total, !fractionalRemainder); 076 077 Number remainder = divideAndRemainder[1]; 078 079 numberVisitor.accept(remainder); 080 081 total = divideAndRemainder[0]; 082 083 } 084 085 numberVisitor.accept(total); 086 087 } 088 089 /** 090 * @param values - numbers corresponding to the radices in most significant first order, 091 * allowed to be of shorter length than the total count of radices 092 * @return sum of {@code values} each converted to the 'scale' of the trailing radix (the least significant), 093 * as given by the constructor of this instance 094 */ 095 public Number sumMostSignificant(Number[] values) { 096 097 int maxAllowedValueIndex = values.length - 1; 098 099 Number sum = values[0]; 100 101 for(int i=0;i<radices.length;++i) { 102 103 sum = radices[i].multiply(sum); 104 105 if(i >= maxAllowedValueIndex) { 106 continue; 107 } 108 109 sum = Calculator.of(sum).add(values[i+1]).peek(); // narrow each addition step 110 111 } 112 113 return sum; 114 115 } 116 117 // -- HELPER 118 119 private int invertIndex(int index) { 120 return radices.length - index - 1; 121 } 122 123}