#include<iostream>
#include<typeinfo>
#include<cxxabi.h>
template < int N> struct V{ } ;
template < int N,class T> struct args{ } ;
template < int M,int N> struct Var{ } ;
template < bool N,class T> struct either{ } ;
struct nu{ } ;
template < class R,class T> struct lambda;
template < class M,class N> struct A{
typedef A< M,N> type;
template < class T> A< A< M,N> ,typename T:: type > operator( ) ( T) {
return A< A< M,N> ,typename T:: type > ( ) ;
}
} ;
template < int N> struct ph{
typedef V< N> type;
template < class T> A< V< N> ,typename T:: type > operator( ) ( T) {
return A< V< N> ,typename T:: type > ( ) ;
}
} ;
template < int N,class T> struct addarg{ } ;
template < int N> struct addarg< N,nu> {
typedef args< N,nu> type;
} ;
template < int N,int C,class T> struct addarg< N,args< C,T> > {
typedef args< C,typename addarg< N,T> :: type > type;
} ;
template < int N,int C,class T> struct notfound{ } ;
template < int N,int C,class T> struct notfound< N,C,args< C,T> > {
static const int value= N;
} ;
template < int N,int C,int R,class T> struct notfound< N,C,args< R,T> > {
static const int value= notfound< N,C,T> :: value ;
} ;
template < int N,int C> struct notfound< N,C,nu> {
static const int value= - 1 ;
} ;
template < int N,class T,class F> struct format_t{
typedef T type;
} ;
template < int N,int C,class F> struct format_t< N,V< C> ,F> {
typedef Var< notfound< N,C,F> :: value ,C> type;
} ;
template < int N,int C,class F> struct format_t< N,Var< - 1 ,C> ,F> {
typedef Var< notfound< 0 ,C,F> :: value ,C> type;
} ;
template < int N,int T,int C,class F> struct format_t< N,Var< T,C> ,F> {
typedef Var< T+ 1 ,C> type;
} ;
template < int N,class L,class R,class F> struct format_t< N,A< L,R> ,F> {
typedef A< typename format_t< N,L,F> :: type ,typename format_t< N,R,F> :: type > type;
} ;
template < int N,class T,class P,class F> struct format_t< N,lambda< T,P> ,F> {
typedef lambda< T,typename format_t< N+ 1 ,P,F> :: type > type;
} ;
template < class T,class F> struct format{
typedef typename format_t< 0 ,T,F> :: type type;
} ;
template < class T> struct lambda_t{
template < int N> lambda_t< typename addarg< N,T> :: type > operator [ ] ( ph< N> ) {
return lambda_t< typename addarg< N,T> :: type > ( ) ;
}
template < class P> lambda< T,typename format< typename P:: type ,T> :: type > operator ( ) ( P) {
return lambda< T,typename format< typename P:: type ,T> :: type > ( ) ;
}
} ;
template < class T> struct subst{
typedef T type;
} ;
template < class R,class T> struct subst< lambda< R,T> > {
typedef lambda< R,typename subst< T> :: type > type;
} ;
template < class M,class N> struct subst< A< M,N> > {
typedef A< typename subst< M> :: type ,typename subst< N> :: type > type;
} ;
template < int N,int T> struct subst< Var< N,T> > {
typedef Var< N- 1 ,T> type;
} ;
template < class T> struct clean{
typedef T type;
} ;
template < class T> struct clean< lambda< nu,T> > {
typedef typename subst< T> :: type type;
} ;
template < class T,int N> struct upper{
typedef T type;
} ;
template < class L,class R,int N> struct upper< A< L,R> ,N> {
typedef A< typename upper< L,N> :: type ,typename upper< R,N> :: type > type;
} ;
template < class R,class M,int N> struct upper< lambda< R,M> ,N> {
typedef lambda< R,typename upper< M,N> :: type > type;
} ;
template < int L,int N,int R> struct upper< Var< L,N> ,R> {
typedef Var< L+ R,N> type;
} ;
template < int C,int P,class M,class T,int N> struct simple{
typedef M type;
} ;
template < int C,int P,class T,int N> struct simple< C,P,Var< C,P> ,T,N> {
typedef typename upper< T,N> :: type type;
} ;
template < int C,int P,class R,class M,class T,int N> struct simple< C,P,lambda< R,M> ,T,N> {
typedef lambda< R,typename simple< C,P,M,T,N+ 1 > :: type > type;
} ;
template < int C,int P,class L,class R,class T,int N> struct simple< C,P,A< L,R> ,T,N> {
typedef A< typename simple< C,P,L,T,N> :: type ,typename simple< C,P,R,T,N> :: type > type;
} ;
template < class M,class N> struct either_apply{ } ;
template < bool F1,class T1,bool F2,class T2> struct either_apply< either< F1,T1> ,either< F2,T2> > {
typedef either< F1 || F2,A< T1,T2> > type;
} ;
template < class M,class N> struct either_lambda{ } ;
template < class R,bool F,class T> struct either_lambda< R,either< F,T> > {
typedef either< F,lambda< R,T> > type;
} ;
template < int N,class T> struct beta{
typedef either< 0 ,T> type;
} ;
template < int C,int P,class R,class M,class N> struct beta< C,A< lambda< args< P,R> ,M> ,N> > {
typedef either< 1 ,typename clean< lambda< R,typename simple< C,P,M,N,1 > :: type > > :: type > type;
} ;
template < int C,class M,class N> struct beta< C,A< M,N> > {
typedef typename either_apply< typename beta< C,M> :: type ,typename beta< C,N> :: type > :: type type;
} ;
template < int C,class R,class T> struct beta< C,lambda< R,T> > {
typedef typename either_lambda< R,typename beta< C+ 1 ,T> :: type > :: type type;
} ;
template < class T> struct Re{ } ;
template < class T> struct Re< either< 0 ,T> > {
typedef T type;
} ;
template < class T> struct Re< either< 1 ,T> > {
typedef typename Re< typename beta< 0 ,T> :: type > :: type type;
} ;
template < class M,class N> struct lambda{
typedef lambda< M,N> type;
template < class T> typename Re< typename beta< 0 ,A< lambda< M,N> ,T> > :: type > :: type operator ( ) ( T) {
return typename Re< typename beta< 0 ,A< lambda< M,N> ,T> > :: type > :: type ( ) ;
}
} ;
template < int N> struct church_t{
typedef A< Var< 0 ,27 > ,typename church_t< N- 1 > :: type > type;
} ;
template <> struct church_t< 0 > {
typedef Var< 0 ,28 > type;
} ;
template < int N> struct Church{
typedef lambda< args< 27 ,args< 28 ,nu> > ,typename church_t< N> :: type > type;
static const type value;
} ;
template < class T> struct count{ } ;
template < int N,class T> struct count< A< Var< N,27 > ,T> > {
static const int value= count< T> :: value + 1 ;
} ;
template < int N> struct count< Var< N,28 > > {
static const int value= 0 ;
} ;
template < class R,class T> std:: ostream & operator<< ( std:: ostream & os,lambda< R,T> ) {
os<< "(λ" << R( ) << "." << T( ) << ")" ;
return os;
} ;
template < class T> std:: ostream & operator<< ( std:: ostream & os,lambda< args< 27 ,args< 28 ,nu> > ,T> ) {
os<< count< T> :: value ;
return os;
} ;
template < int M,int N> std:: ostream & operator<< ( std:: ostream & os,Var< M,N> ) {
os<< char ( N+ 96 ) ;
return os;
} ;
template < class L,class R,class C> std:: ostream & operator<< ( std:: ostream & os,A< L,A< C,R> > ) {
os<< L( ) << " (" << A< C,R> ( ) << ")" ;
return os;
} ;
template < class L,class R> std:: ostream & operator<< ( std:: ostream & os,A< L,R> ) {
os<< L( ) << " " << R( ) ;
return os;
} ;
template < int N> std:: ostream & operator<< ( std:: ostream & os,V< N> ) {
os<< char ( N+ 96 ) ;
return os;
} ;
template < int N,class R> std:: ostream & operator<< ( std:: ostream & os,args< N,R> ) {
os<< char ( N+ 96 ) << R( ) ;
return os;
}
std:: ostream & operator<< ( std:: ostream & os,nu) {
return os;
}
template < int N> std:: ostream & operator<< ( std:: ostream & os,ph< N> ) {
os<< char ( N+ 96 ) ;
return os;
}
lambda_t< nu> Lambda;
ph< 1 > a;
ph< 2 > b;
ph< 3 > c;
ph< 4 > d;
ph< 5 > e;
ph< 6 > f;
ph< 7 > g;
ph< 8 > h;
ph< 9 > i;
ph< 10 > j;
ph< 11 > k;
ph< 12 > l;
ph< 13 > m;
ph< 14 > n;
ph< 15 > o;
ph< 16 > p;
ph< 17 > q;
ph< 18 > r;
ph< 19 > s;
ph< 20 > t;
ph< 21 > u;
ph< 22 > v;
ph< 23 > w;
ph< 24 > x;
ph< 25 > y;
ph< 26 > z;
ph< 27 > Fu;
ph< 28 > Va;
auto _s= Lambda[ x] [ y] [ z] ( x( z) ( y( z) ) ) ;
auto _k= Lambda[ x] [ y] ( x) ;
auto _i= Lambda[ x] ( x) ;
#define S (_s)
#define K (_k)
#define I (_i)
auto Succ= Lambda[ n] [ Fu] [ Va] ( Fu( n( Fu) ( Va) ) ) ;
auto Prev= Lambda[ n] [ Fu] [ Va] ( n( Lambda[ g] [ h] ( h( g( Fu) ) ) ) ( Lambda[ u] ( Va) ) ( Lambda[ u] ( u) ) ) ;
auto Add= Lambda[ m] [ n] [ Fu] [ Va] ( m( Fu) ( n( Fu) ( Va) ) ) ;
auto Mul= Lambda[ m] [ n] [ Fu] [ Va] ( m( n( Fu) ) ( Va) ) ;
auto True= Lambda[ x] [ y] ( x) ;
auto False= Lambda[ x] [ y] ( y) ;
auto And= Lambda[ p] [ q] ( p( q) ( False) ) ;
auto Or= Lambda[ p] [ q] ( p( True) ( q) ) ;
auto Not= Lambda[ p] ( p( False) ( True) ) ;
auto If= Lambda[ p] [ x] [ y] ( p( x) ( y) ) ;
auto Cons= Lambda[ s] [ b] [ f] ( f( s) ( b) ) ;
auto Car= Lambda[ p] ( p( True) ) ;
auto Cdr= Lambda[ p] ( p( False) ) ;
int main( ) {
//SKI
std:: cout << S<< std:: endl ;
std:: cout << K<< std:: endl ;
std:: cout << I<< std:: endl ;
std:: cout << S K K ( a) << std:: endl ;
std:: cout << S I I ( a) << std:: endl ;
std:: cout << K ( a) << std:: endl ;
std:: cout << K ( a) ( b) << std:: endl ;
std:: cout << K I<< std:: endl ;
std:: cout << K I ( a) ( b) << std:: endl ;
std:: cout << S( S( K( S) ) K) ( I) << std:: endl ; //Bug Expect:λxy.x(x y)
//std::cout<<S I I(S I I)<<std::endl; -- おなじみのアレ コンパイルエラー
std:: cout << std:: endl ;
//Church 数値で出力するようになってはいる
std:: cout << Church< 5 > :: value << std:: endl ;
std:: cout << Succ( Church< 5 > :: value ) << std:: endl ;
std:: cout << Prev( Church< 5 > :: value ) << std:: endl ;
std:: cout << Add( Church< 5 > :: value ) ( Church< 3 > :: value ) << std:: endl ;
std:: cout << Mul( Church< 5 > :: value ) ( Church< 3 > :: value ) << std:: endl ;
std:: cout << std:: endl ;
//Logic 出力はそのまま
std:: cout << True<< std:: endl ;
std:: cout << False<< std:: endl ;
std:: cout << And( True) ( True) << std:: endl ;
std:: cout << And( True) ( False) << std:: endl ;
std:: cout << Or( False) ( True) << std:: endl ;
std:: cout << Or( False) ( False) << std:: endl ;
std:: cout << Not( True) << std:: endl ;
std:: cout << Not( False) << std:: endl ;
std:: cout << If( True) ( Church< 5 > :: value ) ( Church< 3 > :: value ) << std:: endl ;
std:: cout << If( False) ( Church< 5 > :: value ) ( Church< 3 > :: value ) << std:: endl ;
std:: cout << If( And( False) ( True) ) ( Church< 5 > :: value ) ( Church< 3 > :: value ) << std:: endl ;
std:: cout << std:: endl ;
//Cons,List 出力はそのまま
std:: cout << Cons( a) ( b) << std:: endl ;
std:: cout << Car( Cons( a) ( b) ) << std:: endl ;
std:: cout << Cdr( Cons( a) ( b) ) << std:: endl ;
auto tc= Cons( Cons( a) ( b) ) ( Cons( c) ( d) ) ;
std:: cout << tc<< std:: endl ;
std:: cout << Car( tc) << std:: endl ;
std:: cout << Cdr( Car( tc) ) << std:: endl ;
auto lt= Cons( a) ( Cons( b) ( Cons( c) ( False) ) ) ;
std:: cout << Car( lt) << std:: endl ;
std:: cout << Cdr( lt) << std:: endl ;
std:: cout << Cdr( Cdr( Cdr( lt) ) ) << std:: endl ;
std:: cout << std:: endl ;
}
I2luY2x1ZGU8aW9zdHJlYW0+CiNpbmNsdWRlPHR5cGVpbmZvPgojaW5jbHVkZTxjeHhhYmkuaD4KCnRlbXBsYXRlPGludCBOPiBzdHJ1Y3QgVnt9Owp0ZW1wbGF0ZTxpbnQgTixjbGFzcyBUPiBzdHJ1Y3QgYXJnc3t9Owp0ZW1wbGF0ZTxpbnQgTSxpbnQgTj4gc3RydWN0IFZhcnt9Owp0ZW1wbGF0ZTxib29sIE4sY2xhc3MgVD4gc3RydWN0IGVpdGhlcnt9OwpzdHJ1Y3QgbnV7fTsKdGVtcGxhdGU8Y2xhc3MgUixjbGFzcyBUPiBzdHJ1Y3QgbGFtYmRhOwoKdGVtcGxhdGU8Y2xhc3MgTSxjbGFzcyBOPiBzdHJ1Y3QgQXsKCXR5cGVkZWYgQTxNLE4+IHR5cGU7Cgl0ZW1wbGF0ZTxjbGFzcyBUPiBBPEE8TSxOPix0eXBlbmFtZSBUOjp0eXBlPiBvcGVyYXRvcigpKFQpewoJCXJldHVybiBBPEE8TSxOPix0eXBlbmFtZSBUOjp0eXBlPigpOwoJfQp9Owp0ZW1wbGF0ZTxpbnQgTj4gc3RydWN0IHBoewoJdHlwZWRlZiBWPE4+IHR5cGU7Cgl0ZW1wbGF0ZTxjbGFzcyBUPiBBPFY8Tj4sdHlwZW5hbWUgVDo6dHlwZT4gb3BlcmF0b3IoKShUKXsKCQlyZXR1cm4gQTxWPE4+LHR5cGVuYW1lIFQ6OnR5cGU+KCk7Cgl9Cn07Cgp0ZW1wbGF0ZTxpbnQgTixjbGFzcyBUPiBzdHJ1Y3QgYWRkYXJne307CnRlbXBsYXRlPGludCBOPiBzdHJ1Y3QgYWRkYXJnPE4sbnU+ewoJdHlwZWRlZiBhcmdzPE4sbnU+IHR5cGU7Cn07CnRlbXBsYXRlPGludCBOLGludCBDLGNsYXNzIFQ+IHN0cnVjdCBhZGRhcmc8TixhcmdzPEMsVD4gPnsKCXR5cGVkZWYgYXJnczxDLHR5cGVuYW1lIGFkZGFyZzxOLFQ+Ojp0eXBlPiB0eXBlOwp9OwoKdGVtcGxhdGU8aW50IE4saW50IEMsY2xhc3MgVD4gc3RydWN0IG5vdGZvdW5ke307CnRlbXBsYXRlPGludCBOLGludCBDLGNsYXNzIFQ+IHN0cnVjdCBub3Rmb3VuZDxOLEMsYXJnczxDLFQ+ID57CglzdGF0aWMgY29uc3QgaW50IHZhbHVlPU47Cn07CnRlbXBsYXRlPGludCBOLGludCBDLGludCBSLGNsYXNzIFQ+IHN0cnVjdCBub3Rmb3VuZDxOLEMsYXJnczxSLFQ+ID57CglzdGF0aWMgY29uc3QgaW50IHZhbHVlPW5vdGZvdW5kPE4sQyxUPjo6dmFsdWU7Cn07CnRlbXBsYXRlPGludCBOLGludCBDPiBzdHJ1Y3Qgbm90Zm91bmQ8TixDLG51PnsKCXN0YXRpYyBjb25zdCBpbnQgdmFsdWU9LTE7Cn07Cgp0ZW1wbGF0ZTxpbnQgTixjbGFzcyBULGNsYXNzIEY+IHN0cnVjdCBmb3JtYXRfdHsKCXR5cGVkZWYgVCB0eXBlOwp9Owp0ZW1wbGF0ZTxpbnQgTixpbnQgQyxjbGFzcyBGPiBzdHJ1Y3QgZm9ybWF0X3Q8TixWPEM+LEY+ewoJdHlwZWRlZiBWYXI8bm90Zm91bmQ8TixDLEY+Ojp2YWx1ZSxDPiB0eXBlOwp9Owp0ZW1wbGF0ZTxpbnQgTixpbnQgQyxjbGFzcyBGPiBzdHJ1Y3QgZm9ybWF0X3Q8TixWYXI8LTEsQz4sRj57Cgl0eXBlZGVmIFZhcjxub3Rmb3VuZDwwLEMsRj46OnZhbHVlLEM+IHR5cGU7Cn07CnRlbXBsYXRlPGludCBOLGludCBULGludCBDLGNsYXNzIEY+IHN0cnVjdCBmb3JtYXRfdDxOLFZhcjxULEM+LEY+ewoJdHlwZWRlZiBWYXI8VCsxLEM+IHR5cGU7Cn07CnRlbXBsYXRlPGludCBOLGNsYXNzIEwsY2xhc3MgUixjbGFzcyBGPiBzdHJ1Y3QgZm9ybWF0X3Q8TixBPEwsUj4sRj57Cgl0eXBlZGVmIEE8dHlwZW5hbWUgZm9ybWF0X3Q8TixMLEY+Ojp0eXBlLHR5cGVuYW1lIGZvcm1hdF90PE4sUixGPjo6dHlwZT4gdHlwZTsKfTsKdGVtcGxhdGU8aW50IE4sY2xhc3MgVCxjbGFzcyBQLGNsYXNzIEY+IHN0cnVjdCBmb3JtYXRfdDxOLGxhbWJkYTxULFA+LEY+ewoJdHlwZWRlZiBsYW1iZGE8VCx0eXBlbmFtZSBmb3JtYXRfdDxOKzEsUCxGPjo6dHlwZT4gdHlwZTsKfTsKdGVtcGxhdGU8Y2xhc3MgVCxjbGFzcyBGPiBzdHJ1Y3QgZm9ybWF0ewoJdHlwZWRlZiB0eXBlbmFtZSBmb3JtYXRfdDwwLFQsRj46OnR5cGUgdHlwZTsKfTsKCnRlbXBsYXRlPGNsYXNzIFQ+IHN0cnVjdCBsYW1iZGFfdHsKCXRlbXBsYXRlPGludCBOPiBsYW1iZGFfdDx0eXBlbmFtZSBhZGRhcmc8TixUPjo6dHlwZT4gb3BlcmF0b3IgW10ocGg8Tj4pewoJCXJldHVybiBsYW1iZGFfdDx0eXBlbmFtZSBhZGRhcmc8TixUPjo6dHlwZT4oKTsKCX0KCXRlbXBsYXRlPGNsYXNzIFA+IGxhbWJkYTxULHR5cGVuYW1lIGZvcm1hdDx0eXBlbmFtZSBQOjp0eXBlLFQ+Ojp0eXBlPiBvcGVyYXRvciAoKShQKXsKCQlyZXR1cm4gbGFtYmRhPFQsdHlwZW5hbWUgZm9ybWF0PHR5cGVuYW1lIFA6OnR5cGUsVD46OnR5cGU+KCk7Cgl9Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUPiBzdHJ1Y3Qgc3Vic3R7Cgl0eXBlZGVmIFQgdHlwZTsJCn07CnRlbXBsYXRlPGNsYXNzIFIsY2xhc3MgVD4gc3RydWN0IHN1YnN0PGxhbWJkYTxSLFQ+ID57Cgl0eXBlZGVmIGxhbWJkYTxSLHR5cGVuYW1lIHN1YnN0PFQ+Ojp0eXBlPiB0eXBlOwp9Owp0ZW1wbGF0ZTxjbGFzcyBNLGNsYXNzIE4+IHN0cnVjdCBzdWJzdDxBPE0sTj4gPnsKCXR5cGVkZWYgQTx0eXBlbmFtZSBzdWJzdDxNPjo6dHlwZSx0eXBlbmFtZSBzdWJzdDxOPjo6dHlwZT4gdHlwZTsKfTsKdGVtcGxhdGU8aW50IE4saW50IFQ+IHN0cnVjdCBzdWJzdDxWYXI8TixUPiA+ewoJdHlwZWRlZiBWYXI8Ti0xLFQ+IHR5cGU7Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUPiBzdHJ1Y3QgY2xlYW57Cgl0eXBlZGVmIFQgdHlwZTsKfTsKdGVtcGxhdGU8Y2xhc3MgVD4gc3RydWN0IGNsZWFuPGxhbWJkYTxudSxUPiA+ewoJdHlwZWRlZiB0eXBlbmFtZSBzdWJzdDxUPjo6dHlwZSB0eXBlOwp9OwoKdGVtcGxhdGU8Y2xhc3MgVCxpbnQgTj4gc3RydWN0IHVwcGVyewoJdHlwZWRlZiBUIHR5cGU7Cn07CnRlbXBsYXRlPGNsYXNzIEwsY2xhc3MgUixpbnQgTj4gc3RydWN0IHVwcGVyPEE8TCxSPixOPnsKCXR5cGVkZWYgQTx0eXBlbmFtZSB1cHBlcjxMLE4+Ojp0eXBlLHR5cGVuYW1lIHVwcGVyPFIsTj46OnR5cGU+IHR5cGU7Cn07CnRlbXBsYXRlPGNsYXNzIFIsY2xhc3MgTSxpbnQgTj4gc3RydWN0IHVwcGVyPGxhbWJkYTxSLE0+LE4+ewoJdHlwZWRlZiBsYW1iZGE8Uix0eXBlbmFtZSB1cHBlcjxNLE4+Ojp0eXBlPiB0eXBlOwp9Owp0ZW1wbGF0ZTxpbnQgTCxpbnQgTixpbnQgUj4gc3RydWN0IHVwcGVyPFZhcjxMLE4+LFI+ewoJdHlwZWRlZiBWYXI8TCtSLE4+IHR5cGU7Cn07Cgp0ZW1wbGF0ZTxpbnQgQyxpbnQgUCxjbGFzcyBNLGNsYXNzIFQsaW50IE4+IHN0cnVjdCBzaW1wbGV7Cgl0eXBlZGVmIE0gdHlwZTsKfTsKdGVtcGxhdGU8aW50IEMsaW50IFAsY2xhc3MgVCxpbnQgTj4gc3RydWN0IHNpbXBsZTxDLFAsVmFyPEMsUD4sVCxOPnsKCXR5cGVkZWYgdHlwZW5hbWUgdXBwZXI8VCxOPjo6dHlwZSB0eXBlOwp9Owp0ZW1wbGF0ZTxpbnQgQyxpbnQgUCxjbGFzcyBSLGNsYXNzIE0sY2xhc3MgVCxpbnQgTj4gc3RydWN0IHNpbXBsZTxDLFAsbGFtYmRhPFIsTT4sVCxOPnsKCXR5cGVkZWYgbGFtYmRhPFIsdHlwZW5hbWUgc2ltcGxlPEMsUCxNLFQsTisxPjo6dHlwZT4gdHlwZTsKfTsKdGVtcGxhdGU8aW50IEMsaW50IFAsY2xhc3MgTCxjbGFzcyBSLGNsYXNzIFQsaW50IE4+IHN0cnVjdCBzaW1wbGU8QyxQLEE8TCxSPixULE4+ewoJdHlwZWRlZiBBPHR5cGVuYW1lIHNpbXBsZTxDLFAsTCxULE4+Ojp0eXBlLHR5cGVuYW1lIHNpbXBsZTxDLFAsUixULE4+Ojp0eXBlPiB0eXBlOwp9OwoKdGVtcGxhdGU8Y2xhc3MgTSxjbGFzcyBOPiBzdHJ1Y3QgZWl0aGVyX2FwcGx5e307CnRlbXBsYXRlPGJvb2wgRjEsY2xhc3MgVDEsYm9vbCBGMixjbGFzcyBUMj4gc3RydWN0IGVpdGhlcl9hcHBseTxlaXRoZXI8RjEsVDE+LGVpdGhlcjxGMixUMj4gPnsKCXR5cGVkZWYgZWl0aGVyPEYxIHx8IEYyLEE8VDEsVDI+ID4gdHlwZTsKfTsKdGVtcGxhdGU8Y2xhc3MgTSxjbGFzcyBOPiBzdHJ1Y3QgZWl0aGVyX2xhbWJkYXt9Owp0ZW1wbGF0ZTxjbGFzcyBSLGJvb2wgRixjbGFzcyBUPiBzdHJ1Y3QgZWl0aGVyX2xhbWJkYTxSLGVpdGhlcjxGLFQ+ID57Cgl0eXBlZGVmIGVpdGhlcjxGLGxhbWJkYTxSLFQ+ID4gdHlwZTsKfTsKCnRlbXBsYXRlPGludCBOLGNsYXNzIFQ+IHN0cnVjdCBiZXRhewoJdHlwZWRlZiBlaXRoZXI8MCxUPiB0eXBlOwp9Owp0ZW1wbGF0ZTxpbnQgQyxpbnQgUCxjbGFzcyBSLGNsYXNzIE0sY2xhc3MgTj4gc3RydWN0IGJldGE8QyxBPGxhbWJkYTxhcmdzPFAsUj4sTT4sTj4gPnsKCXR5cGVkZWYgZWl0aGVyPDEsdHlwZW5hbWUgY2xlYW48bGFtYmRhPFIsdHlwZW5hbWUgc2ltcGxlPEMsUCxNLE4sMT46OnR5cGU+ID46OnR5cGU+IHR5cGU7Cn07CnRlbXBsYXRlPGludCBDLGNsYXNzIE0sY2xhc3MgTj4gc3RydWN0IGJldGE8QyxBPE0sTj4gPnsKCXR5cGVkZWYgdHlwZW5hbWUgZWl0aGVyX2FwcGx5PHR5cGVuYW1lIGJldGE8QyxNPjo6dHlwZSx0eXBlbmFtZSBiZXRhPEMsTj46OnR5cGU+Ojp0eXBlIHR5cGU7Cn07CnRlbXBsYXRlPGludCBDLGNsYXNzIFIsY2xhc3MgVD4gc3RydWN0IGJldGE8QyxsYW1iZGE8UixUPiA+ewoJdHlwZWRlZiB0eXBlbmFtZSBlaXRoZXJfbGFtYmRhPFIsdHlwZW5hbWUgYmV0YTxDKzEsVD46OnR5cGU+Ojp0eXBlIHR5cGU7Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUPiBzdHJ1Y3QgUmV7fTsKdGVtcGxhdGU8Y2xhc3MgVD4gc3RydWN0IFJlPGVpdGhlcjwwLFQ+ID57Cgl0eXBlZGVmIFQgdHlwZTsKfTsKdGVtcGxhdGU8Y2xhc3MgVD4gc3RydWN0IFJlPGVpdGhlcjwxLFQ+ID57Cgl0eXBlZGVmIHR5cGVuYW1lIFJlPHR5cGVuYW1lIGJldGE8MCxUPjo6dHlwZT46OnR5cGUgdHlwZTsKfTsKCnRlbXBsYXRlPGNsYXNzIE0sY2xhc3MgTj4gc3RydWN0IGxhbWJkYXsKCXR5cGVkZWYgbGFtYmRhPE0sTj4gdHlwZTsKCXRlbXBsYXRlPGNsYXNzIFQ+IHR5cGVuYW1lIFJlPHR5cGVuYW1lIGJldGE8MCxBPGxhbWJkYTxNLE4+LFQ+ID46OnR5cGU+Ojp0eXBlIG9wZXJhdG9yICgpKFQpewoJCXJldHVybiB0eXBlbmFtZSBSZTx0eXBlbmFtZSBiZXRhPDAsQTxsYW1iZGE8TSxOPixUPiA+Ojp0eXBlPjo6dHlwZSgpOwoJfQp9OwoKdGVtcGxhdGU8aW50IE4+IHN0cnVjdCBjaHVyY2hfdHsKCXR5cGVkZWYgQTxWYXI8MCwyNz4sdHlwZW5hbWUgY2h1cmNoX3Q8Ti0xPjo6dHlwZT4gdHlwZTsKfTsKdGVtcGxhdGU8PiBzdHJ1Y3QgY2h1cmNoX3Q8MD57Cgl0eXBlZGVmIFZhcjwwLDI4PiB0eXBlOwp9Owp0ZW1wbGF0ZTxpbnQgTj4gc3RydWN0IENodXJjaHsKCXR5cGVkZWYgbGFtYmRhPGFyZ3M8MjcsYXJnczwyOCxudT4gPix0eXBlbmFtZSBjaHVyY2hfdDxOPjo6dHlwZT4gdHlwZTsKCXN0YXRpYyBjb25zdCB0eXBlIHZhbHVlOwp9OwoKdGVtcGxhdGU8Y2xhc3MgVD4gc3RydWN0IGNvdW50e307CnRlbXBsYXRlPGludCBOLGNsYXNzIFQ+IHN0cnVjdCBjb3VudDxBPFZhcjxOLDI3PixUPiA+ewoJc3RhdGljIGNvbnN0IGludCB2YWx1ZT1jb3VudDxUPjo6dmFsdWUrMTsKfTsKdGVtcGxhdGU8aW50IE4+IHN0cnVjdCBjb3VudDxWYXI8TiwyOD4gPnsKCXN0YXRpYyBjb25zdCBpbnQgdmFsdWU9MDsKfTsKCnRlbXBsYXRlPGNsYXNzIFIsY2xhc3MgVD4gc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgb3MsbGFtYmRhPFIsVD4pewoJb3M8PCIozrsiPDxSKCk8PCIuIjw8VCgpPDwiKSI7CglyZXR1cm4gb3M7Cn07CnRlbXBsYXRlPGNsYXNzIFQ+IHN0ZDo6b3N0cmVhbSYgb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0mIG9zLGxhbWJkYTxhcmdzPDI3LGFyZ3M8MjgsbnU+ID4sVD4pewoJb3M8PGNvdW50PFQ+Ojp2YWx1ZTsKCXJldHVybiBvczsKfTsKdGVtcGxhdGU8aW50IE0saW50IE4+IHN0ZDo6b3N0cmVhbSYgb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0mIG9zLFZhcjxNLE4+KXsKCW9zPDxjaGFyKE4rOTYpOwoJcmV0dXJuIG9zOwp9Owp0ZW1wbGF0ZTxjbGFzcyBMLGNsYXNzIFIsY2xhc3MgQz4gc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgb3MsQTxMLEE8QyxSPiA+KXsKCW9zPDxMKCk8PCIgKCI8PEE8QyxSPigpPDwiKSI7CglyZXR1cm4gb3M7Cn07CnRlbXBsYXRlPGNsYXNzIEwsY2xhc3MgUj4gc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgb3MsQTxMLFI+KXsKCW9zPDxMKCk8PCIgIjw8UigpOwoJcmV0dXJuIG9zOwp9Owp0ZW1wbGF0ZTxpbnQgTj4gc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgb3MsVjxOPil7Cglvczw8Y2hhcihOKzk2KTsKCXJldHVybiBvczsKfTsKdGVtcGxhdGU8aW50IE4sY2xhc3MgUj4gc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgb3MsYXJnczxOLFI+KXsKCW9zPDxjaGFyKE4rOTYpPDxSKCk7CglyZXR1cm4gb3M7Cn0Kc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgb3MsbnUpewoJcmV0dXJuIG9zOwp9CnRlbXBsYXRlPGludCBOPiBzdGQ6Om9zdHJlYW0mIG9wZXJhdG9yPDwoc3RkOjpvc3RyZWFtJiBvcyxwaDxOPil7Cglvczw8Y2hhcihOKzk2KTsJCglyZXR1cm4gb3M7Cn0KCmxhbWJkYV90PG51PiBMYW1iZGE7CnBoPDE+IGE7CnBoPDI+IGI7CnBoPDM+IGM7CnBoPDQ+IGQ7CnBoPDU+IGU7CnBoPDY+IGY7CnBoPDc+IGc7CnBoPDg+IGg7CnBoPDk+IGk7CnBoPDEwPiBqOwpwaDwxMT4gazsKcGg8MTI+IGw7CnBoPDEzPiBtOwpwaDwxND4gbjsKcGg8MTU+IG87CnBoPDE2PiBwOwpwaDwxNz4gcTsKcGg8MTg+IHI7CnBoPDE5PiBzOwpwaDwyMD4gdDsKcGg8MjE+IHU7CnBoPDIyPiB2OwpwaDwyMz4gdzsKcGg8MjQ+IHg7CnBoPDI1PiB5OwpwaDwyNj4gejsKcGg8Mjc+IEZ1OwpwaDwyOD4gVmE7CgphdXRvIF9zPUxhbWJkYVt4XVt5XVt6XSh4KHopKHkoeikpKTsKYXV0byBfaz1MYW1iZGFbeF1beV0oeCk7CmF1dG8gX2k9TGFtYmRhW3hdKHgpOwoKI2RlZmluZSBTIChfcykKI2RlZmluZSBLIChfaykKI2RlZmluZSBJIChfaSkKCmF1dG8gU3VjYz1MYW1iZGFbbl1bRnVdW1ZhXShGdShuKEZ1KShWYSkpKTsKYXV0byBQcmV2PUxhbWJkYVtuXVtGdV1bVmFdKG4oTGFtYmRhW2ddW2hdKGgoZyhGdSkpKSkoTGFtYmRhW3VdKFZhKSkoTGFtYmRhW3VdKHUpKSk7CmF1dG8gQWRkPUxhbWJkYVttXVtuXVtGdV1bVmFdKG0oRnUpKG4oRnUpKFZhKSkpOwphdXRvIE11bD1MYW1iZGFbbV1bbl1bRnVdW1ZhXShtKG4oRnUpKShWYSkpOwphdXRvIFRydWU9TGFtYmRhW3hdW3ldKHgpOwphdXRvIEZhbHNlPUxhbWJkYVt4XVt5XSh5KTsKYXV0byBBbmQ9TGFtYmRhW3BdW3FdKHAocSkoRmFsc2UpKTsKYXV0byBPcj1MYW1iZGFbcF1bcV0ocChUcnVlKShxKSk7CmF1dG8gTm90PUxhbWJkYVtwXShwKEZhbHNlKShUcnVlKSk7CmF1dG8gSWY9TGFtYmRhW3BdW3hdW3ldKHAoeCkoeSkpOwphdXRvIENvbnM9TGFtYmRhW3NdW2JdW2ZdKGYocykoYikpOwphdXRvIENhcj1MYW1iZGFbcF0ocChUcnVlKSk7CmF1dG8gQ2RyPUxhbWJkYVtwXShwKEZhbHNlKSk7CgppbnQgbWFpbigpewoJLy9TS0kKCXN0ZDo6Y291dDw8Uzw8c3RkOjplbmRsOwoJc3RkOjpjb3V0PDxLPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PEk8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8UyBLIEsgKGEpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PFMgSSBJIChhKTw8c3RkOjplbmRsOwoJc3RkOjpjb3V0PDxLIChhKTw8c3RkOjplbmRsOwoJc3RkOjpjb3V0PDxLIChhKSAoYik8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8SyBJPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PEsgSSAoYSkgKGIpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PFMoUyhLKFMpKUspKEkpPDxzdGQ6OmVuZGw7IC8vQnVnCUV4cGVjdDrOu3h5LngoeCB5KQoJLy9zdGQ6OmNvdXQ8PFMgSSBJKFMgSSBJKTw8c3RkOjplbmRsOyAtLSDjgYrjgarjgZjjgb/jga7jgqLjg6wg44Kz44Oz44OR44Kk44Or44Ko44Op44O8CglzdGQ6OmNvdXQ8PHN0ZDo6ZW5kbDsKCQoJLy9DaHVyY2gg5pWw5YCk44Gn5Ye65Yqb44GZ44KL44KI44GG44Gr44Gq44Gj44Gm44Gv44GE44KLCglzdGQ6OmNvdXQ8PENodXJjaDw1Pjo6dmFsdWU8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8U3VjYyhDaHVyY2g8NT46OnZhbHVlKTw8c3RkOjplbmRsOwoJc3RkOjpjb3V0PDxQcmV2KENodXJjaDw1Pjo6dmFsdWUpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PEFkZChDaHVyY2g8NT46OnZhbHVlKShDaHVyY2g8Mz46OnZhbHVlKTw8c3RkOjplbmRsOwoJc3RkOjpjb3V0PDxNdWwoQ2h1cmNoPDU+Ojp2YWx1ZSkoQ2h1cmNoPDM+Ojp2YWx1ZSk8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8c3RkOjplbmRsOwoKCS8vTG9naWMg5Ye65Yqb44Gv44Gd44Gu44G+44G+CglzdGQ6OmNvdXQ8PFRydWU8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8RmFsc2U8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8QW5kKFRydWUpKFRydWUpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PEFuZChUcnVlKShGYWxzZSk8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8T3IoRmFsc2UpKFRydWUpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PE9yKEZhbHNlKShGYWxzZSk8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8Tm90KFRydWUpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PE5vdChGYWxzZSk8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8SWYoVHJ1ZSkoQ2h1cmNoPDU+Ojp2YWx1ZSkoQ2h1cmNoPDM+Ojp2YWx1ZSk8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8SWYoRmFsc2UpKENodXJjaDw1Pjo6dmFsdWUpKENodXJjaDwzPjo6dmFsdWUpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PElmKEFuZChGYWxzZSkoVHJ1ZSkpKENodXJjaDw1Pjo6dmFsdWUpKENodXJjaDwzPjo6dmFsdWUpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PHN0ZDo6ZW5kbDsKCQoJLy9Db25zLExpc3Qg5Ye65Yqb44Gv44Gd44Gu44G+44G+CglzdGQ6OmNvdXQ8PENvbnMoYSkoYik8PHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dDw8Q2FyKENvbnMoYSkoYikpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PENkcihDb25zKGEpKGIpKTw8c3RkOjplbmRsOwoJYXV0byB0Yz1Db25zKENvbnMoYSkoYikpKENvbnMoYykoZCkpOwoJc3RkOjpjb3V0PDx0Yzw8c3RkOjplbmRsOwoJc3RkOjpjb3V0PDxDYXIodGMpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PENkcihDYXIodGMpKTw8c3RkOjplbmRsOwoJYXV0byBsdD1Db25zKGEpKENvbnMoYikoQ29ucyhjKShGYWxzZSkpKTsKCXN0ZDo6Y291dDw8Q2FyKGx0KTw8c3RkOjplbmRsOwoJc3RkOjpjb3V0PDxDZHIobHQpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PENkcihDZHIoQ2RyKGx0KSkpPDxzdGQ6OmVuZGw7CglzdGQ6OmNvdXQ8PHN0ZDo6ZW5kbDsKfQo=