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