package zeta.tool;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import zeta.TaskManager;
import zeta.tool.check.CheckConsistencyZetaZeros;
import zeta.util.StreamUtils;
import zeta.util.ThrowableHandler;
public class ZetaStatistic {
public static void main(String[] args) {
if (args.length == 3 && args[0].length() == 1) {
if (args[0].charAt(0) == 'v') {
verify(args[1], args[2]);
return;
} else if (args[0].charAt(0) == 'c') {
check(Integer.parseInt(args[1]), args[2]);
return;
} else if (args[0].charAt(0) == 'e') {
try {
expandFileAndCheck(args[1], args[2], null);
} catch (Exception e) {
ThrowableHandler.handle(e);
}
return;
}
} else if (args.length == 2 && args[0].length() == 1 && args[0].charAt(0) == 'r') {
reduceFilesize2(args[1]);
return;
} else if (args.length == 2 && args[0].length() == 1 && args[0].charAt(0) == 'g') {
System.out.println(getStartN(Double.parseDouble(args[1])));
return;
} else if (args.length == 1 && args[0].length() == 1 && args[0].charAt(0) == '?') {
System.out.println("USAGE: e(xpand) <input> <output>\n"
+ " r(educe) <input/output>"
+ " g(etStartN) <t>");
return;
}
calc(-1);
}
static void calc(int maxNumberToProceed) { try {
TaskManager.getTask("zeta-zeros").setResources(2); } catch (Exception e) {
ThrowableHandler.handle(e);
}
ZetaStatistic.maxNumberToProceed = maxNumberToProceed;
PrintStream stdOut = System.out;
PrintStream log = null;
try {
log = new PrintStream(new FileOutputStream("statistic.log", true), true);
System.setOut(log);
String[] lastError = new String[2];
lastError[0] = lastError[1] = "";
int anzahlError = 0;
while (true) {
String[] error = null;
try {
error = statistic();
} catch (ZipException ze) {
ThrowableHandler.handle(ze);
WorkUnit workUnit = new WorkUnit(ze.getMessage());
if (workUnit.isValid()) {
if (recomputation(workUnit.workUnitId, workUnit.range)) {
continue;
} else {
throw ze;
}
}
}
if (error == null) {
break;
}
if (error.length == 0) {
continue;
}
long[] sizeRange = new long[2];
sizeRange[0] = Long.parseLong(error[1])-100;
WorkUnit workUnit = new WorkUnit(error[4]);
long workUnitId = (workUnit.isValid())? workUnit.workUnitId : 0;
if (sizeRange[0] < workUnitId) {
sizeRange[0] = workUnitId;
}
if (!lastError[0].equals(error[0]) || !lastError[1].equals(error[1])) {
anzahlError = 0;
} else if (++anzahlError == 2) {
break;
}
lastError = error;
if (anzahlError == 0) {
sizeRange[1] = 200;
zetaZerosExpand(sizeRange[0], (int)sizeRange[1], 0);
if (updateData(sizeRange, error[2], error[3], error[4])) continue;
}
String statisticTmp = fastCheck(workUnitId, error);
int idx = statisticTmp.indexOf(';')+1;
int idx2 = statisticTmp.indexOf(';', idx);
if (idx2 == -1 || statisticTmp == error[5]) {
while (true) {
statisticTmp = error[5];
for (sizeRange[1] = 300; sizeRange[1] <= 1300; sizeRange[1] += 500, sizeRange[0] -= 100) {
zetaZerosExpand(sizeRange[0], (int)sizeRange[1], 0);
if (updateData(sizeRange, error[2], null, null)) break;
}
if (sizeRange[1] > 1300) {
for (sizeRange[1] = 10000; sizeRange[1] <= 50000; sizeRange[1] += 20000, sizeRange[0] -= 100) {
zetaZerosExpand(sizeRange[0], (int)sizeRange[1], 0);
if (updateData(sizeRange, error[2], null, null)) break;
}
if (sizeRange[1] > 50000) break;
}
statisticTmp = statistic(statisticTmp, ConstantProperties.TEMP_DIR, true);
idx = statisticTmp.indexOf(';')+1;
idx2 = statisticTmp.indexOf(';', idx);
if (idx2 != -1) break;
sizeRange[0] = Long.parseLong(statisticTmp.substring(idx))-100;
if (sizeRange[0] < workUnitId) sizeRange[0] = workUnitId;
}
}
reduceFilesize2(ConstantProperties.TEMP_DIR + "zeta_zeros.txt", error[4]);
updateData(null, error[2], error[3], error[4]);
}
} catch (Exception e) {
ThrowableHandler.handle(e);
} finally {
StreamUtils.close(log);
}
System.setOut(stdOut);
}
private static String[] statistic() throws Exception { File file = new File(ConstantProperties.FINAL_DIR + "/1");
File[] list = file.listFiles();
if (list != null) {
long maxRange = 0;
File tmpFile = null;
int size = 0;
for (int i = 0; i < list.length; ++i) {
String s = list[i].getName();
int l = s.length();
if (s.startsWith("zeta_zeros_") && l > 11 && Character.isDigit(s.charAt(11))) {
if (s.endsWith(".zip")) {
++size;
} else if (s.endsWith(".tmp") && s.startsWith("zeta_zeros_0_") && l > 13 && Character.isDigit(s.charAt(13))) {
int idx = 13;
while (++idx < l && Character.isDigit(s.charAt(idx)));
long r = Long.parseLong(s.substring(13, idx));
if (r > maxRange) {
maxRange = r;
tmpFile = list[i];
}
}
}
}
maxRange += 2;
WorkUnit[] workUnits = new WorkUnit[size];
size = 0;
for (int i = 0; i < list.length; ++i) {
String s = list[i].getName();
int l = s.length();
if (s.startsWith("zeta_zeros_") && s.endsWith(".zip") && l > 11 && Character.isDigit(s.charAt(11))) {
int idx = 11;
while (++idx < l && Character.isDigit(s.charAt(idx)));
if (++idx < l && Character.isDigit(s.charAt(idx)) && idx < l-3) {
workUnits[size++] = new WorkUnit(Long.parseLong(s.substring(11, idx-1)), Integer.parseInt(s.substring(idx, l-4)));
} else {
throw new RuntimeException(s);
}
}
}
Arrays.sort(workUnits);
String statisticTmp = null;
if (tmpFile != null) {
if (!lastTmpFilename.equals(tmpFile.getName())) {
lastTmpFilename = tmpFile.getName();
System.out.println(lastTmpFilename);
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream((int)tmpFile.length());
StreamUtils.writeData(new FileInputStream(tmpFile), buffer, true, true);
statisticTmp = buffer.toString();
}
byte[] buffer = new byte[1000000];
for (int i = 0; i < workUnits.length; ++i) {
if (workUnits[i].workUnitId <= maxRange && workUnits[i].workUnitId+workUnits[i].range > maxRange) {
String s = "zeta_zeros_" + workUnits[i].workUnitId + '_';
File f = null;
for (int j = 0; j < list.length; ++j) {
String s2 = list[j].getName();
if (s2.startsWith(s) && s2.endsWith(".zip")) {
f = list[j];
break;
}
}
if (f != null) {
System.out.println(f.getName());
try {
ZipInputStream zip = new ZipInputStream(new FileInputStream(f));
for (int k = 0; k < 2; ++k) {
ZipEntry zEntry = zip.getNextEntry();
String filename = null;
String name = zEntry.getName();
if (name.endsWith(".txt")) {
filename = "zeta_zeros.txt";
} else if (name.endsWith(".log")) {
filename = "zeta_zeros.log";
} else if (name.endsWith(".$$$")) {
zip.close();
GetData.decrypt(1, ConstantProperties.FINAL_DIR + "/1/" + f.getName()); return new String[0];
}
if (filename == null) {
System.err.println("Fatal error reading '" + f.getName() + "'!");
System.exit(1);
}
File tempFile = new File(ConstantProperties.TEMP_DIR + filename);
if (!tempFile.delete() && tempFile.exists()) {
System.err.println("Fatal error deleting '" + f.getName() + "'!");
System.exit(1);
}
try {
StreamUtils.writeData(zip, new FileOutputStream(tempFile), false, true);
} catch (IOException ioe) {
if (filename.equals("zeta_zeros.txt") && tempFile.length() > 50*1024*1024) { ThrowableHandler.handle(ioe);
throw new ZipException("Too large");
} else {
throw ioe;
}
}
}
zip.close();
} catch (NullPointerException npe) {
ThrowableHandler.handle(npe);
throw new ZipException(workUnits[i].toString());
} catch (EOFException ioe) {
ThrowableHandler.handle(ioe);
throw new ZipException(workUnits[i].toString());
} catch (ZipException ze) {
ThrowableHandler.handle(ze);
throw new ZipException(workUnits[i].toString());
}
if (reduceFilesize2(ConstantProperties.TEMP_DIR + "zeta_zeros.txt", ConstantProperties.TEMP_DIR + f.getName().substring(0, f.getName().length()-3) + "txt")) {
updateData(null, ConstantProperties.TEMP_DIR + "zeta_zeros.txt", ConstantProperties.TEMP_DIR + "zeta_zeros.log", f.getName());
return new String[0];
}
long[] problems = expandFileAndCheck(ConstantProperties.TEMP_DIR + "zeta_zeros.txt", workUnits[i]);
if (problems != null && problems.length > 1) {
if (workUnits[i].workUnitId == previousWorkUnitId && problems.length >= previousNumberProblems && previousFirstProblem == problems[0]) {
System.err.println("Fatal error: Again " + (problems.length/2) + " problems (" + (previousNumberProblems/2) + ')');
System.exit(1);
}
long sizeOfProblem = 0;
for (int k = 1; k < problems.length; k += 2) {
sizeOfProblem += problems[k];
}
System.out.println("Number of problems: " + (problems.length/2) + ", size=" + sizeOfProblem);
if (problems.length > 200 || sizeOfProblem*5 > workUnits[i].range) { throw new ZipException(workUnits[i].toString());
}
for (int k = 0; k < problems.length; k += 2) {
zetaZerosExpand(problems[k], (int)problems[k+1], 0);
}
updateData(problems, ConstantProperties.TEMP_DIR + "zeta_zeros.txt", ConstantProperties.TEMP_DIR + "zeta_zeros.log", f.getName());
previousWorkUnitId = workUnits[i].workUnitId;
previousNumberProblems = problems.length;
previousFirstProblem = problems[0];
return new String[0];
}
previousNumberProblems = 0;
previousWorkUnitId = workUnits[i].workUnitId;
if (!checkLog(ConstantProperties.TEMP_DIR + "zeta_zeros.log") || !checkHeader.checkHeader(workUnits[i].workUnitId, workUnits[i].range, ConstantProperties.TEMP_DIR + "zeta_zeros.log")) {
throw new ZipException(workUnits[i].toString());
}
if (problems != null && problems.length == 1) {
int lines = (int)problems[0];
if (lines > 0 && lines+500 < workUnits[i].range) {
String nameTxt = f.getName().substring(0, f.getName().length()-3) + "txt";
String nameLog = f.getName().substring(0, f.getName().length()-3) + "log";
file = new File(nameTxt);
file.delete();
new File(ConstantProperties.TEMP_DIR + "zeta_zeros.txt").renameTo(file);
if (!removeLastChar(ConstantProperties.TEMP_DIR + "zeta_zeros.log", nameLog)) {
throw new Exception("Internal Error!");
}
zetaZerosExpand(workUnits[i].workUnitId, workUnits[i].range, 0);
file = new File(ConstantProperties.TEMP_DIR + "zeta_zeros.log");
file.delete();
new File(nameLog).renameTo(file);
file = new File(ConstantProperties.TEMP_DIR + "zeta_zeros.txt");
file.delete();
new File(nameTxt).renameTo(file);
updateData(null, ConstantProperties.TEMP_DIR + "zeta_zeros.txt", ConstantProperties.TEMP_DIR + "zeta_zeros.log", f.getName());
return new String[0];
}
}
String statisticTmpOld = statisticTmp;
statisticTmp = statistic(statisticTmp, ConstantProperties.TEMP_DIR, false);
int idx = statisticTmp.indexOf(';')+1;
int idx2 = statisticTmp.indexOf(';', idx);
if (idx2 == -1) { final String[] result = { statisticTmp.substring(0, idx-1), statisticTmp.substring(idx), ConstantProperties.TEMP_DIR + "zeta_zeros.txt", ConstantProperties.TEMP_DIR + "zeta_zeros.log", f.getName(), statisticTmpOld };
return result;
}
maxRange = Long.parseLong(statisticTmp.substring(idx, idx2));
System.out.println("maxRange=" + maxRange + ", lastLine=" + statisticTmp.substring(0, idx-1));
FileWriter writer = new FileWriter(ConstantProperties.FINAL_DIR + "/1/zeta_zeros_0_" + maxRange + ".tmp");
writer.write(statisticTmp, 0, statisticTmp.length());
writer.close();
f = new File(ConstantProperties.TEMP_DIR + "zeta_zeros.txt");
f.delete();
f = new File(ConstantProperties.TEMP_DIR + "zeta_zeros.log");
f.delete();
if (maxNumberToProceed > 0 && --maxNumberToProceed == 0) return null; }
}
}
}
return null;
}
private static boolean checkLog(String filename) {
BufferedReader reader = null;
try {
int count = 0;
reader = new BufferedReader(new FileReader(filename));
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
if (line.indexOf("search3b") >= 0) {
System.out.println(filename + " used search3b!");
}
if (line.startsWith(".... We make a shift at")) {
System.out.println(filename + " contains shifts!");
System.err.println(filename + " contains shifts!");
return false;
}
}
} catch (IOException ioe) {
ThrowableHandler.handle(ioe);
} finally {
StreamUtils.close(reader);
}
return true;
}
private static boolean updateData(long[] sizeRange, String sourceTxt, String sourceLog, String destination) throws IOException {
boolean found = (sizeRange != null);
boolean foundOne = false;
boolean change = false;
int lines = 0;
if (found) {
File txt = new File("zeta_zeros_" + sizeRange[0] + '_' + sizeRange[1] + ".txt");
System.out.println(txt.getName());
BufferedReader reader = new BufferedReader(new FileReader(txt));
BufferedReader reader2 = new BufferedReader(new FileReader(sourceTxt));
BufferedWriter writer = new BufferedWriter(new FileWriter(ConstantProperties.TEMP_DIR + "tmp.txt"));
String line = reader.readLine();
String lineFull = line;
String line2Full = null;
if (line == null || line.length() == 0) {
return false;
}
String prefix = "";
String prefix2 = "";
int idxSizeRange = 2;
if (line.charAt(0) == '.') {
prefix = line.substring(1);
line = reader.readLine();
int idx = line.indexOf('.')+1;
lineFull = line.substring(0, idx) + prefix + line.substring(idx);
}
double lineValue = Double.parseDouble(lineFull.substring(lineFull.indexOf('.')+1));
System.out.println("start line=" + lineFull);
boolean first = true;
found = false;
while (true) {
String line2 = reader2.readLine();
if (line2 == null || line2.length() == 0) {
break;
}
if (first) {
first = false;
if (line2.charAt(0) == '.') {
prefix2 = line2.substring(1);
line2 = reader2.readLine();
}
}
int idx = line2.indexOf('.')+1;
line2Full = line2.substring(0, idx) + prefix2 + repairDot(line2.substring(idx));
if (equalLines(line2Full, lineFull) || lineValue > 0.0 && Double.parseDouble(line2Full.substring(idx)) > lineValue) {
writer.write(lineFull);
writer.newLine();
++lines;
found = true;
while (true) {
line = reader.readLine();
if (line == null) break;
if (line.length() == 0) continue;
idx = line.indexOf('.')+1;
lineFull = line.substring(0, idx) + prefix + line.substring(idx);
writer.write(lineFull);
writer.newLine();
change = true;
++lines;
}
lineValue = 0.0;
double valueLineFull = Double.parseDouble(lineFull.substring(lineFull.indexOf('.')+1));
while (line2Full != null && !equalLines(lineFull, line2Full)) {
line2 = reader2.readLine();
if (line2 == null) break;
if (line2.length() == 0) throw new IOException("wrong last shift!");
idx = line2.indexOf('.')+1;
String sl = prefix2 + repairDot(line2.substring(idx));
if (sl.length() == 0) continue;
line2Full = line2.substring(0, idx) + sl;
if (Double.parseDouble(sl) > valueLineFull) {
System.out.println("error: " + lineFull + ',' + line2Full);
found = false;
break;
}
}
if (found) {
foundOne = true;
}
System.out.println("end line=" + line2Full + ", found=" + found);
line = null;
lineValue = 0.0;
while (idxSizeRange < sizeRange.length) {
if (txt != null) {
reader.close();
txt.delete();
File log = new File("zeta_zeros_" + sizeRange[idxSizeRange-2] + '_' + sizeRange[idxSizeRange-1] + ".log");
log.delete();
}
idxSizeRange += 2;
if (sizeRange[idxSizeRange-2] > 0) {
txt = new File("zeta_zeros_" + sizeRange[idxSizeRange-2] + '_' + sizeRange[idxSizeRange-1] + ".txt");
System.out.println(txt.getName());
reader = new BufferedReader(new FileReader(txt));
lineFull = line = reader.readLine();
if (line == null || line.length() == 0) throw new IOException("internal io error!");
if (line.charAt(0) == '.') {
prefix = line.substring(1);
line = reader.readLine();
idx = line.indexOf('.')+1;
lineFull = line.substring(0, idx) + prefix + line.substring(idx);
} else prefix = "";
System.out.println("start line=" + lineFull);
lineValue = Double.parseDouble(lineFull.substring(lineFull.indexOf('.')+1));
found = false;
break;
}
txt = null;
}
} else {
writer.write(line2Full);
writer.newLine();
++lines;
}
}
writer.close();
reader.close();
reader2.close();
if (sizeRange.length > 500 && !foundOne) {
System.out.println("Fatal error: update not successful!");
System.exit(1);
}
for (int i = 0; i < sizeRange.length; i += 2) {
txt = new File("zeta_zeros_" + sizeRange[i] + '_' + sizeRange[i+1] + ".txt");
txt.delete();
File log = new File("zeta_zeros_" + sizeRange[i] + '_' + sizeRange[i+1] + ".log");
log.delete();
}
} else {
File f = new File(sourceTxt);
File txt = new File(ConstantProperties.TEMP_DIR + "tmp.txt");
txt.delete();
f.renameTo(txt);
foundOne = found = true;
}
if (foundOne || change && lines+50 >= sizeRange[1]) {
File f = new File(sourceTxt);
f.delete();
File txt = new File(ConstantProperties.TEMP_DIR + "tmp.txt");
txt.renameTo(f);
if (destination != null) {
String workUnit = ConstantProperties.TEMP_DIR + destination.substring(0, destination.length()-3) + "txt";
f = new File(workUnit);
new File(sourceTxt).renameTo(f);
reduceFilesize(workUnit);
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(destination));
zipOut.setLevel(Deflater.BEST_COMPRESSION);
zipOut.putNextEntry(new ZipEntry(destination.substring(0, destination.length()-3) + "txt"));
StreamUtils.writeData(new FileInputStream(workUnit), zipOut, true, false);
zipOut.putNextEntry(new ZipEntry(destination.substring(0, destination.length()-3) + "log"));
String dir = ConstantProperties.FINAL_DIR + "/1/";
StreamUtils.writeData(new FileInputStream(sourceLog), zipOut, true, true);
f.delete();
new File(dir + "tmp").mkdir();
f = new File(dir + destination);
f.renameTo(new File(dir + "tmp/" + destination));
f.delete();
new File(destination).renameTo(f);
}
}
return found;
}
private static boolean equalLines(String line1, String line2) {
if (line1.equals(line2)) {
return true;
}
int l = line2.length();
if (l > 2 && line1.startsWith(line2.substring(0, l-1))) {
int i1 = line1.indexOf('.')+1;
int i2 = line2.indexOf('.')+1;
if (i1 > 0 && i1 == i2) {
if (Math.abs(Double.parseDouble(line1.substring(i1))-Double.parseDouble(line2.substring(i2))) <= 0.001) {
return true;
}
}
}
return false;
}
private static String fastCheck(long nStart, String[] error) {
BufferedReader reader = null;
try {
int idx = 0;
long lastN = 0;
int lastSize = 100;
List problems = new ArrayList(20);
reader = new BufferedReader(new FileReader(ConstantProperties.TEMP_DIR + "zeta_zeros.log"));
long nPos = Long.parseLong(error[1]);
while (true) {
String line = reader.readLine();
if (line == null) break;
if (line.startsWith("This happened between ") || line.startsWith("Exit n=")) {
long n = 0;
int i = (line.charAt(0) == 'T')? 22 : 7;
final int l = line.length();
while (i < l && Character.isDigit(line.charAt(i))) { n *= 10; n += Character.digit(line.charAt(i), 10); ++i; }
if (nPos < n && lastN < nPos) {
if (lastN+lastSize+10 < nPos) {
lastSize = 100;
long n2 = nPos-50;
if (n2 < nStart) n2 = nStart;
final Object[] o = { new Long(n2), new Integer(lastSize) };
problems.add(o);
} else {
lastSize = (int)(nPos-lastN)+150;
nPos = ((Long)((Object[])problems.get(problems.size()-1))[0]).longValue();
final Object[] o = { new Long(nPos), new Integer(lastSize) };
problems.add(problems.size()-1, o);
}
lastN = nPos;
}
if (lastN < n) {
if (lastN+lastSize+10 < n) {
lastSize = 100;
long n2 = n-50;
if (n2 < nStart) n2 = nStart;
final Object[] o = { new Long(n2), new Integer(lastSize) };
problems.add(o);
} else {
lastSize = (int)(n-lastN)+150;
n = ((Long)((Object[])problems.get(problems.size()-1))[0]).longValue();
final Object[] o = { new Long(n), new Integer(lastSize) };
problems.set(problems.size()-1, o);
}
}
lastN = n;
}
}
int j = 0;
int l = problems.size();
if (l == 0) {
final Object[] o = { new Long(nPos), new Integer(100) };
problems.add(o);
l = 1;
}
l *= 2;
long[] sizeRange = new long[l];
for (int i = 0; i < l; i += 2) {
Object[] o = (Object[])problems.get(i/2);
sizeRange[i] = ((Long)o[0]).longValue();
sizeRange[i+1] = ((Integer)o[1]).intValue();
}
int repeat = 0;
do {
for (int i = 0; i < l; i += 2) {
long n2 = sizeRange[i]-10;
if (n2 < nStart) n2 = nStart;
sizeRange[i] = n2;
sizeRange[i+1] += 20;
zetaZerosExpand(sizeRange[i], (int)sizeRange[i+1], 0);
}
} while (!updateData(sizeRange, error[2], error[3], null) && ++repeat < 3);
reader.close();
reader = null;
return statistic(error[5], ConstantProperties.TEMP_DIR, false);
} catch (IOException ioe) {
ThrowableHandler.handle(ioe);
return error[5];
} finally {
StreamUtils.close(reader);
}
}
private static void check(int gramBlockLength, String filename) {
BufferedReader reader = null;
BufferedReader reader2 = null;
try {
int blocks = 0;
WorkUnit workUnit = new WorkUnit(filename);
if (workUnit.isValid()) {
reader = new BufferedReader(new FileReader(filename));
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
if (line.indexOf('.') == gramBlockLength) {
boolean found = false;
if (zetaZerosExpand(workUnit.workUnitId-5, 20, 0) != 0) {
throw new IOException();
}
File f = new File("zeta_zeros_" + (workUnit.workUnitId-5) + "_20.txt");
reader2 = new BufferedReader(new FileReader(f));
while (true) {
String line2 = reader2.readLine();
if (line2 == null) {
break;
}
if (line2.equals(line)) {
found = true;
break;
}
}
reader2.close();
if (!found) {
System.out.println("Error: " + line);
return;
}
f.delete();
f = new File("zeta_zeros_" + (workUnit.workUnitId-5) + "_20.log");
f.delete();
for (int i = 1; i < gramBlockLength; ++i) {
reader.readLine();
}
workUnit.workUnitId += gramBlockLength-1;
++blocks;
}
++workUnit.workUnitId;
}
reader.close();
}
System.out.println(blocks + " blocks are checked.");
} catch (IOException ioe) {
ThrowableHandler.handle(ioe);
} finally {
StreamUtils.close(reader);
StreamUtils.close(reader2);
}
}
static {
try {
System.loadLibrary("zeta_zeros");
} catch (Exception e) {
ThrowableHandler.handle(e);
}
}
static long[] expandFileAndCheck(String filename, WorkUnit workUnit) throws Exception {
return expandFileAndCheck(filename, filename, workUnit);
}
static long[] expandFileAndCheck(String source, String destination, WorkUnit workUnit) throws Exception {
long maxWorkUnitId = (workUnit == null)? 0 : workUnit.workUnitId+workUnit.range;
List problems = new ArrayList(100);
BufferedReader reader = null;
BufferedWriter writer = null;
boolean equal = false;
if (source.equals(destination)) {
equal = true;
destination += ".tmp";
}
int lines = 0;
int wrongLines = 0;
try {
reader = new BufferedReader(new FileReader(source));
String line = reader.readLine();
if (line == null || line.length() == 0) {
throw new Exception("Internal Error!");
}
writer = new BufferedWriter(new FileWriter(destination));
String prefix = "";
String previousLineFull = null;
if (line.charAt(0) == '.') {
prefix = line.substring(1);
} else {
previousLineFull = repairDot(line);
writer.write(previousLineFull);
writer.newLine();
++lines;
}
int expandLines = 0;
int plausibilityChecks = 0;
long nStart = -1;
long problemNStart = -1;
long workUnitId = -1;
double gram = 9.6669;
double value = 0.0;
double nextGramPoint = 0.0;
while (true) {
line = reader.readLine();
if (line == null || line.length() == 0) {
break;
}
if (Character.isDigit(line.charAt(line.length()-1))) {
plausibilityChecks |= 2;
}
int idx = line.indexOf('.')+1;
if (idx > 1) {
plausibilityChecks |= 1;
}
String postfix = repairDot(line.substring(idx));
if (problemNStart >= 0) {
if (justDots(line, idx)) {
continue;
}
try {
nextGramPoint = Double.parseDouble(prefix + postfix);
} catch (NumberFormatException nfe) {
continue;
}
long nPos = Math.max(getStartN(nextGramPoint)-2, problemNStart);
double d = nextGramPoint;
do {
d = Gram(++nPos, d);
} while (d < nextGramPoint);
nextGramPoint = d;
boolean contains = false;
if (problems.size() > 0) {
long[] o = (long[])problems.get(problems.size()-1);
contains = (nPos <= o[0]+o[1] && problemNStart >= o[0]);
}
if (!contains) {
problems.add(new long[] { problemNStart, nPos-problemNStart+5 });
}
problemNStart = -1;
nStart = nPos;
}
if (workUnitId > 0 && nStart-workUnitId > 10 && previousLineFull != null && (idx == line.length() && line.charAt(0) == '1' && idx == 2 || line.indexOf(".........................", idx) > 0)) {
double d = Double.parseDouble(previousLineFull.substring(previousLineFull.indexOf('.')+1));
if (value > 0.0 && d < value) {
continue;
}
nStart = getStartN(d);
problemNStart = nStart-5;
continue;
}
String lineFull = "";
if (prefix.length() > 0 && (postfix.length() == 0 && nStart >= 0 || postfix.length() > 0 && postfix.charAt(0) == '.')) {
boolean equalGram = (postfix.length() == 0);
if (nStart >= 0 && postfix.length() > 0) {
if (nextGramPoint > 0.0) {
gram = nextGramPoint;
nextGramPoint = 0.0;
} else {
nStart += postfix.length();
gram = Gram(nStart, gram);
}
} else if (postfix.length() > 1) {
try {
workUnitId = nStart = Long.parseLong(postfix.substring(1));
} catch (NumberFormatException nfe) {
ThrowableHandler.handle(nfe);
throw new ZipException(workUnit.toString());
}
gram = Gram(nStart, (nStart > 1)? 6.2831853*nStart/Math.log((double)nStart) : 9.6669);
}
postfix = String.valueOf((long)Math.floor((gram - Math.floor(gram))*1000.0+0.5));
if (postfix.length() == 4) {
if (!equalGram) {
gram += 1.0;
}
postfix = String.valueOf(Integer.parseInt(postfix.substring(1)));
}
String s = ".";
switch (postfix.length()) {
case 0: s = "";
break;
case 1: if (postfix.charAt(0) != '0') {
s = ".00";
} else {
postfix = s = "";
}
break;
case 2: s = ".0";
if (postfix.charAt(1) == '0') {
postfix = String.valueOf(postfix.charAt(0));
}
break;
case 3: if (postfix.charAt(2) == '0') {
postfix = (postfix.charAt(1) == '0')? String.valueOf(postfix.charAt(0)) : postfix.substring(0, 2);
}
break;
}
lineFull = line.substring(0, idx) + String.valueOf((long)Math.floor(gram)) + s + postfix;
if (++expandLines >= 10000) {
System.out.println("Number of lines which are continuously reduced: " + expandLines);
throw new ZipException(workUnit.toString());
}
} else {
lineFull = line.substring(0, idx) + prefix + postfix;
expandLines = 0;
}
double valueLine = 0.0;
try {
valueLine = Double.parseDouble(lineFull.substring(lineFull.indexOf('.')+1));
} catch (NumberFormatException nfe) {
System.out.println("format error line: " + lineFull + ", prev=" + previousLineFull);
continue;
}
if (value > 0.0 && Math.abs(valueLine-value) > 20000.0 || valueLine < value ) {
++wrongLines;
continue;
}
if (value > 0.0 && valueLine-value > 5.0) {
if (justDots(line, idx)) {
continue;
}
nextGramPoint = valueLine;
long nPos = Math.max(getStartN(nextGramPoint)-2, problemNStart);
if (maxWorkUnitId > 0 && nPos > maxWorkUnitId) {
nPos = maxWorkUnitId-2;
nextGramPoint = valueLine = Gram(maxWorkUnitId, nextGramPoint);
}
double d = nextGramPoint;
do {
d = Gram(++nPos, d);
} while (d < nextGramPoint);
nextGramPoint = d;
long prevNPos = getStartN(value);
boolean contains = false;
if (problems.size() > 0) {
long[] o = (long[])problems.get(problems.size()-1);
contains = (nPos <= o[0]+o[1] && prevNPos >= o[0]);
}
if (!contains) {
problems.add(new long[] { prevNPos, nPos-prevNPos+5 });
}
nStart = nPos;
}
writer.write(lineFull);
writer.newLine();
++lines;
previousLineFull = lineFull;
value = valueLine;
}
if (plausibilityChecks < 3) {
System.out.println("Wrong file format: " + source);
System.err.println("Wrong file format: " + source);
throw new ZipException(workUnit.toString());
}
} catch (ZipException ze) {
throw ze;
} catch (IOException ioe) {
ThrowableHandler.handle(ioe);
throw new Exception("Internal Error!");
} finally {
StreamUtils.close(reader);
try {
if (writer != null) {
writer.close();
}
} catch (IOException ioe) {
throw new Exception("Internal Error!");
}
}
if (workUnit != null && (wrongLines*5 > workUnit.range || wrongLines > 0 && lines*3 < workUnit.range)) { System.out.println("Number of wrong lines: " + wrongLines + " of " + lines + " (" + workUnit.range + ')');
throw new ZipException(workUnit.toString());
}
if (equal) {
File f = new File(source);
f.delete();
if ( !new File(destination).renameTo(f)) {
throw new Exception("Internal Error!");
}
}
if (problems.size() > 0) {
long[] result = new long[2*problems.size()];
Iterator i = problems.iterator();
for (int j = 0; i.hasNext(); j += 2) {
long[] value = (long[])i.next();
result[j] = value[0];
result[j+1] = value[1];
}
return result;
}
return new long[] { lines };
}
private static boolean removeLastChar(String source, String destination) {
FileInputStream in = null;
FileOutputStream out = null;
try {
byte[] buffer = new byte[1000000];
long size = new File(source).length();
in = new FileInputStream(source);
out = new FileOutputStream(destination);
while (true) {
int n = in.read(buffer);
if (n <= 0) break;
size -= n;
if (size == 0) {
out.write(buffer, 0, n-1);
break;
} else {
out.write(buffer, 0, n);
}
}
} catch (IOException ioe) {
ThrowableHandler.handle(ioe);
return false;
} finally {
StreamUtils.close(in);
try {
if (out != null) {
out.close();
}
} catch (IOException ioe) {
return false;
}
}
return true;
}
private static boolean recomputation(long workUnitId, int range) throws IOException {
String nameTxt = "zeta_zeros_" + workUnitId + '_'+ range + ".txt";
String nameLog = "zeta_zeros_" + workUnitId + '_'+ range + ".log";
String destination = "zeta_zeros_" + workUnitId + '_'+ range + ".zip";
File fTxt = new File(nameTxt);
File fLog = new File(nameLog);
fTxt.delete();
fLog.delete();
if (zetaZeros(workUnitId, range, 0) == 0) {
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(destination));
zipOut.setLevel(Deflater.BEST_COMPRESSION);
zipOut.putNextEntry(new ZipEntry(nameTxt));
StreamUtils.writeData(new FileInputStream(nameTxt), zipOut, true, false);
zipOut.putNextEntry(new ZipEntry(nameLog));
String dir = ConstantProperties.FINAL_DIR + "/1/";
StreamUtils.writeData(new FileInputStream(nameLog), zipOut, true, true);
fTxt.delete();
fLog.delete();
File f = new File(dir + "tmp");
f.mkdir();
f = new File(dir + destination);
f.renameTo(new File(dir + "tmp/" + destination));
f.delete();
return (new File(destination).renameTo(f));
}
return false;
}
private static String repairDot(String s) {
final int i = s.indexOf(',');
if (i >= 0 && s.indexOf(',', i+1) < 0 && s.indexOf('.') < 0) {
StringBuffer buffer = new StringBuffer(s);
buffer.setCharAt(i, '.');
s = buffer.toString();
}
return s;
}
private static boolean justDots(String s, int i) {
final int l = s.length();
for (; i < l; ++i) {
if (s.charAt(i) != '.') {
return false;
}
}
return true;
}
static double Gram(long n) {
return Gram(n, (n > 1)? 6.2831853*n/Math.log((double)n) : 9.6669);
}
final static double PI = 3.1415926535897932384626433832795028841971693993751;
final static double PI_INV = 1.0/PI;
final static double TWO_PI = 2*PI;
final static double TWO_PI_INV = 0.5*PI_INV;
static double Gram(long n, double a) { double t2,t1 = a*TWO_PI_INV;
double d = ((double)n) + 0.125;
do {
t2 = (t1+d)/Math.log(t1);
if (Math.abs(t1-t2) < t2*1e-13) return t2*TWO_PI;
t1 = (t2+d)/Math.log(t2);
} while (Math.abs(t1-t2) >= t1*1e-13);
return t1*TWO_PI;
}
static long getStartN(double t) {
long n2,n1 = (long)(t*0.83675);
double g2,g1 = Gram(n1);
if (g1 > t) {
do {
n2 = n1; g2 = g1;
n1 >>= 1;
g1 = Gram(n1);
} while (g1 > t);
} else {
n2 = n1; g2 = g1;
while (true) {
n2 <<= 1;
g2 = Gram(n2);
if (g2 > t) break;
g1 = g2; n1 = n2;
}
}
while (n2-n1 > 1) {
long n = (n1+n2) >> 1;
double g = Gram(n);
if (g > t) n2 = n;
else n1 = n;
}
return n1;
}
static int zetaZerosExpand(long workUnitId, int range, int sleep) {
int result = zetaZeros(workUnitId, range, sleep);
try {
expandFileAndCheck("zeta_zeros_" + workUnitId + '_' + range + ".txt", new WorkUnit(workUnitId, range));
if (StreamUtils.search(new String[] { "... Close pair of zeros between" }, new FileInputStream("zeta_zeros_" + workUnitId + '_' + range + ".log"), true)) {
System.out.println("Close zero in 'zeta_zeros_" + workUnitId + '_' + range + ".log'");
System.exit(1); }
} catch (Exception e) {
ThrowableHandler.handle(e);
System.exit(1);
}
return result;
}
private static boolean reduceFilesize2(String filename) {
return reduceFilesize2(filename, filename);
}
private static boolean reduceFilesize2(String filename1, String filename2) {
if (!filename1.equals(filename2)) {
File f1 = new File(filename1);
File f2 = new File(filename2);
f2.delete();
if (!f1.renameTo(f2)) return false;
boolean result = reduceFilesize(filename2);
return (f2.renameTo(f1) && result);
}
return reduceFilesize(filename1);
}
private static int previousNumberProblems = 0;
private static long previousFirstProblem = 0;
private static long previousWorkUnitId = 0;
private static int maxNumberToProceed = -1;
private static String lastTmpFilename = "";
private static CheckConsistencyZetaZeros checkHeader = new CheckConsistencyZetaZeros();
static native boolean reduceFilesize(String filename);
private static native String statistic(String tmpEntry, String directory, boolean removeLine);
private static native void verify(String smallFile, String largeFile);
static native int zetaZeros(long start, int range, int sleepN);
private static class WorkUnit implements Comparable {
int range;
long workUnitId = -1;
public WorkUnit(long workUnitId, int range) {
this.workUnitId = workUnitId;
this.range = range;
}
public WorkUnit(String text) {
if (text != null) {
int l = text.length();
if (l > 11 && text.startsWith("zeta_zeros_") && Character.isDigit(text.charAt(11))) {
int idx = 11;
while (++idx < l && Character.isDigit(text.charAt(idx)));
if (idx+1 < l && text.charAt(idx) == '_' && Character.isDigit(text.charAt(idx+1))) {
int idx2 = ++idx;
while (++idx2 < l && Character.isDigit(text.charAt(idx2)));
range = Integer.parseInt(text.substring(idx, idx2));
workUnitId = Long.parseLong(text.substring(11, idx-1));
}
}
}
}
public int compareTo(Object o) {
WorkUnit w = (WorkUnit)o;
if (workUnitId < w.workUnitId) {
return -1;
} else if (workUnitId > w.workUnitId) {
return 1;
} else if (range < w.range) {
return 1;
} else if (range > w.range) {
return -1;
} else {
return 0;
}
}
public boolean isValid() {
return (workUnitId >= 0);
}
public String toString() {
return "zeta_zeros_" + workUnitId + '_' + range;
}
}
}