/* * Copyright (c) 2009-2015 * IT-Consulting Stephan Schloepke (http://www.schloepke.de/) * klemm software consulting Mirko Klemm (http://www.klemm-scs.com/) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.jbasics.math.obsolete; import org.jbasics.arrays.ArrayConstants; /** * Helper class to deal with Sign/Magnitude arrays. That is an array representing a big integer number in form of * <code><em>a<sub>0</sub> + 2<sup>n</sup>a<sub>1</sub> + 2<sup>2n</sup>a<sub>2</sub> + ... + * 2<sup>in</sup>a<sub>i</sub></em></code> where n is the bits of the integer architecture. The values of the polynom * are stored in big endian order so the array is like <code><em>[a<sub>i</sub>, ... , a<sub>2</sub>, a<sub>1</sub>, * a<sub>0</sub>]</em></code>. Additionally a sign is used in form of a signum. * * @author Stephan Schloepke * @since 1.0 */ public class SignMagnitudeArrayHelper { /** * Convert a given byte array storing a two complements big number (radix 2<sup>8</sup>) to an absolute magnitude * stored in an int array (radix 2<sup>int bit length</sup>). * * @param input The input in two's complement to convert (null or zero lenght array is considered to by zero and * produces a zero length integer array) * * @return The absolute magnitude as int array (radix 2<sup>int bit length</sup>) * * @since 1.0 */ public static int[] convertFromTwoComplement(final byte[] input) { if (input == null || input.length == 0) { return ArrayConstants.ZERO_LENGTH_INT_ARRAY; } int startIndex = 0; boolean sign = input[0] < 0; if (sign) { while (startIndex < input.length && input[startIndex] == -1) { startIndex++; } } else { while (startIndex < input.length && input[startIndex] == 0) { startIndex++; } } // now we know the exact location of the last byte used in the two's complement int endIndex = input.length; if (endIndex - startIndex == 0) { return ArrayConstants.ZERO_LENGTH_INT_ARRAY; } int len = ((endIndex - startIndex) + 3) / 4; if (sign && (len * 4) == (endIndex - startIndex)) { // In the case that we exactly fit into the integers we need to ensure that the borrow // propagation will be good so we check // all bytes if they are zero. Than we will need one extra int int i = startIndex; while (i < endIndex && input[i++] == 0) { // Nothing to do here } if (i == endIndex) { len++; } } int[] result = new int[len]; boolean carry = true; for (int i = len - 1; i >= 0; i--) { int remaining = endIndex - startIndex; int tmp = 0; if (remaining >= 4) { remaining = 4; } else if (sign) { tmp = -1 << remaining * 8; } for (int bit = 0; remaining > 0; bit += 8, remaining--) { int t = input[--endIndex] & 0xff; tmp |= (t) << bit; } if (sign) { result[i] = ~tmp; if (carry) { carry = result[i]++ == 0; } } else { result[i] = tmp; } } return result; } /** * Converts a given signum (rang [-1,1]) with a given magnitude array to a byte array two's complement number. <p> A * zero length byte array is produced for a signum of zero indicating a zero value. </p> * * @param signum The signum of the number to produce (-1 negtiv, 0 zero, 1 positiv). * @param magnitude The absolute magnuted of the number (radix 2<sup>int bit length</sup>). * * @return The two's complement byte array (radix 2<sup>8</sup>) */ public static byte[] convertToTwoComplement(final int signum, final int[] magnitude) { if (signum == 0 || magnitude == null || magnitude.length == 0) { return ArrayConstants.ZERO_LENGTH_BYTE_ARRAY; } throw new UnsupportedOperationException(); } }