//#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define FILE_SAMPLE "sample.txt" // データファイル
#define FILE_TEST "test.txt" // データファイル
#define DAT_N (500) // 1行のデータ個数
// データ
typedef struct
{
double a_data[ DAT_N] ; // a[]
char a_fname[ _MAX_PATH] ;
int b_lines;
char ** b_fname;
double ** b_data; // b[][]
double c_data[ DAT_N] ; // c[]
} ALL_DATA;
// Error コード
enum ERR_CODE
{
EDR_Normal = 0 , // 正常終了
EDR_FileOpen , // ファイルが開けない
EDR_FewData , // データが足りない
EDR_MemAlloc , // メモリ確保失敗
EDR_Zero , // 要素が全てゼロ
} ;
char * getStrERR_CODE( int code)
{
switch ( code)
{
case EDR_Normal : return "正常終了" ;
case EDR_FileOpen : return "ファイルが開けない" ;
case EDR_FewData : return "データが足りない" ;
case EDR_MemAlloc : return "メモリ確保失敗" ;
case EDR_Zero : return "要素が全てゼロ" ;
}
return "" ;
}
void aldat_init( ALL_DATA * d) ; // ALL_DATA初期化
ERR_CODE aldat_alloc( ALL_DATA * d, int lines) ; // ALL_DATA確保
void aldat_free( ALL_DATA * d) ; // ALL_DATA解放
ERR_CODE data_read( char * file1, char * file2, ALL_DATA * d) ; // データ読み込み
char * f2s_n( double d, int n) ; // 有効数字n桁小数文字列生成
#ifdef _DEBUG
#define debug_out(x) debug_file_out(x)
void debug_file_out( ALL_DATA * d) ;
#else
#define debug_out(x)
#endif
//---------------------------------------------------------------------------
// ALL_DATA初期化
//---------------------------------------------------------------------------
void aldat_init( ALL_DATA * d)
{
if ( NULL == d)
{
return ;
}
memset ( d
, 0x00 , sizeof ( ALL_DATA
) ) ; }
//---------------------------------------------------------------------------
// ALL_DATA確保
// 戻り値が EDR_Normal 以外の時は、当関数でfreeしているので呼び元でfreeしなくて良い
//---------------------------------------------------------------------------
ERR_CODE aldat_alloc( ALL_DATA * d, int lines)
{
ERR_CODE r = EDR_Normal;
int i;
// b の行数
d-> b_lines = lines;
// b
if ( NULL
== ( d
-> b_data
= ( double ** ) malloc ( sizeof ( double * ) * lines
) ) ) {
r = EDR_MemAlloc;
goto END_aldat_alloc;
}
memset ( d
-> b_data
, 0x00 , sizeof ( double * ) * lines
) ; // b[]
if ( NULL
== ( d
-> b_fname
= ( char ** ) malloc ( sizeof ( char * ) * lines
) ) ) {
r = EDR_MemAlloc;
goto END_aldat_alloc;
}
memset ( d
-> b_data
, 0x00 , sizeof ( char * ) * lines
) ; // b[][] と b[]のfilename
for ( i= 0 ; i< lines; i++ )
{
if ( NULL
== ( d
-> b_data
[ i
] = ( double * ) malloc ( sizeof ( double ) * DAT_N
) ) ) {
r = EDR_MemAlloc;
goto END_aldat_alloc;
}
if ( NULL
== ( d
-> b_fname
[ i
] = ( char * ) malloc ( sizeof ( char ) * _MAX_PATH
) ) ) {
r = EDR_MemAlloc;
goto END_aldat_alloc;
}
}
r = EDR_Normal;
END_aldat_alloc:;
if ( EDR_Normal != r)
{
aldat_free( d) ;
}
return r;
}
//---------------------------------------------------------------------------
// ALL_DATA解放
//---------------------------------------------------------------------------
void aldat_free( ALL_DATA * d)
{
int i;
if ( NULL == d)
{
return ;
}
for ( i= 0 ; i < d-> b_lines; i++ )
{
if ( NULL == d-> b_data[ i] && NULL == d-> b_fname[ i] )
{
break ;
}
if ( d-> b_data[ i] )
{
}
if ( d-> b_fname[ i] )
{
}
}
aldat_init( d) ;
}
//---------------------------------------------------------------------------
// 関数 = データ読み込み
// 引数 = file1 : データファイル名 (sample.txt)
// file2 : データファイル名 (test.txt)
// d : データ
// 戻り値 = enum ERR_CODE;
// 注意 = ・dは呼び元で用意すること
// ・メモリ初期化/確保とエラー時の解放はは当関数でするが、
// 使用後の解放は呼び元ですること
//---------------------------------------------------------------------------
ERR_CODE data_read( char * file1, char * file2, ALL_DATA * d)
{
ERR_CODE res = EDR_Normal; // 戻り値
FILE * fp = NULL; // ファイル
char * buf = NULL; // 1行読み込みバッファ
int buf_size; // 〃 サイズ
int i, j, line; // 汎用
char * token; // 汎用
// 初期化
aldat_init( d) ;
// buf のサイズ (大きい方のファイルのサイズ)
if ( NULL
== ( fp
= fopen ( file1
, "rb" ) ) ) {
res = EDR_FileOpen;
goto END_DATAREAD;
}
if ( NULL
== ( fp
= fopen ( file2
, "rb" ) ) ) {
res = EDR_FileOpen;
goto END_DATAREAD;
}
fp = NULL;
buf_size = ( j > i) ? j : i;
// buff 確保
if ( NULL
== ( buf
= ( char * ) malloc ( buf_size
) ) ) {
res = EDR_MemAlloc;
goto END_DATAREAD;
}
// test.txt を空読みしてデータ数(行数)を数える
for ( line
= 0 ; NULL
!= fgets ( buf
, buf_size
, fp
) ; line
++ ) ; if ( line < 1 )
{
res = EDR_FewData;
goto END_DATAREAD;
}
fp = NULL;
// データ領域確保
if ( EDR_Normal != ( res = aldat_alloc( d, line) ) )
{
goto END_DATAREAD;
}
// sample.txt
fgets ( buf
, buf_size
, fp
) ; // filename
if ( NULL
== ( token
= strtok ( buf
, "\t " ) ) ) {
res = EDR_FewData;
goto END_DATAREAD;
}
strncpy ( d
-> a_fname
, token
, _MAX_PATH
) ; // data
for ( j = 0 ; j < DAT_N; j++ ) {
if ( NULL == token) {
res = EDR_FewData;
goto END_DATAREAD;
}
d
-> a_data
[ j
] = atof ( token
) ; }
fp = NULL;
// test.txt
for ( i = 0 ; i < d-> b_lines; i++ )
{
fgets ( buf
, buf_size
, fp
) ; // filename
if ( NULL
== ( token
= strtok ( buf
, "\t " ) ) ) {
res = EDR_FewData;
goto END_DATAREAD;
}
strncpy ( d
-> b_fname
[ i
] , token
, _MAX_PATH
) ; // data
for ( j = 0 ; j < DAT_N; j++ ) {
if ( NULL == token) {
res = EDR_FewData;
goto END_DATAREAD;
}
d
-> b_data
[ i
] [ j
] = atof ( token
) ; }
}
fp = NULL;
res = EDR_Normal;
END_DATAREAD:;
if ( res != EDR_Normal)
{
aldat_free( d) ;
}
if ( buf)
{
buf = NULL;
}
buf_size = 0 ;
if ( fp)
{
fp = NULL;
}
return res;
}
//---------------------------------------------------------------------------
// 関数 = 有効数字n桁小数文字列生成
// 動作 = 例えば n == 6 のとき、
// 0.0 → "0"
// 0.123456789 → "0.123457"
// 0.000123456789 → "0.000123457"
// 0.0120000 → "0.012"
// を返す
// メモ = ・n < 16
// ・未完成
//---------------------------------------------------------------------------
char * f2s_n( double d, int n)
{
static char b[ 32 ] ;
if ( d == 0.0 )
{
return "0" ;
}
return & b[ 0 ] ;
}
//---------------------------------------------------------------------------
// データ出力 (debug)
//---------------------------------------------------------------------------
#ifdef _DEBUG
void debug_file_out( ALL_DATA * d)
{
int i, j;
FILE * fp;
fp
= fopen ( "dbg_s.txt" , "w" ) ; for ( j = 0 ; j < DAT_N; j++ )
{
fprintf ( fp
, "%s\t " , f2s_n
( d
-> a_data
[ j
] , 6 ) ) ; }
fp
= fopen ( "dbg_t.txt" , "w" ) ; for ( i = 0 ; i < d-> b_lines; i++ )
{
fprintf ( fp
, "%s\t " , d
-> b_fname
[ i
] ) ; for ( j = 0 ; j < DAT_N; j++ )
{
fprintf ( fp
, "%s\t " , f2s_n
( d
-> b_data
[ i
] [ j
] , 6 ) ) ; }
}
}
#endif
//---------------------------------------------------------------------------
// main
//---------------------------------------------------------------------------
int main( )
{
int result = 0 ;
ALL_DATA data;
ERR_CODE res;
int i, j;
double v1, v2, v3;
// 初期化
aldat_init( & data) ;
// read
if ( EDR_Normal != ( res = data_read( FILE_SAMPLE, FILE_TEST, & data) ) )
{
result = ( int ) res;
goto END_MAIN;
}
// (debugモード時) 読んだデータを確認のためファイル dbg_s.txt, dbg_t.txt に書き出す
debug_out( & data) ;
// 計算
for ( i= 0 ; i < data.b_lines ; i++ )
{
v1 = v2 = v3 = 0.0 ;
for ( j= 0 ; j< DAT_N; j++ )
{
v1 += data.a_data [ j] * data.b_data [ i] [ j] ;
v2 += data.a_data [ j] * data.a_data [ j] ;
v3 += data.b_data [ i] [ j] * data.b_data [ i] [ j] ;
}
if ( v2 == 0.0 || v3 == 0.0 )
{
result = EDR_Zero;
goto END_MAIN;
}
data.
c_data [ i
] = v1
/ ( sqrt ( v2
) * sqrt ( v3
) ) ; }
// 結果
for ( i= 0 ; i < data.b_lines ; i++ )
{
printf ( "%s\t %s\n " , data.
b_fname [ i
] , f2s_n
( data.
c_data [ i
] , 15 ) ) ; }
// end
result = ( int ) EDR_Normal;
END_MAIN:;
aldat_free( & data) ;
if ( EDR_Normal != result)
{
fprintf ( stderr
, "%s\n " , getStrERR_CODE
( result
) ) ; }
return result;
}
Ly8jaW5jbHVkZSAic3RkYWZ4LmgiCiNpbmNsdWRlPHN0ZGlvLmg+CiNpbmNsdWRlPHN0ZGxpYi5oPgojaW5jbHVkZTxzdHJpbmcuaD4KI2luY2x1ZGU8bWF0aC5oPgoKI2RlZmluZSBGSUxFX1NBTVBMRSAic2FtcGxlLnR4dCIgICAgLy8g44OH44O844K/44OV44Kh44Kk44OrCiNkZWZpbmUgRklMRV9URVNUICAgInRlc3QudHh0IiAgICAgIC8vIOODh+ODvOOCv+ODleOCoeOCpOODqwojZGVmaW5lIERBVF9OICg1MDApICAgICAgICAgICAgICAgICAvLyAx6KGM44Gu44OH44O844K/5YCL5pWwCgovLyDjg4fjg7zjgr8KdHlwZWRlZiBzdHJ1Y3QKewogICAgZG91YmxlICAgICAgYV9kYXRhW0RBVF9OXTsgIC8vIGFbXQogICAgY2hhciAgICAgICAgYV9mbmFtZVtfTUFYX1BBVEhdOwogICAgaW50ICAgICAgICAgYl9saW5lczsKICAgIGNoYXIgKiogICAgIGJfZm5hbWU7CiAgICBkb3VibGUgKiogICBiX2RhdGE7ICAgICAgICAgLy8gYltdW10KICAgIGRvdWJsZSAgICAgIGNfZGF0YVtEQVRfTl07ICAvLyBjW10KfSBBTExfREFUQTsKCi8vIEVycm9yIOOCs+ODvOODiQplbnVtIEVSUl9DT0RFCnsKICAgIEVEUl9Ob3JtYWwgPSAwICAsIC8vIOato+W4uOe1guS6hgogICAgRURSX0ZpbGVPcGVuICAgICwgLy8g44OV44Kh44Kk44Or44GM6ZaL44GR44Gq44GECiAgICBFRFJfRmV3RGF0YSAgICAgLCAvLyDjg4fjg7zjgr/jgYzotrPjgorjgarjgYQKICAgIEVEUl9NZW1BbGxvYyAgICAsIC8vIOODoeODouODqueiuuS/neWkseaVlwogICAgRURSX1plcm8gICAgICAgICwgLy8g6KaB57Sg44GM5YWo44Gm44K844OtCn07CmNoYXIgKmdldFN0ckVSUl9DT0RFKGludCBjb2RlKQp7CiAgICBzd2l0Y2goY29kZSkKICAgIHsKICAgIGNhc2UgRURSX05vcm1hbCAgICAgIDpyZXR1cm4gIuato+W4uOe1guS6hiI7CiAgICBjYXNlIEVEUl9GaWxlT3BlbiAgICA6cmV0dXJuICLjg5XjgqHjgqTjg6vjgYzplovjgZHjgarjgYQiOwogICAgY2FzZSBFRFJfRmV3RGF0YSAgICAgOnJldHVybiAi44OH44O844K/44GM6Laz44KK44Gq44GEIjsKICAgIGNhc2UgRURSX01lbUFsbG9jICAgIDpyZXR1cm4gIuODoeODouODqueiuuS/neWkseaVlyI7CiAgICBjYXNlIEVEUl9aZXJvICAgICAgICA6cmV0dXJuICLopoHntKDjgYzlhajjgabjgrzjg60iOwogICAgfQogICAgcmV0dXJuICIiOwp9Cgp2b2lkICAgICAgICBhbGRhdF9pbml0KEFMTF9EQVRBICpkKTsgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFMTF9EQVRB5Yid5pyf5YyWCkVSUl9DT0RFICAgIGFsZGF0X2FsbG9jKEFMTF9EQVRBICpkLCBpbnQgbGluZXMpOyAgICAgICAgICAgICAgLy8gQUxMX0RBVEHnorrkv50Kdm9pZCAgICAgICAgYWxkYXRfZnJlZShBTExfREFUQSAqZCk7ICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBTExfREFUQeino+aUvgpFUlJfQ09ERSAgICBkYXRhX3JlYWQoY2hhciAqZmlsZTEsIGNoYXIgKmZpbGUyLCBBTExfREFUQSAqZCk7IC8vIOODh+ODvOOCv+iqreOBv+i+vOOBvwpjaGFyICogICAgICBmMnNfbihkb3VibGUgZCwgaW50IG4pOyAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIOacieWKueaVsOWtl27moYHlsI/mlbDmloflrZfliJfnlJ/miJAKCiNpZmRlZiBfREVCVUcKICAjZGVmaW5lIGRlYnVnX291dCh4KSBkZWJ1Z19maWxlX291dCh4KQogIHZvaWQgZGVidWdfZmlsZV9vdXQoQUxMX0RBVEEgKmQpOwojZWxzZQogICNkZWZpbmUgZGVidWdfb3V0KHgpCiNlbmRpZgoKLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gQUxMX0RBVEHliJ3mnJ/ljJYKLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0Kdm9pZCBhbGRhdF9pbml0KEFMTF9EQVRBICpkKQp7CiAgICBpZihOVUxMID09IGQpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQogICAgbWVtc2V0KGQsIDB4MDAsIHNpemVvZihBTExfREFUQSkpOwp9CgovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLyBBTExfREFUQeeiuuS/nQovLyDmiLvjgorlgKTjgYwgRURSX05vcm1hbCDku6XlpJbjga7mmYLjga/jgIHlvZPplqLmlbDjgadmcmVl44GX44Gm44GE44KL44Gu44Gn5ZG844Gz5YWD44GnZnJlZeOBl+OBquOBj+OBpuiJr+OBhAovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpFUlJfQ09ERSBhbGRhdF9hbGxvYyhBTExfREFUQSAqZCwgaW50IGxpbmVzKQp7CiAgICBFUlJfQ09ERSAgciA9IEVEUl9Ob3JtYWw7CiAgICBpbnQgaTsKCiAgICAvLyBiIOOBruihjOaVsAogICAgZC0+Yl9saW5lcyA9IGxpbmVzOwogICAgLy8gYgogICAgaWYoTlVMTCA9PSAoZC0+Yl9kYXRhID0gKGRvdWJsZSAqKiltYWxsb2Moc2l6ZW9mKGRvdWJsZSAqKSAqIGxpbmVzKSkpCiAgICB7CiAgICAgICAgciA9IEVEUl9NZW1BbGxvYzsKICAgICAgICBnb3RvIEVORF9hbGRhdF9hbGxvYzsKICAgIH0KICAgIG1lbXNldChkLT5iX2RhdGEsIDB4MDAsIHNpemVvZihkb3VibGUgKikgKiBsaW5lcyk7CiAgICAvLyBiW10KICAgIGlmKE5VTEwgPT0gKGQtPmJfZm5hbWUgPSAoY2hhciAqKiltYWxsb2Moc2l6ZW9mKGNoYXIgKikgKiBsaW5lcykpKQogICAgewogICAgICAgIHIgPSBFRFJfTWVtQWxsb2M7CiAgICAgICAgZ290byBFTkRfYWxkYXRfYWxsb2M7CiAgICB9CiAgICBtZW1zZXQoZC0+Yl9kYXRhLCAweDAwLCBzaXplb2YoY2hhciAqKSAqIGxpbmVzKTsKICAgIC8vIGJbXVtdIOOBqCBiW13jga5maWxlbmFtZQogICAgZm9yKGk9MDsgaTxsaW5lczsgaSsrKQogICAgewogICAgICAgIGlmKE5VTEwgPT0gKGQtPmJfZGF0YVtpXSA9IChkb3VibGUgKiltYWxsb2Moc2l6ZW9mKGRvdWJsZSkgKiBEQVRfTikpKQogICAgICAgIHsKICAgICAgICAgICAgciA9IEVEUl9NZW1BbGxvYzsKICAgICAgICAgICAgZ290byBFTkRfYWxkYXRfYWxsb2M7CiAgICAgICAgfQogICAgICAgIGlmKE5VTEwgPT0gKGQtPmJfZm5hbWVbaV0gPSAoY2hhciAqKW1hbGxvYyhzaXplb2YoY2hhcikgKiBfTUFYX1BBVEgpKSkKICAgICAgICB7CiAgICAgICAgICAgIHIgPSBFRFJfTWVtQWxsb2M7CiAgICAgICAgICAgIGdvdG8gRU5EX2FsZGF0X2FsbG9jOwogICAgICAgIH0KICAgIH0KCiAgICByID0gRURSX05vcm1hbDsKRU5EX2FsZGF0X2FsbG9jOjsKICAgIGlmKEVEUl9Ob3JtYWwgIT0gcikKICAgIHsKICAgICAgICBhbGRhdF9mcmVlKGQpOwogICAgfQogICAgcmV0dXJuIHI7Cn0KCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIEFMTF9EQVRB6Kej5pS+Ci8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnZvaWQgYWxkYXRfZnJlZShBTExfREFUQSAqZCkKewogICAgaW50IGk7CgogICAgaWYoTlVMTCA9PSBkKQogICAgewogICAgICAgIHJldHVybjsKICAgIH0KICAgIGZvcihpPTA7IGkgPCBkLT5iX2xpbmVzOyBpKyspCiAgICB7CiAgICAgICAgaWYoTlVMTCA9PSBkLT5iX2RhdGFbaV0gJiYgTlVMTCA9PSBkLT5iX2ZuYW1lW2ldKQogICAgICAgIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmKGQtPmJfZGF0YVtpXSkKICAgICAgICB7CiAgICAgICAgICAgIGZyZWUoZC0+Yl9kYXRhW2ldKTsKICAgICAgICB9CiAgICAgICAgaWYoZC0+Yl9mbmFtZVtpXSkKICAgICAgICB7CiAgICAgICAgICAgIGZyZWUoZC0+Yl9mbmFtZVtpXSk7CiAgICAgICAgfQogICAgfQogICAgZnJlZShkLT5iX2RhdGEpOwogICAgZnJlZShkLT5iX2ZuYW1lKTsKICAgIGFsZGF0X2luaXQoZCk7Cn0KCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIOmWouaVsCAgICAgPSDjg4fjg7zjgr/oqq3jgb/ovrzjgb8KLy8g5byV5pWwICAgICA9IGZpbGUxICA6IOODh+ODvOOCv+ODleOCoeOCpOODq+WQjSAoc2FtcGxlLnR4dCkKLy8gICAgICAgICAgICBmaWxlMiAgOiDjg4fjg7zjgr/jg5XjgqHjgqTjg6vlkI0gKHRlc3QudHh0KQovLyAgICAgICAgICAgIGQgICAgICA6IOODh+ODvOOCvwovLyDmiLvjgorlgKQgICA9IGVudW0gRVJSX0NPREU7Ci8vIOazqOaEjyAgICAgPSDjg7tk44Gv5ZG844Gz5YWD44Gn55So5oSP44GZ44KL44GT44GoCi8vICAgICAgICAgICAg44O744Oh44Oi44Oq5Yid5pyf5YyWL+eiuuS/neOBqOOCqOODqeODvOaZguOBruino+aUvuOBr+OBr+W9k+mWouaVsOOBp+OBmeOCi+OBjOOAgQovLyAgICAgICAgICAgICAg5L2/55So5b6M44Gu6Kej5pS+44Gv5ZG844Gz5YWD44Gn44GZ44KL44GT44GoCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCkVSUl9DT0RFIGRhdGFfcmVhZChjaGFyICpmaWxlMSwgY2hhciAqZmlsZTIsIEFMTF9EQVRBICpkKQp7CiAgICBFUlJfQ09ERSByZXMgPSBFRFJfTm9ybWFsOyAvLyDmiLvjgorlgKQKICAgIEZJTEUgKmZwID0gTlVMTDsgICAgICAgIC8vIOODleOCoeOCpOODqwogICAgY2hhciAqYnVmID0gTlVMTDsgICAgICAgLy8gMeihjOiqreOBv+i+vOOBv+ODkOODg+ODleOCoQogICAgaW50IGJ1Zl9zaXplOyAgICAgICAgICAgLy8gICDjgIMgIOOCteOCpOOCugogICAgaW50IGksIGosIGxpbmU7ICAgICAgICAgLy8g5rGO55SoCiAgICBjaGFyICp0b2tlbjsgICAgICAgICAgICAvLyDmsY7nlKgKCiAgICAvLyDliJ3mnJ/ljJYKICAgIGFsZGF0X2luaXQoZCk7CgogICAgLy8gYnVmIOOBruOCteOCpOOCuiAo5aSn44GN44GE5pa544Gu44OV44Kh44Kk44Or44Gu44K144Kk44K6KQogICAgaWYgKE5VTEwgPT0gKGZwID0gZm9wZW4oZmlsZTEsICJyYiIpKSkKICAgIHsKICAgICAgICByZXMgPSBFRFJfRmlsZU9wZW47CiAgICAgICAgZ290byBFTkRfREFUQVJFQUQ7CiAgICB9CiAgICBmc2VlayhmcCwgMCwgU0VFS19FTkQpOwogICAgaSA9IChpbnQpZnRlbGwoZnApICsgMTsKICAgIGZjbG9zZShmcCk7CiAgICBpZiAoTlVMTCA9PSAoZnAgPSBmb3BlbihmaWxlMiwgInJiIikpKQogICAgewogICAgICAgIHJlcyA9IEVEUl9GaWxlT3BlbjsKICAgICAgICBnb3RvIEVORF9EQVRBUkVBRDsKICAgIH0KICAgIGZzZWVrKGZwLCAwLCBTRUVLX0VORCk7CiAgICBqID0gKGludClmdGVsbChmcCkgKyAxOwogICAgZmNsb3NlKGZwKTsKICAgIGZwID0gTlVMTDsKICAgIGJ1Zl9zaXplID0gKGogPiBpKSA/IGogOiBpOwogICAgLy8gYnVmZiDnorrkv50KICAgIGlmKE5VTEwgPT0gKGJ1ZiA9IChjaGFyKiltYWxsb2MoYnVmX3NpemUpKSkKICAgIHsKICAgICAgICByZXMgPSBFRFJfTWVtQWxsb2M7CiAgICAgICAgZ290byBFTkRfREFUQVJFQUQ7CiAgICB9CgogICAgLy8gdGVzdC50eHQg44KS56m66Kqt44G/44GX44Gm44OH44O844K/5pWwKOihjOaVsCnjgpLmlbDjgYjjgosKICAgIGZwID0gZm9wZW4oZmlsZTIsICJyIik7CiAgICBmb3IobGluZSA9IDA7IE5VTEwgIT0gZmdldHMoYnVmLCBidWZfc2l6ZSwgZnApOyBsaW5lKyspOwogICAgaWYobGluZSA8IDEpCiAgICB7CiAgICAgICAgcmVzID0gRURSX0Zld0RhdGE7CiAgICAgICAgZ290byBFTkRfREFUQVJFQUQ7CiAgICB9CiAgICBmY2xvc2UoZnApOwogICAgZnAgPSBOVUxMOwogICAgLy8g44OH44O844K/6aCY5Z+f56K65L+dCiAgICBpZihFRFJfTm9ybWFsICE9IChyZXMgPSBhbGRhdF9hbGxvYyhkLCBsaW5lKSkpCiAgICB7CiAgICAgICAgZ290byBFTkRfREFUQVJFQUQ7CiAgICB9CgogICAgLy8gc2FtcGxlLnR4dAogICAgZnAgPSBmb3BlbihmaWxlMSwgInIiKTsKICAgIGZnZXRzKGJ1ZiwgYnVmX3NpemUsIGZwKTsKICAgIC8vIGZpbGVuYW1lCiAgICBpZihOVUxMID09ICh0b2tlbiA9IHN0cnRvayhidWYsICJcdCIpKSkKICAgIHsKICAgICAgICByZXMgPSBFRFJfRmV3RGF0YTsKICAgICAgICBnb3RvIEVORF9EQVRBUkVBRDsKICAgIH0KICAgIHN0cm5jcHkoZC0+YV9mbmFtZSwgdG9rZW4sIF9NQVhfUEFUSCk7CiAgICAvLyBkYXRhCiAgICBmb3IgKGogPSAwOyBqIDwgREFUX047IGorKykgewogICAgICAgIHRva2VuID0gc3RydG9rKE5VTEwsICJcdCIpOwogICAgICAgIGlmIChOVUxMID09IHRva2VuKSB7CiAgICAgICAgICAgIHJlcyA9IEVEUl9GZXdEYXRhOwogICAgICAgICAgICBnb3RvIEVORF9EQVRBUkVBRDsKICAgICAgICB9CiAgICAgICAgZC0+YV9kYXRhW2pdID0gYXRvZih0b2tlbik7CiAgICB9CiAgICBmY2xvc2UoZnApOwogICAgZnAgPSBOVUxMOwoKICAgIC8vIHRlc3QudHh0CiAgICBmcCA9IGZvcGVuKGZpbGUyLCAiciIpOwogICAgZm9yKGkgPSAwOyBpIDwgZC0+Yl9saW5lczsgaSsrKQogICAgewogICAgICAgIGZnZXRzKGJ1ZiwgYnVmX3NpemUsIGZwKTsKICAgICAgICAvLyBmaWxlbmFtZQogICAgICAgIGlmKE5VTEwgPT0gKHRva2VuID0gc3RydG9rKGJ1ZiwgIlx0IikpKQogICAgICAgIHsKICAgICAgICAgICAgcmVzID0gRURSX0Zld0RhdGE7CiAgICAgICAgICAgIGdvdG8gRU5EX0RBVEFSRUFEOwogICAgICAgIH0KICAgICAgICBzdHJuY3B5KGQtPmJfZm5hbWVbaV0sIHRva2VuLCBfTUFYX1BBVEgpOwogICAgICAgIC8vIGRhdGEKICAgICAgICBmb3IgKGogPSAwOyBqIDwgREFUX047IGorKykgewogICAgICAgICAgICB0b2tlbiA9IHN0cnRvayhOVUxMLCAiXHQiKTsKICAgICAgICAgICAgaWYgKE5VTEwgPT0gdG9rZW4pIHsKICAgICAgICAgICAgICAgIHJlcyA9IEVEUl9GZXdEYXRhOwogICAgICAgICAgICAgICAgZ290byBFTkRfREFUQVJFQUQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZC0+Yl9kYXRhW2ldW2pdID0gYXRvZih0b2tlbik7CiAgICAgICAgfQogICAgfQogICAgZmNsb3NlKGZwKTsKICAgIGZwID0gTlVMTDsKCiAgICByZXMgPSBFRFJfTm9ybWFsOwpFTkRfREFUQVJFQUQ6OwogICAgaWYocmVzICE9IEVEUl9Ob3JtYWwpCiAgICB7CiAgICAgICAgYWxkYXRfZnJlZShkKTsKICAgIH0KICAgIGlmKGJ1ZikKICAgIHsKICAgICAgICBmcmVlKGJ1Zik7CiAgICAgICAgYnVmID0gTlVMTDsKICAgIH0KICAgIGJ1Zl9zaXplID0gMDsKICAgIGlmKGZwKQogICAgewogICAgICAgIGZjbG9zZShmcCk7CiAgICAgICAgZnAgPSBOVUxMOwogICAgfQogICAgcmV0dXJuIHJlczsKfQoKLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8g6Zai5pWwID0g5pyJ5Yq55pWw5a2XbuahgeWwj+aVsOaWh+Wtl+WIl+eUn+aIkAovLyDli5XkvZwgPSDkvovjgYjjgbAgbiA9PSA2IOOBruOBqOOBjeOAgQovLyAgICAgICAgICAgICAgMC4wICAgICAgICAgICAgIOKGkiAiMCIKLy8gICAgICAgICAgICAgIDAuMTIzNDU2Nzg5ICAgICDihpIgIjAuMTIzNDU3IgovLyAgICAgICAgICAgICAgMC4wMDAxMjM0NTY3ODkgIOKGkiAiMC4wMDAxMjM0NTciCi8vICAgICAgICAgICAgICAwLjAxMjAwMDAgICAgICAg4oaSICIwLjAxMiIKLy8gICAgICAgICAg44KS6L+U44GZCi8vIOODoeODoiA9IOODu24gPCAxNgovLyAgICAgICAg44O75pyq5a6M5oiQCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmNoYXIgKmYyc19uKGRvdWJsZSBkLCBpbnQgbikKewogICAgc3RhdGljIGNoYXIgYlszMl07CgogICAgaWYoZCA9PSAwLjApCiAgICB7CiAgICAgICAgcmV0dXJuICIwIjsKICAgIH0KICAgIHNwcmludGYoYiwgIiUuKmYiLCBuLCBkKTsKCiAgICByZXR1cm4gJmJbMF07Cn0KCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vICAgICAg44OH44O844K/5Ye65YqbIChkZWJ1ZykKLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KI2lmZGVmIF9ERUJVRwp2b2lkIGRlYnVnX2ZpbGVfb3V0KEFMTF9EQVRBICpkKQp7CiAgICBpbnQgaSwgajsKICAgIEZJTEUgKmZwOwoKICAgIGZwID0gZm9wZW4oImRiZ19zLnR4dCIsICJ3Iik7CiAgICBmcHJpbnRmKGZwLCAiJXNcdCIsIGQtPmFfZm5hbWUpOwogICAgZm9yKGogPSAwOyBqIDwgREFUX047IGorKykKICAgIHsKICAgICAgICBmcHJpbnRmKGZwLCAiJXNcdCIsIGYyc19uKGQtPmFfZGF0YVtqXSwgNikpOwogICAgfQogICAgZnByaW50ZihmcCwgIlxuIik7CiAgICBmY2xvc2UoZnApOwogICAgZnAgPSBmb3BlbigiZGJnX3QudHh0IiwgInciKTsKICAgIGZvcihpID0gMDsgaSA8IGQtPmJfbGluZXM7IGkrKykKICAgIHsKICAgICAgICBmcHJpbnRmKGZwLCAiJXNcdCIsIGQtPmJfZm5hbWVbaV0pOwogICAgICAgIGZvcihqID0gMDsgaiA8IERBVF9OOyBqKyspCiAgICAgICAgewogICAgICAgICAgICBmcHJpbnRmKGZwLCAiJXNcdCIsIGYyc19uKGQtPmJfZGF0YVtpXVtqXSwgNikpOwogICAgICAgIH0KICAgICAgICBmcHJpbnRmKGZwLCAiXG4iKTsKICAgIH0KICAgIGZjbG9zZShmcCk7Cn0KI2VuZGlmCgovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLyAgICAgIG1haW4KLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KaW50IG1haW4oKQp7CiAgICBpbnQgcmVzdWx0ID0gMDsKICAgIEFMTF9EQVRBIGRhdGE7CiAgICBFUlJfQ09ERSByZXM7CiAgICBpbnQgaSwgajsKICAgIGRvdWJsZSB2MSx2Mix2MzsKCiAgICAvLyDliJ3mnJ/ljJYKICAgIGFsZGF0X2luaXQoJmRhdGEpOwoKICAgIC8vIHJlYWQKICAgIGlmKEVEUl9Ob3JtYWwgIT0gKHJlcyA9IGRhdGFfcmVhZChGSUxFX1NBTVBMRSwgRklMRV9URVNULCAmZGF0YSkpKQogICAgewogICAgICAgIHJlc3VsdCA9IChpbnQpcmVzOwogICAgICAgIGdvdG8gRU5EX01BSU47CiAgICB9CgogICAgLy8gKGRlYnVn44Oi44O844OJ5pmCKSDoqq3jgpPjgaDjg4fjg7zjgr/jgpLnorroqo3jga7jgZ/jgoHjg5XjgqHjgqTjg6sgZGJnX3MudHh0LCBkYmdfdC50eHQg44Gr5pu444GN5Ye644GZCiAgICBkZWJ1Z19vdXQoJmRhdGEpOwoKICAgIC8vIOioiOeulwogICAgZm9yKGk9MDsgaSA8IGRhdGEuYl9saW5lczsgaSsrKQogICAgewogICAgICAgIHYxID0gdjIgPSB2MyA9IDAuMDsKICAgICAgICBmb3Ioaj0wOyBqPCBEQVRfTjsgaisrKQogICAgICAgIHsKICAgICAgICAgICAgdjEgKz0gZGF0YS5hX2RhdGFbal0gKiBkYXRhLmJfZGF0YVtpXVtqXTsKICAgICAgICAgICAgdjIgKz0gZGF0YS5hX2RhdGFbal0gKiBkYXRhLmFfZGF0YVtqXTsKICAgICAgICAgICAgdjMgKz0gZGF0YS5iX2RhdGFbaV1bal0gKiBkYXRhLmJfZGF0YVtpXVtqXTsKICAgICAgICB9CiAgICAgICAgaWYodjIgPT0gMC4wIHx8IHYzID09IDAuMCkKICAgICAgICB7CiAgICAgICAgICAgIGZwcmludGYoc3RkZXJyLCAiJWTooYznm67jgIEiLCBpICsgMSk7CiAgICAgICAgICAgIHJlc3VsdCA9IEVEUl9aZXJvOwogICAgICAgICAgICBnb3RvIEVORF9NQUlOOwogICAgICAgIH0KICAgICAgICBkYXRhLmNfZGF0YVtpXSA9IHYxIC8gKHNxcnQodjIpICogc3FydCh2MykpOwogICAgfQoKICAgIC8vIOe1kOaenAogICAgZm9yKGk9MDsgaSA8IGRhdGEuYl9saW5lczsgaSsrKQogICAgewogICAgICAgIHByaW50ZigiJXNcdCVzXG4iLCBkYXRhLmJfZm5hbWVbaV0sIGYyc19uKGRhdGEuY19kYXRhW2ldLCAxNSkpOwogICAgfQoKICAgIC8vIGVuZAogICAgcmVzdWx0ID0gKGludClFRFJfTm9ybWFsOwpFTkRfTUFJTjo7CiAgICBhbGRhdF9mcmVlKCZkYXRhKTsKICAgIGlmKEVEUl9Ob3JtYWwgIT0gcmVzdWx0KQogICAgewogICAgICAgIGZwcmludGYoc3RkZXJyLCAiJXNcbiIsIGdldFN0ckVSUl9DT0RFKHJlc3VsdCkpOwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKfQo=