⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mutablenumeric.java

📁 java 数据库 功能强大 效率高 SmallSQL Database is a free DBMS library for the Java(tm) platform. It runs on
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* =============================================================
 * SmallSQL : a free Java DBMS library for the Java(tm) platform
 * =============================================================
 *
 * (C) Copyright 2004-2007, by Volker Berlin.
 *
 * Project Info:  http://www.smallsql.de/
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 *
 * ---------------
 * MutableNumeric.java
 * ---------------
 * Author: Volker Berlin
 * 
 */
package smallsql.database;

import java.math.*;

class MutableNumeric extends Number implements Mutable{

    private static final long serialVersionUID = -750525164208565056L;
    private int[] value;
    private int scale;
    private int signum;

    
    /** 
     * The most significant value is on position 0.
     */
    MutableNumeric(byte[] complement){
		setValue(complement);
    }
    
    private void setValue(byte[] complement){
        int length = complement.length;
        if(length == 0){
            value   = EMPTY_INTS;
            signum  = 0;
            return;
        }
        value = new int[ (length + 3) / 4 ];
        if(complement[0] < 0){
            negate( complement );
            signum = -1;
        }else{
			signum = 0;
        	for(int i=0; i<complement.length; i++)
        		if(complement[i] != 0){
        			signum = 1;
        			break;
        		}
        }
        for(int v=value.length-1; v>=0; v--){
            int temp = 0;
            for(int i=0; i<4 && 0<length; i++){
                temp |= (complement[ --length ] & 0xFF) << (i*8);
            }
            value[v] = temp;
        }
    }

    MutableNumeric(int complement){
        if(complement == 0){
            signum = 0;
            value = EMPTY_INTS;
        }else{
            value = new int[1];
            if(complement < 0){
                value[0] = -complement;
                signum = -1;
            }else{
                value[0] = complement;
                signum = 1;
            }
        }
    }

    MutableNumeric(int complement, int scale){
        this( complement );
        this.scale = scale;
    }

    MutableNumeric(long complement){
        if(complement == 0){
            signum = 0;
            value = EMPTY_INTS;
        }else{
            value = new int[2];
            if(complement < 0){
                value[0] = (int)(~(complement >> 32));
                value[1] = (int)(-complement);
                signum = -1;
            }else{
                value[0] = (int)(complement >> 32);
                value[1] = (int)complement;
                signum = 1;
            }
        }
    }

    MutableNumeric(long complement, int scale){
        this( complement );
        this.scale = scale;
    }

    MutableNumeric(double val){
    	//first convert it to a string, because double to BigDecimal has very large rounding bug
        this( new BigDecimal( String.valueOf(val) ) );
    }

    MutableNumeric(float val){
        //first convert it to a string, because float to BigDecimal has very large rounding bug
        this( new BigDecimal( String.valueOf(val) ) );
    }

    MutableNumeric(String val){
        this( new BigDecimal( val ) );
    }

    MutableNumeric( BigDecimal big ){
        this(big.unscaledValue().toByteArray() );
        scale   = big.scale();
    }

    MutableNumeric(int signum, int[] value, int scale){
        this.signum = signum;
        this.value  = value;
        this.scale  = scale;
    }
    
	MutableNumeric(MutableNumeric numeric){
		this.signum = numeric.signum;
		this.value  = new int[numeric.value.length];
		System.arraycopy(numeric.value, 0, value, 0, value.length);
		this.scale  = numeric.scale;
	}
    
    
    int[] getInternalValue(){
        return value;
    }
	

    /**
     * Add the value to the current MutableNumeric Object and change it.
     * @param num the added value
     */
    void add(MutableNumeric num){
		if(num.scale < scale){
			num.setScale(scale);
		}else
		if(num.scale > scale){
			setScale(num.scale);
		}
        add( num.signum, num.value );
    }
	

    private void add( int sig2, int[] val2){
        if(val2.length > value.length){
            int[] temp = val2;
            val2 = value;
            value = temp;
            int tempi = signum;
            signum = sig2;
            sig2 = tempi;
        }
        if(signum != sig2)
            sub(val2);
        else
            add(val2);
    }

    
    /**
     * Add the value to the current MutableNumeric Object and change it.
     * The parameter <code>val2</code> has a shorter or equals length.
     * The signum of both values is equals.
     * @param val2 the added value
     */
    private void add( int[] val2){
        long temp = 0;
        int v1 = value.length;
        for(int v2 = val2.length; v2>0; ){
            temp = (value[--v1] & 0xFFFFFFFFL) + (val2 [--v2] & 0xFFFFFFFFL) + (temp >>> 32);
            value[v1] = (int)temp;
        }
        boolean uebertrag = (temp >>> 32) != 0;
        while(v1 > 0 && uebertrag)
            uebertrag = (value[--v1] = value[v1] + 1) == 0;

        // resize if needed
        if(uebertrag){
			resizeValue(1);
        }
    }
    
    
    
    /**
     * Resize the value mantissa with a carryover. 
     * @param highBits Is the high value that is save on the resize place.
     */
	private void resizeValue(int highBits){
		int val[] = new int[value.length+1];
		val[0] = highBits;
		System.arraycopy(value, 0, val, 1, value.length);
		value = val;
    }
	 
    
    /**
     * Subtract the value to the current MutableNumeric Object and change it.
     * @param num the subtracted  value
     */
    void sub(MutableNumeric num){
		if(num.scale < scale){
			num.setScale(scale);
		}else
		if(num.scale > scale){
			setScale(num.scale);
		}
        add( -num.signum, num.value );
    }

    /**
     * Subtract the value to the current MutableNumeric Object and change it.
     * The parameter <code>val2</code> has a shorter or equals length.
     * The signum of both values is equals.
     * @param val2 the subtracted  value
     */
    private void sub(int[] val2){
        long temp = 0;
        int v1 = value.length;
        for(int v2 = val2.length; v2>0; ){
            temp = (value[--v1] & 0xFFFFFFFFL) - (val2 [--v2] & 0xFFFFFFFFL) + (temp >>>= 32);
            value[v1] = (int)temp;
        }

        boolean uebertrag = (temp >>> 32) != 0;
        while(v1 > 0 && uebertrag)
            uebertrag = (value[--v1] = value[v1] - 1) == -1;

        if(uebertrag){
            signum = -signum;
            int last = value.length-1;
            for(int i=0; i<=last; i++){
                value[i] = (i == last) ? -value[i] : ~value[i];
            }
        }
    }

    void mul(MutableNumeric num){
		//TODO performance
		BigDecimal big = toBigDecimal().multiply(num.toBigDecimal() );
		setValue( big.unscaledValue().toByteArray() );
		scale = big.scale();
		signum = big.signum();
    }

	final void mul(int factor){
		if(factor < 0){
			factor = - factor;
			signum = -signum;
		}
		long carryover = 0;
		for(int i = value.length-1; i>=0; i--){
			long v = (value[i] & 0xFFFFFFFFL) * factor + carryover;
			value[i] = (int)v;
			carryover = v >> 32;
		}
		if(carryover > 0){
			resizeValue( (int)carryover );
		}
	}
	

    void div(MutableNumeric num){
    	//TODO performance

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -