#define _CRT_SECURE_NO_WARNINGS
# include <cstdlib>
# include <iostream>
# include <iomanip>
#include <string>
# include <fstream>
# include <ctime>
# include <cmath>
using namespace std;
int main();
void dtable_data_write(ofstream &output, int m, int n, double table[]);
void dtable_write(string output_filename, int m, int n, double table[],
bool header);
void f(double a, double b, double t0, double t, int n, double x[],
double value[]);
int r83_np_fa(int n, double a[]);
double *r83_np_sl(int n, double a_lu[], double b[], int job);
void timestamp();
void u0(double a, double b, double t0, int n, double x[], double value[]);
double ua(double a, double b, double t0, double t);
double ub(double a, double b, double t0, double t);
int main()
{
double *a;
double *b;
double *fvec;
bool header;
int i;
int info;
int j;
int job;
double k;
double *t;
double t_delt;
string t_file;
double t_max;
double t_min;
int t_num;
double *u;
string u_file;
double w;
double *x;
double x_delt;
string x_file;
double x_max;
double x_min;
int x_num;
setlocale(LC_ALL, "Russian");
timestamp();
cout << "\n";
cout << "FD1D_HEAT_IMPLICIT\n";
cout << " Язык разработки C++\n";
cout << "\n";
cout << " Конечно-разностное решение\n";
cout << " Зависимое от времени одномерное уравнение теплопроводности\n";
cout << "\n";
cout << " Ut - k * Uxx = F(x,t)\n";
cout << "\n";
cout << " для пространственного интервала А<=X <=B с граничными условиями\n";
cout << "\n";
cout << " U(A,t) = UA(t)\n";
cout << " U(B,t) = UB(t)\n";
cout << "\n";
cout << " и временной интервал T0 <= T <= T1 с начальным условием\n";
cout << "\n";
cout << " U(X,T0) = U0(X).\n";
cout << "\n";
k = 5.0E-07;
//
// Set X values.
//
x_min = 0.0;
x_max = 0.1;
x_num = 2;
x_delt = (x_max - x_min) / (double)(x_num - 1);
x = new double[x_num];
for (i = 0; i < x_num; i++)
{
x[i] = ((double)(x_num - i - 1) * x_min
+ (double)(i)* x_max)
/ (double)(x_num - 1);
}
//
// Set T values.
//
t_min = 0.0;
t_max = 5000.0;
t_num = 20;
t_delt = (t_max - t_min) / (double)(t_num - 1);
t = new double[t_num];
for (j = 0; j < t_num; j++)
{
t[j] = ((double)(t_num - j - 1) * t_min
+ (double)(j)* t_max)
/ (double)(t_num - 1);
}
//
// Set the initial data, for time T_MIN.
//
u = new double[x_num*t_num];
u0(x_min, x_max, t_min, x_num, x, u);
//
//
w = k * t_delt / x_delt / x_delt;
a = new double[3 * x_num];
a[0 + 0 * 3] = 0.0;
a[1 + 0 * 3] = 1.0;
a[0 + 1 * 3] = 0.0;
for (i = 1; i < x_num - 1; i++)
{
a[2 + (i - 1) * 3] = -w;
a[1 + i * 3] = 1.0 + 2.0 * w;
a[0 + (i + 1) * 3] = -w;
}
a[2 + (x_num - 2) * 3] = 0.0;
a[1 + (x_num - 1) * 3] = 1.0;
a[2 + (x_num - 1) * 3] = 0.0;
//
// Factor the matrix.
//
info = r83_np_fa(x_num, a);
b = new double[x_num];
fvec = new double[x_num];
for (j = 1; j < t_num; j++)
{
//
// Set the right hand side B.
//
b[0] = ua(x_min, x_max, t_min, t[j]);
f(x_min, x_max, t_min, t[j - 1], x_num, x, fvec);
for (i = 1; i < x_num - 1; i++)
{
b[i] = u[i + (j - 1)*x_num] + t_delt * fvec[i];
}
b[x_num - 1] = ub(x_min, x_max, t_min, t[j]);
delete[] fvec;
job = 0;
fvec = r83_np_sl(x_num, a, b, job);
for (i = 0; i < x_num; i++)
{
u[i + j*x_num] = fvec[i];
}
}
x_file = "x.txt";
header = false;
dtable_write(x_file, 1, x_num, x, header);
cout << "\n";
cout << " X data written to \"" << x_file << "\".\n";
t_file = "t.txt";
header = false;
dtable_write(t_file, 1, t_num, t, header);
cout << " T data written to \"" << t_file << "\".\n";
u_file = "u.txt";
header = false;
dtable_write(u_file, x_num, t_num, u, header);
cout << " U data written to \"" << u_file << "\".\n";
cout << "\n";
cout << "FD1D_HEAT_IMPLICIT\n";
cout << " Normal end of execution.\n";
cout << "\n";
timestamp();
delete[] a;
delete[] b;
delete[] fvec;
delete[] t;
delete[] u;
delete[] x;
return 0;
}
//****************************************************************************80
void dtable_data_write(ofstream &output, int m, int n, double table[])
{
int i;
int j;
for (j = 0; j < n; j++)
{
for (i = 0; i < m; i++)
{
output << setw(10) << table[i + j*m] << " ";
}
output << "\n";
}
return;
}
//****************************************************************************80
void dtable_write(string output_filename, int m, int n, double table[],
bool header)
{
ofstream output;
output.open(output_filename.c_str());
if (!output)
{
cerr << "\n";
cerr << "DTABLE_WRITE - Fatal error!\n";
cerr << " Could not open the output file.\n";
return;
}
if (header)
{
// dtable_header_write ( output_filename, output, m, n );
}
dtable_data_write(output, m, n, table);
output.close();
return;
}
//****************************************************************************80
void f(double a, double b, double t0, double t, int n, double x[],
double value[])
{
int i;
for (i = 0; i < n; i++)
{
value[i] = 0.0;
}
return;
}
//****************************************************************************80
int r83_np_fa(int n, double a[])
{
int i;
for (i = 1; i <= n - 1; i++)
{
if (a[1 + (i - 1) * 3] == 0.0)
{
cout << "\n";
cout << "R83_NP_FA - Fatal error!\n";
cout << " Zero pivot on step " << i << "\n";
return i;
}
//
// Store the multiplier in L.
//
a[2 + (i - 1) * 3] = a[2 + (i - 1) * 3] / a[1 + (i - 1) * 3];
//
// Modify the diagonal entry in the next column.
//
a[1 + i * 3] = a[1 + i * 3] - a[2 + (i - 1) * 3] * a[0 + i * 3];
}
if (a[1 + (n - 1) * 3] == 0.0)
{
cout << "\n";
cout << "R83_NP_FA - Fatal error!\n";
cout << " Zero pivot on step " << n << "\n";
return n;
}
return 0;
}
//****************************************************************************80
double *r83_np_sl(int n, double a_lu[], double b[], int job)
{
int i;
double *x;
x = new double[n];
for (i = 0; i < n; i++)
{
x[i] = b[i];
}
if (job == 0)
{
//
// Solve L * Y = B.
//
for (i = 1; i < n; i++)
{
x[i] = x[i] - a_lu[2 + (i - 1) * 3] * x[i - 1];
}
//
// Solve U * X = Y.
//
for (i = n; 1 <= i; i--)
{
x[i - 1] = x[i - 1] / a_lu[1 + (i - 1) * 3];
if (1 < i)
{
x[i - 2] = x[i - 2] - a_lu[0 + (i - 1) * 3] * x[i - 1];
}
}
}
else
{
//
// Solve U' * Y = B
//
for (i = 1; i <= n; i++)
{
x[i - 1] = x[i - 1] / a_lu[1 + (i - 1) * 3];
if (i < n)
{
x[i] = x[i] - a_lu[0 + i * 3] * x[i - 1];
}
}
//
// Solve L' * X = Y.
//
for (i = n - 1; 1 <= i; i--)
{
x[i - 1] = x[i - 1] - a_lu[2 + (i - 1) * 3] * x[i];
}
}
return x;
}
//****************************************************************************80
void timestamp()
/
{
# define TIME_SIZE 40
static char time_buffer[TIME_SIZE];
const struct tm *tm;
size_t len;
time_t now;
now = time(NULL);
tm = localtime(&now);
len = strftime(time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm);
cout << time_buffer << "\n";
return;
# undef TIME_SIZE
}
//****************************************************************************80
void u0(double a, double b, double t0, int n, double x[], double value[])
{
int i;
for (i = 0; i < n; i++)
{
value[i] = 100.0;
}
return;
}
//****************************************************************************80
double ua(double a, double b, double t0, double t)
{
double value;
value = 20.0;
return value;
}
double ub(double a, double b, double t0, double t)
{
double value;
value = 20.0;
system("PAUSE");
return value;
}
I2RlZmluZSBfQ1JUX1NFQ1VSRV9OT19XQVJOSU5HUwojIGluY2x1ZGUgPGNzdGRsaWI+CiMgaW5jbHVkZSA8aW9zdHJlYW0+CiMgaW5jbHVkZSA8aW9tYW5pcD4KI2luY2x1ZGUgPHN0cmluZz4KCiMgaW5jbHVkZSA8ZnN0cmVhbT4KIyBpbmNsdWRlIDxjdGltZT4KIyBpbmNsdWRlIDxjbWF0aD4KIAoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmludCBtYWluKCk7CnZvaWQgZHRhYmxlX2RhdGFfd3JpdGUob2ZzdHJlYW0gJm91dHB1dCwgaW50IG0sIGludCBuLCBkb3VibGUgdGFibGVbXSk7CnZvaWQgZHRhYmxlX3dyaXRlKHN0cmluZyBvdXRwdXRfZmlsZW5hbWUsIGludCBtLCBpbnQgbiwgZG91YmxlIHRhYmxlW10sCglib29sIGhlYWRlcik7CnZvaWQgZihkb3VibGUgYSwgZG91YmxlIGIsIGRvdWJsZSB0MCwgZG91YmxlIHQsIGludCBuLCBkb3VibGUgeFtdLAoJZG91YmxlIHZhbHVlW10pOwppbnQgcjgzX25wX2ZhKGludCBuLCBkb3VibGUgYVtdKTsKZG91YmxlICpyODNfbnBfc2woaW50IG4sIGRvdWJsZSBhX2x1W10sIGRvdWJsZSBiW10sIGludCBqb2IpOwp2b2lkIHRpbWVzdGFtcCgpOwp2b2lkIHUwKGRvdWJsZSBhLCBkb3VibGUgYiwgZG91YmxlIHQwLCBpbnQgbiwgZG91YmxlIHhbXSwgZG91YmxlIHZhbHVlW10pOwpkb3VibGUgdWEoZG91YmxlIGEsIGRvdWJsZSBiLCBkb3VibGUgdDAsIGRvdWJsZSB0KTsKZG91YmxlIHViKGRvdWJsZSBhLCBkb3VibGUgYiwgZG91YmxlIHQwLCBkb3VibGUgdCk7CgoKaW50IG1haW4oKQoKCgp7Cglkb3VibGUgKmE7Cglkb3VibGUgKmI7Cglkb3VibGUgKmZ2ZWM7Cglib29sIGhlYWRlcjsKCWludCBpOwoJaW50IGluZm87CglpbnQgajsKCWludCBqb2I7Cglkb3VibGUgazsKCWRvdWJsZSAqdDsKCWRvdWJsZSB0X2RlbHQ7CglzdHJpbmcgdF9maWxlOwoJZG91YmxlIHRfbWF4OwoJZG91YmxlIHRfbWluOwoJaW50IHRfbnVtOwoJZG91YmxlICp1OwoJc3RyaW5nIHVfZmlsZTsKCWRvdWJsZSB3OwoJZG91YmxlICp4OwoJZG91YmxlIHhfZGVsdDsKCXN0cmluZyB4X2ZpbGU7Cglkb3VibGUgeF9tYXg7Cglkb3VibGUgeF9taW47CglpbnQgeF9udW07CglzZXRsb2NhbGUoTENfQUxMLCAiUnVzc2lhbiIpOwoJdGltZXN0YW1wKCk7Cgljb3V0IDw8ICJcbiI7Cgljb3V0IDw8ICJGRDFEX0hFQVRfSU1QTElDSVRcbiI7Cgljb3V0IDw8ICIgINCv0LfRi9C6INGA0LDQt9GA0LDQsdC+0YLQutC4IEMrK1xuIjsKCWNvdXQgPDwgIlxuIjsKCWNvdXQgPDwgIiAg0JrQvtC90LXRh9C90L4t0YDQsNC30L3QvtGB0YLQvdC+0LUg0YDQtdGI0LXQvdC40LVcbiI7Cgljb3V0IDw8ICIgINCX0LDQstC40YHQuNC80L7QtSDQvtGCINCy0YDQtdC80LXQvdC4INC+0LTQvdC+0LzQtdGA0L3QvtC1INGD0YDQsNCy0L3QtdC90LjQtSDRgtC10L/Qu9C+0L/RgNC+0LLQvtC00L3QvtGB0YLQuFxuIjsKCWNvdXQgPDwgIlxuIjsKCWNvdXQgPDwgIiAgICBVdCAtIGsgKiBVeHggPSBGKHgsdClcbiI7Cgljb3V0IDw8ICJcbiI7Cgljb3V0IDw8ICIgINC00LvRjyDQv9GA0L7RgdGC0YDQsNC90YHRgtCy0LXQvdC90L7Qs9C+INC40L3RgtC10YDQstCw0LvQsCDQkDw9WCA8PUIg0YEg0LPRgNCw0L3QuNGH0L3Ri9C80Lgg0YPRgdC70L7QstC40Y/QvNC4XG4iOwoJY291dCA8PCAiXG4iOwoJY291dCA8PCAiICAgIFUoQSx0KSA9IFVBKHQpXG4iOwoJY291dCA8PCAiICAgIFUoQix0KSA9IFVCKHQpXG4iOwoJY291dCA8PCAiXG4iOwoJY291dCA8PCAiICDQuCDQstGA0LXQvNC10L3QvdC+0Lkg0LjQvdGC0LXRgNCy0LDQuyBUMCA8PSBUIDw9IFQxINGBINC90LDRh9Cw0LvRjNC90YvQvCDRg9GB0LvQvtCy0LjQtdC8XG4iOwoJY291dCA8PCAiXG4iOwoJY291dCA8PCAiICAgIFUoWCxUMCkgPSBVMChYKS5cbiI7Cgljb3V0IDw8ICJcbiI7CgoKCWsgPSA1LjBFLTA3OwoJLy8KCS8vICBTZXQgWCB2YWx1ZXMuCgkvLwoJeF9taW4gPSAwLjA7Cgl4X21heCA9IDAuMTsKCXhfbnVtID0gMjsKCXhfZGVsdCA9ICh4X21heCAtIHhfbWluKSAvIChkb3VibGUpKHhfbnVtIC0gMSk7CgoJeCA9IG5ldyBkb3VibGVbeF9udW1dOwoKCWZvciAoaSA9IDA7IGkgPCB4X251bTsgaSsrKQoJewoJCXhbaV0gPSAoKGRvdWJsZSkoeF9udW0gLSBpIC0gMSkgKiB4X21pbgoJCQkrIChkb3VibGUpKGkpKiB4X21heCkKCQkJLyAoZG91YmxlKSh4X251bSAtIDEpOwoJfQoJLy8gCgkvLyAgU2V0IFQgdmFsdWVzLgoJLy8KCXRfbWluID0gMC4wOwoJdF9tYXggPSA1MDAwLjA7Cgl0X251bSA9IDIwOwoJdF9kZWx0ID0gKHRfbWF4IC0gdF9taW4pIC8gKGRvdWJsZSkodF9udW0gLSAxKTsKCgl0ID0gbmV3IGRvdWJsZVt0X251bV07CgoJZm9yIChqID0gMDsgaiA8IHRfbnVtOyBqKyspCgl7CgkJdFtqXSA9ICgoZG91YmxlKSh0X251bSAtIGogLSAxKSAqIHRfbWluCgkJCSsgKGRvdWJsZSkoaikqIHRfbWF4KQoJCQkvIChkb3VibGUpKHRfbnVtIC0gMSk7Cgl9CgkvLwoJLy8gIFNldCB0aGUgaW5pdGlhbCBkYXRhLCBmb3IgdGltZSBUX01JTi4KCS8vCgl1ID0gbmV3IGRvdWJsZVt4X251bSp0X251bV07CgoJdTAoeF9taW4sIHhfbWF4LCB0X21pbiwgeF9udW0sIHgsIHUpOwoJLy8KCgkvLwoJdyA9IGsgKiB0X2RlbHQgLyB4X2RlbHQgLyB4X2RlbHQ7CgoJYSA9IG5ldyBkb3VibGVbMyAqIHhfbnVtXTsKCglhWzAgKyAwICogM10gPSAwLjA7CgoJYVsxICsgMCAqIDNdID0gMS4wOwoJYVswICsgMSAqIDNdID0gMC4wOwoKCWZvciAoaSA9IDE7IGkgPCB4X251bSAtIDE7IGkrKykKCXsKCQlhWzIgKyAoaSAtIDEpICogM10gPSAtdzsKCQlhWzEgKyBpICogM10gPSAxLjAgKyAyLjAgKiB3OwoJCWFbMCArIChpICsgMSkgKiAzXSA9IC13OwoJfQoKCWFbMiArICh4X251bSAtIDIpICogM10gPSAwLjA7CglhWzEgKyAoeF9udW0gLSAxKSAqIDNdID0gMS4wOwoKCWFbMiArICh4X251bSAtIDEpICogM10gPSAwLjA7CgkvLwoJLy8gIEZhY3RvciB0aGUgbWF0cml4LgoJLy8KCWluZm8gPSByODNfbnBfZmEoeF9udW0sIGEpOwoKCWIgPSBuZXcgZG91YmxlW3hfbnVtXTsKCWZ2ZWMgPSBuZXcgZG91YmxlW3hfbnVtXTsKCglmb3IgKGogPSAxOyBqIDwgdF9udW07IGorKykKCXsKCQkvLwoJCS8vICBTZXQgdGhlIHJpZ2h0IGhhbmQgc2lkZSBCLgoJCS8vCgkJYlswXSA9IHVhKHhfbWluLCB4X21heCwgdF9taW4sIHRbal0pOwoKCQlmKHhfbWluLCB4X21heCwgdF9taW4sIHRbaiAtIDFdLCB4X251bSwgeCwgZnZlYyk7CgoJCWZvciAoaSA9IDE7IGkgPCB4X251bSAtIDE7IGkrKykKCQl7CgkJCWJbaV0gPSB1W2kgKyAoaiAtIDEpKnhfbnVtXSArIHRfZGVsdCAqIGZ2ZWNbaV07CgkJfQoKCQliW3hfbnVtIC0gMV0gPSB1Yih4X21pbiwgeF9tYXgsIHRfbWluLCB0W2pdKTsKCgkJZGVsZXRlW10gZnZlYzsKCgkJam9iID0gMDsKCQlmdmVjID0gcjgzX25wX3NsKHhfbnVtLCBhLCBiLCBqb2IpOwoKCQlmb3IgKGkgPSAwOyBpIDwgeF9udW07IGkrKykKCQl7CgkJCXVbaSArIGoqeF9udW1dID0gZnZlY1tpXTsKCQl9Cgl9CgoJeF9maWxlID0gIngudHh0IjsKCWhlYWRlciA9IGZhbHNlOwoJZHRhYmxlX3dyaXRlKHhfZmlsZSwgMSwgeF9udW0sIHgsIGhlYWRlcik7CgoJY291dCA8PCAiXG4iOwoJY291dCA8PCAiICBYIGRhdGEgd3JpdHRlbiB0byBcIiIgPDwgeF9maWxlIDw8ICJcIi5cbiI7CgoJdF9maWxlID0gInQudHh0IjsKCWhlYWRlciA9IGZhbHNlOwoJZHRhYmxlX3dyaXRlKHRfZmlsZSwgMSwgdF9udW0sIHQsIGhlYWRlcik7CgoJY291dCA8PCAiICBUIGRhdGEgd3JpdHRlbiB0byBcIiIgPDwgdF9maWxlIDw8ICJcIi5cbiI7CgoJdV9maWxlID0gInUudHh0IjsKCWhlYWRlciA9IGZhbHNlOwoJZHRhYmxlX3dyaXRlKHVfZmlsZSwgeF9udW0sIHRfbnVtLCB1LCBoZWFkZXIpOwoKCWNvdXQgPDwgIiAgVSBkYXRhIHdyaXR0ZW4gdG8gXCIiIDw8IHVfZmlsZSA8PCAiXCIuXG4iOwoKCWNvdXQgPDwgIlxuIjsKCWNvdXQgPDwgIkZEMURfSEVBVF9JTVBMSUNJVFxuIjsKCWNvdXQgPDwgIiAgTm9ybWFsIGVuZCBvZiBleGVjdXRpb24uXG4iOwoJY291dCA8PCAiXG4iOwoJdGltZXN0YW1wKCk7CgoJZGVsZXRlW10gYTsKCWRlbGV0ZVtdIGI7CglkZWxldGVbXSBmdmVjOwoJZGVsZXRlW10gdDsKCWRlbGV0ZVtdIHU7CglkZWxldGVbXSB4OwoKCXJldHVybiAwOwp9Ci8vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKjgwCgp2b2lkIGR0YWJsZV9kYXRhX3dyaXRlKG9mc3RyZWFtICZvdXRwdXQsIGludCBtLCBpbnQgbiwgZG91YmxlIHRhYmxlW10pCgoKewoJaW50IGk7CglpbnQgajsKCglmb3IgKGogPSAwOyBqIDwgbjsgaisrKQoJewoJCWZvciAoaSA9IDA7IGkgPCBtOyBpKyspCgkJewoJCQlvdXRwdXQgPDwgc2V0dygxMCkgPDwgdGFibGVbaSArIGoqbV0gPDwgIiAgIjsKCQl9CgkJb3V0cHV0IDw8ICJcbiI7Cgl9CgoJcmV0dXJuOwp9Ci8vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKjgwCgp2b2lkIGR0YWJsZV93cml0ZShzdHJpbmcgb3V0cHV0X2ZpbGVuYW1lLCBpbnQgbSwgaW50IG4sIGRvdWJsZSB0YWJsZVtdLAoJYm9vbCBoZWFkZXIpCgoJCnsKCW9mc3RyZWFtIG91dHB1dDsKCglvdXRwdXQub3BlbihvdXRwdXRfZmlsZW5hbWUuY19zdHIoKSk7CgoJaWYgKCFvdXRwdXQpCgl7CgkJY2VyciA8PCAiXG4iOwoJCWNlcnIgPDwgIkRUQUJMRV9XUklURSAtIEZhdGFsIGVycm9yIVxuIjsKCQljZXJyIDw8ICIgIENvdWxkIG5vdCBvcGVuIHRoZSBvdXRwdXQgZmlsZS5cbiI7CgkJcmV0dXJuOwoJfQoKCWlmIChoZWFkZXIpCgl7CgkJLy8gIGR0YWJsZV9oZWFkZXJfd3JpdGUgKCBvdXRwdXRfZmlsZW5hbWUsIG91dHB1dCwgbSwgbiApOwoJfQoKCWR0YWJsZV9kYXRhX3dyaXRlKG91dHB1dCwgbSwgbiwgdGFibGUpOwoKCW91dHB1dC5jbG9zZSgpOwoKCXJldHVybjsKfQovLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio4MAoKdm9pZCBmKGRvdWJsZSBhLCBkb3VibGUgYiwgZG91YmxlIHQwLCBkb3VibGUgdCwgaW50IG4sIGRvdWJsZSB4W10sCglkb3VibGUgdmFsdWVbXSkKCnsKCWludCBpOwoKCWZvciAoaSA9IDA7IGkgPCBuOyBpKyspCgl7CgkJdmFsdWVbaV0gPSAwLjA7Cgl9CglyZXR1cm47Cn0KLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqODAKCmludCByODNfbnBfZmEoaW50IG4sIGRvdWJsZSBhW10pCgoKewoJaW50IGk7CgoJZm9yIChpID0gMTsgaSA8PSBuIC0gMTsgaSsrKQoJewoJCWlmIChhWzEgKyAoaSAtIDEpICogM10gPT0gMC4wKQoJCXsKCQkJY291dCA8PCAiXG4iOwoJCQljb3V0IDw8ICJSODNfTlBfRkEgLSBGYXRhbCBlcnJvciFcbiI7CgkJCWNvdXQgPDwgIiAgWmVybyBwaXZvdCBvbiBzdGVwICIgPDwgaSA8PCAiXG4iOwoJCQlyZXR1cm4gaTsKCQl9CgkJLy8KCQkvLyAgU3RvcmUgdGhlIG11bHRpcGxpZXIgaW4gTC4KCQkvLwoJCWFbMiArIChpIC0gMSkgKiAzXSA9IGFbMiArIChpIC0gMSkgKiAzXSAvIGFbMSArIChpIC0gMSkgKiAzXTsKCQkvLwoJCS8vICBNb2RpZnkgdGhlIGRpYWdvbmFsIGVudHJ5IGluIHRoZSBuZXh0IGNvbHVtbi4KCQkvLwoJCWFbMSArIGkgKiAzXSA9IGFbMSArIGkgKiAzXSAtIGFbMiArIChpIC0gMSkgKiAzXSAqIGFbMCArIGkgKiAzXTsKCX0KCglpZiAoYVsxICsgKG4gLSAxKSAqIDNdID09IDAuMCkKCXsKCQljb3V0IDw8ICJcbiI7CgkJY291dCA8PCAiUjgzX05QX0ZBIC0gRmF0YWwgZXJyb3IhXG4iOwoJCWNvdXQgPDwgIiAgWmVybyBwaXZvdCBvbiBzdGVwICIgPDwgbiA8PCAiXG4iOwoJCXJldHVybiBuOwoJfQoKCXJldHVybiAwOwp9Ci8vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKjgwCgpkb3VibGUgKnI4M19ucF9zbChpbnQgbiwgZG91YmxlIGFfbHVbXSwgZG91YmxlIGJbXSwgaW50IGpvYikKCgp7CglpbnQgaTsKCWRvdWJsZSAqeDsKCgl4ID0gbmV3IGRvdWJsZVtuXTsKCglmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQoJewoJCXhbaV0gPSBiW2ldOwoJfQoKCWlmIChqb2IgPT0gMCkKCXsKCQkvLwoJCS8vICBTb2x2ZSBMICogWSA9IEIuCgkJLy8KCQlmb3IgKGkgPSAxOyBpIDwgbjsgaSsrKQoJCXsKCQkJeFtpXSA9IHhbaV0gLSBhX2x1WzIgKyAoaSAtIDEpICogM10gKiB4W2kgLSAxXTsKCQl9CgkJLy8KCQkvLyAgU29sdmUgVSAqIFggPSBZLgoJCS8vCgkJZm9yIChpID0gbjsgMSA8PSBpOyBpLS0pCgkJewoJCQl4W2kgLSAxXSA9IHhbaSAtIDFdIC8gYV9sdVsxICsgKGkgLSAxKSAqIDNdOwoJCQlpZiAoMSA8IGkpCgkJCXsKCQkJCXhbaSAtIDJdID0geFtpIC0gMl0gLSBhX2x1WzAgKyAoaSAtIDEpICogM10gKiB4W2kgLSAxXTsKCQkJfQoJCX0KCX0KCWVsc2UKCXsKCQkvLwoJCS8vICBTb2x2ZSBVJyAqIFkgPSBCCgkJLy8KCQlmb3IgKGkgPSAxOyBpIDw9IG47IGkrKykKCQl7CgkJCXhbaSAtIDFdID0geFtpIC0gMV0gLyBhX2x1WzEgKyAoaSAtIDEpICogM107CgkJCWlmIChpIDwgbikKCQkJewoJCQkJeFtpXSA9IHhbaV0gLSBhX2x1WzAgKyBpICogM10gKiB4W2kgLSAxXTsKCQkJfQoJCX0KCQkvLwoJCS8vICBTb2x2ZSBMJyAqIFggPSBZLgoJCS8vCgkJZm9yIChpID0gbiAtIDE7IDEgPD0gaTsgaS0tKQoJCXsKCQkJeFtpIC0gMV0gPSB4W2kgLSAxXSAtIGFfbHVbMiArIChpIC0gMSkgKiAzXSAqIHhbaV07CgkJfQoJfQoKCXJldHVybiB4Owp9Ci8vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKjgwCgp2b2lkIHRpbWVzdGFtcCgpCgovCnsKIyBkZWZpbmUgVElNRV9TSVpFIDQwCgoJc3RhdGljIGNoYXIgdGltZV9idWZmZXJbVElNRV9TSVpFXTsKCWNvbnN0IHN0cnVjdCB0bSAqdG07CglzaXplX3QgbGVuOwoJdGltZV90IG5vdzsKCglub3cgPSB0aW1lKE5VTEwpOwoJdG0gPSBsb2NhbHRpbWUoJm5vdyk7CgoJbGVuID0gc3RyZnRpbWUodGltZV9idWZmZXIsIFRJTUVfU0laRSwgIiVkICVCICVZICVJOiVNOiVTICVwIiwgdG0pOwoKCWNvdXQgPDwgdGltZV9idWZmZXIgPDwgIlxuIjsKCglyZXR1cm47CiMgdW5kZWYgVElNRV9TSVpFCn0KLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqODAKCnZvaWQgdTAoZG91YmxlIGEsIGRvdWJsZSBiLCBkb3VibGUgdDAsIGludCBuLCBkb3VibGUgeFtdLCBkb3VibGUgdmFsdWVbXSkKCgp7CglpbnQgaTsKCglmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQoJewoJCXZhbHVlW2ldID0gMTAwLjA7Cgl9CglyZXR1cm47Cn0KLy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqODAKCmRvdWJsZSB1YShkb3VibGUgYSwgZG91YmxlIGIsIGRvdWJsZSB0MCwgZG91YmxlIHQpCgoKewoJZG91YmxlIHZhbHVlOwoKCXZhbHVlID0gMjAuMDsKCglyZXR1cm4gdmFsdWU7Cn0KCgpkb3VibGUgdWIoZG91YmxlIGEsIGRvdWJsZSBiLCBkb3VibGUgdDAsIGRvdWJsZSB0KQoKewoJZG91YmxlIHZhbHVlOwoKCXZhbHVlID0gMjAuMDsKCXN5c3RlbSgiUEFVU0UiKTsKCXJldHVybiB2YWx1ZTsKCQoKCQoJCn0=