Groovy Function – Infinity Multiplication – Beyond Memory

Advertisement

/* "Copyright Notice", please do not remove.
 * Written by Kevin Ng
 * The full tutorial on this subject can be found @ http://kevinhng86.iblog.website or http://programming.world.edu.
 * Release date to http://programming.world.edu will lag at least one week after release on http://kevinhng86.iblog.website
 * This source code file is a part of Kevin Ng's Z library.
 * This source code is licenses under CCDL-1.0  A copy of CDDL1.0 can be found at https://opensource.org/licenses/CDDL-1.0
 * End "Copyright Notice"

 * Notice: This is the protype version of infiXF.
 *         This version does support decimal calculation.
 *         InfiXF is for sciencetific use.

 * Limitation: Although had not calculate the number to be that large yet, in theory InfiXF can calculate two strings of digits that are 1/5 the size of the hard drive.
 *             If the hard drive is 1 Terabyte, This program can calculate the multiplication procedure for two strings of digit with the combine storage of 200 GB.
 *             That is about 100 billion digits in length for each string of digits.
 *             This version does not come with the renderer.
 *             After a huge calculation, and if the answer file is larger than 1GB another program woulb be requires to render the answer on screen.
 *             InfiXF does not consume memory and have very little memory foot print.
 *             InfiXF however does requires the storage space as large as the two files that contained the strings of digits to produce the answer string.
 */
public class libZ
{
    public static void infiXF()
    {
        boolean isaNeg
        boolean isbNeg
        String afile = "a.infiX"
        String bfile = "b.infiX"
        String atmp = afile.concat(".tmp")
        String btmp = bfile.concat(".tmp")
        String outputfile = "result.infiX"
        String outputtmp = outputfile.concat(".tmp")
        String readA = ""
        String readB = ""
        long dAfterDecA = -1
        long dAfterDecB = -1
        long dAfterDecT = 0
        long tmpDReadA = 0
        long tmpDReadB = 0
        int perReadTmp = 50 // This is changeable, how many character to read at once during temporary file reading.
        byte[] bufferR

        try{
            RandomAccessFile FileA = new RandomAccessFile(afile, "r")
            FileWriter TmpA = new FileWriter(atmp)
            bufferR = new byte[(FileA.length() - 0 > perReadTmp? perReadTmp : (int)(FileA.length() - 0))]
            FileA.read(bufferR)
            readA = new String(bufferR)
            isaNeg = readA.charAt(0) == '-'
            readA = readA.replaceAll("^[-+]+", "")
            readA = readA.trim()
            dAfterDecA = readA.indexOf('.')
            dAfterDecA = dAfterDecA > -1? readA.length() - 1 - dAfterDecA : dAfterDecA
            if (dAfterDecA > -1){
                readA = readA.replaceAll("[.]", "")
            }
            TmpA.write(readA);

            while (FileA.getFilePointer() < FileA.length() ){
                bufferR = new byte[(FileA.length() - FileA.getFilePointer() > perReadTmp? perReadTmp : (int)(FileA.length() - FileA.getFilePointer()))]
                FileA.read(bufferR)
                readA = new String(bufferR)
                readA = readA.trim()
                if (dAfterDecA < 0){
                    dAfterDecA = readA.indexOf(".")
                    dAfterDecA = dAfterDecA > -1? readA.length() - 1 - dAfterDecA : -1
                    if (dAfterDecA > -1){
                        readA = readA.replaceAll("[.]", "")
                    }
                } else {
                    tmpDReadA = readA.length()
                    dAfterDecA = dAfterDecA + tmpDReadA
                }
                TmpA.write(readA)
            }
            TmpA.close()
            FileA.close()
        } catch (IOException e) {
            throw new IllegalArgumentException("Unable to process " + afile + "file" , e)
        }

        try{
            RandomAccessFile FileB = new RandomAccessFile(bfile, "r")
            FileWriter TmpB = new FileWriter(btmp)
            bufferR = new byte[(FileB.length() - 0 > perReadTmp? perReadTmp : (int)(FileB.length() - 0))]
            FileB.read(bufferR)
            readB = new String(bufferR)
            isbNeg = readB.charAt(0) == '-'
            readB = readB.replaceAll("^[-+]+", "")
            readB = readB.trim()

            dAfterDecB = readB.indexOf('.')
            dAfterDecB = dAfterDecB > -1? readB.length() - 1 - dAfterDecB : dAfterDecB
            if (dAfterDecB > -1){
                readB = readB.replaceAll("[.]", "")
            }
            TmpB.write(readB)

            while (FileB.getFilePointer() < FileB.length() ){
                bufferR = new byte[(FileB.length() - FileB.getFilePointer() > perReadTmp? perReadTmp : (int)(FileB.length() - FileB.getFilePointer()))]
                FileB.read(bufferR)
                readB = new String(bufferR)
                readB = readB.trim()
                if (dAfterDecB < 0){
                    dAfterDecB = readB.indexOf(".")
                    dAfterDecB = dAfterDecB > -1? readB.length() - 1 - dAfterDecB : -1
                    if (dAfterDecB > -1){
                        readB = readB.replaceAll("[.]", "")
                    }
                } else {
                    tmpDReadB = readB.length();
                    dAfterDecB = dAfterDecB + tmpDReadB
                }
                TmpB.write(readB)
            }
            TmpB.close()
            FileB.close()
        } catch (IOException e) {
            throw new IllegalArgumentException("Unable to process " + bfile + " file" , e)
        }

        String pad0 = ""
        dAfterDecA = (dAfterDecA < 0)? 0 : dAfterDecA
        dAfterDecB = (dAfterDecB < 0)? 0 : dAfterDecB
        dAfterDecT = dAfterDecA + dAfterDecB
        int digit = 9; // This is the amount of digits to calculate per cycle.
        long atmpsize = new File(atmp).length()
        long btmpsize = new File(btmp).length()
        long premakeoutlen = (atmpsize + btmpsize) + (digit * 2)

        while (pad0.length() < (digit - 1)){
            pad0 = "0".concat(pad0)
        }
        // This code is for the event of someone setting the digit variable to 1.
        // The event most likely not to occur. nevertheless being able to set the digit variable to one also offer the greatest backward compatibility in technology.
        String pad0tmp = pad0.length() < 1? "0" : pad0
        int digittmp = digit < 1? 1 : digit - 1

        try{
            FileWriter OutputTmp = new FileWriter(outputtmp);
            long idn = 0
            while (idn < premakeoutlen){
                OutputTmp.write(pad0tmp)
                idn = idn + digittmp
            }
            OutputTmp.close()
        } catch (IOException e) {
            throw new IllegalArgumentException("Unable to create " + outputtmp + " file" , e)
        }

        long a = 0
        long b = 0
        long o = 0
        long posrB = 1
        long posrO = 1
        long loopidxB = 1
        long temp = 0
        long tempadd = 0
        long blen = btmpsize
        long alen = 0
        long posrA = 0
        long leftover = 0
        long remainder = 0
        long loopidxA = 0
        long olen = new File(outputtmp).length()
        byte[] bufferC = new byte[digit]
        String tempaddstr = ""
        String tempstr = ""
        String leftoverstr = ""

        try{
            RandomAccessFile TmpB = new RandomAccessFile(btmp, "r")
            while (posrB != 0){
                alen = atmpsize
                posrA = 1
                leftover = 0
                remainder = 0
                loopidxA = 1
                posrB = blen - (loopidxB * digit)

                bufferC = new byte[(posrB > 0? digit : digit + (int)(posrB))]
                TmpB.seek(posrB > 0? posrB : 0)
                TmpB.read(bufferC)
                b = Long.parseLong(new String(bufferC))
                RandomAccessFile TmpA = new RandomAccessFile(atmp, "r")
                RandomAccessFile OutputTmp = new RandomAccessFile(outputtmp, "rw")
                while (posrA != 0){
                    posrO = olen - ((loopidxA + loopidxB - 1) * digit)
                    posrA = alen - (loopidxA * digit)

                    bufferC = new byte[(posrA > 0? digit : digit + (int)(posrA))]
                    TmpA.seek((posrA > 0? posrA : 0))
                    TmpA.read(bufferC)
                    a = Long.parseLong(new String(bufferC))

                    temp = (b * a + remainder + leftover)
                    tempstr = String.valueOf(temp)
                    leftover = tempstr.length() > digit? Long.parseLong(tempstr.substring(0,tempstr.length() - digit)) : 0
                    tempstr = pad0.concat(tempstr)

                    bufferC = new byte[digit]
                    OutputTmp.seek(posrO)
                    OutputTmp.read(bufferC)
                    o = Long.parseLong(new String(bufferC))

                    tempadd = Long.parseLong(tempstr.substring(tempstr.length() - digit )) + o
                    tempaddstr = String.valueOf(tempadd)
                    remainder = tempaddstr.length() > digit? Long.parseLong(tempaddstr.substring(0,tempaddstr.length() - digit)) : 0
                    tempaddstr = pad0.concat(tempaddstr)
                    OutputTmp.seek(posrO)
                    OutputTmp.writeBytes(tempaddstr.substring(tempaddstr.length() - digit))

                    posrA = posrA > 0? posrA : 0
                    loopidxA = loopidxA + 1
                }
                if (remainder + leftover > 0){
                    posrO = posrO - digit
                    leftoverstr = pad0.concat(String.valueOf(leftover + remainder))
                    OutputTmp.seek(posrO)
                    OutputTmp.writeBytes(leftoverstr.substring(leftoverstr.length() - digit))
                }
                OutputTmp.close()
                TmpA.close()
                posrB = posrB > 0? posrB : 0
                loopidxB = loopidxB + 1
            }
            TmpB.close()
        } catch (IOException e) {
            throw new IllegalArgumentException("Unable to process caculation for " + afile + " file and " + bfile + " file." , e)
        }

        boolean lead0End = false
        long dBeforeDec = olen - dAfterDecT
        long posw = 0
        long truncatediff = 0
        long truncatelen = 0
        String readOutputTmp = ""
        String checker = ""
        String truncatestr = ""

        try{
            RandomAccessFile OutputTmp = new RandomAccessFile(outputtmp, "r")
            FileWriter Output = new FileWriter(outputfile)
            if (isaNeg != isbNeg){
                Output.write("-")
            }
            while (posw < dBeforeDec){
                bufferR = new byte[(posw + perReadTmp < dBeforeDec? perReadTmp : (int)(dBeforeDec - posw))]
                OutputTmp.seek(posw)
                OutputTmp.read(bufferR)
                readOutputTmp = new String(bufferR)
                if (lead0End == false){
                    readOutputTmp = readOutputTmp.replaceAll("^0+", "")
                    lead0End = readOutputTmp.length() > 0? true : false
                }
                Output.write(readOutputTmp)
                posw = (posw + perReadTmp < dBeforeDec)? posw + perReadTmp : dBeforeDec
            }
            Output.close()


            long outputlen = new File(outputfile).length()
            RandomAccessFile Output2 = new RandomAccessFile(outputfile, "rw")
            if (outputlen < 2){
                bufferR = new byte[1]
                Output2.read(bufferR)
                checker = new String(bufferR)
                if (outputlen < 1 || checker.equals("-")){
                    Output2.seek(Output2.length())
                    Output2.writeBytes("0")
                }
            }

            if (dAfterDecT > 0){
                Output2.seek(Output2.length())
                Output2.writeBytes(".")
            }

            Output2.seek(Output2.length())
            while (posw < olen){
                OutputTmp.seek(posw)
                bufferR = new byte[(olen - posw > perReadTmp? perReadTmp : (int)(olen - OutputTmp.getFilePointer()))]
                OutputTmp.read(bufferR)
                readOutputTmp = new String(bufferR)
                truncatestr = readOutputTmp
                truncatestr = readOutputTmp.replaceAll('0+$', "")
                truncatediff = readOutputTmp.length() - truncatestr.length()
                truncatelen = truncatediff == readOutputTmp.length()? truncatediff + truncatelen : truncatediff
                Output2.writeBytes(readOutputTmp)
                posw = posw + perReadTmp
            }

            outputlen = Output2.length()
            Output2.setLength(outputlen - truncatelen)
            outputlen = Output2.length()
            Output2.seek(outputlen - 1)
            bufferR = new byte[1]
            Output2.read(bufferR)
            readOutputTmp = new String(bufferR)
            if (readOutputTmp.equals(".")){
                Output2.setLength(outputlen - 1)
            }
            Output2.close()
            OutputTmp.close()

        } catch (IOException e) {
            throw new IllegalArgumentException("Unable to process result file." , e)
        }
    }
    
    public static void randFile()
    {
        String fileA = "a.infiX"
        String fileB = "b.infiX"
        int randDigitA = (int)(Math.random() * (350 - 0) + 40)
        int randDigitB = (int)(Math.random() * (350 - 0) + 40)
        int randDecPOSA = (int)(Math.random() * (randDigitA - 20) + 20)
        int randDecPOSB = (int)(Math.random() * (randDigitB - 20) + 20)

        try {
            FileWriter RANDOMA = new FileWriter(fileA);
            RANDOMA.write("-")
            for (int idn = 0; idn < randDigitA; idn++){
                RANDOMA.write(""+(int)(Math.random() * (9 - 0) + 0))
                if (idn == randDecPOSA){
                    RANDOMA.write(".")
                }
            }
            RANDOMA.close()

            FileWriter RANDOMB = new FileWriter(fileB)
            for (int idn = 0; idn < randDigitB; idn++){
                RANDOMB.write(""+(int)(Math.random() * (9 - 0) + 0))
                if (idn == randDecPOSB){
                    RANDOMB.write(".")
                }
            }
            RANDOMB.close()

        } catch (IOException e) {
            throw new IllegalArgumentException("Unable to create " + fileA + " and " + fileB , e)
        }
    }
}

libZ.randFile()
libZ.infiXF()
System.out.println("Check in the current directory.")
System.out.println(" a.infiX is the file that hold the first set of digits.")
System.out.println(" b.infiX is the second file that hold the digits.")
System.out.println(" result.infiX is the result of the multiplication procedure.")
System.out.println("The name of the temporary file for them are a.infiX.tmp, b.infiX.tmp, result.infiX.tmp.")
System.out.println("Temporary files can be delete after execution, but are currently kept for debuging purposes.")
Advertisement


Random Article You May Like