2009年2月22日日曜日

swig 経過

 とりあえず、現在は、こんな感じ…。BOOST_PP_IF( BOOST_PP_EQUAL( ... などとやっていたが、さすがにこれは、やり過ぎでやめた。boost random の引数等が違っていて、さすがにこれは等価には扱いきれなかった。欲を言えば、seed_type とか seed_arg_count とかを定義していて欲しかったかも?

namespace {
char copyright[] =
"";
}

#include <iostream>
#include <typeinfo>
#include <fstream>
#include <boost/preprocessor.hpp>
#include <boost/random.hpp>

#define RANDOM_TYPE_COUNT 16
#define RANDOM_TYPE_ARRAY ( RANDOM_TYPE_COUNT, ( \
minstd_rand, \
rand48, \
ecuyer1988, \
kreutzer1986, \
hellekalek1995, \
mt11213b, \
mt19937, \
lagged_fibonacci607, \
lagged_fibonacci1279, \
lagged_fibonacci2281, \
lagged_fibonacci3217, \
lagged_fibonacci4423, \
lagged_fibonacci9689, \
lagged_fibonacci19937, \
lagged_fibonacci23209, \
lagged_fibonacci44497 \
) )

#define NTH_ecuyer1988 2
#define NTH_lagged_fibonacci607 7

#define INC_OP( r, i ) BOOST_PP_INC(i)
#define PRED( r, i ) BOOST_PP_LESS(i,RANDOM_TYPE_COUNT)

#define NEXT_LINE ofs << "\n";

#define ALGO_CLASS_NAME( x ) BOOST_PP_CAT( "algo_", BOOST_PP_STRINGIZE(x) )

// for random_def.hpp
void print_type( std::ostream& os, const char* class_name, size_t class_size ) {
os << "struct " << class_name << " {" << std::endl;
os << " char pos[" << class_size << "];" << std::endl;
os << "};" << std::endl;
}
#define PRINT_TYPE_X( x ) { \
print_type( ofs, BOOST_PP_STRINGIZE(x), sizeof(x) ); \
NEXT_LINE \
print_type( ofs, BOOST_PP_CAT("valiate_generator_", BOOST_PP_STRINGIZE(x)), sizeof(variate_generator<x,uniform_real<> >) ); \
NEXT_LINE \
}
#define PRINT_TYPE( r, i ) PRINT_TYPE_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY) )

// for random_retype.hpp
void print_retype( std::ostream& os, const char* base_name ) {
os << "typedef variate_generator< " << base_name << ", uniform_real<> > ";
os << "variate_generator_" << base_name << ";" << std::endl;
}
#define PRINT_RETYPE_X( x ) { \
print_retype( ofs, BOOST_PP_STRINGIZE(x) ); \
NEXT_LINE \
}
#define PRINT_RETYPE( r, i ) PRINT_RETYPE_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY) )


// for random.hpp
void print_class( std::ostream& os, const char* class_name, const char* result_name, int array_number ) {
os << "class algo_" << class_name << " {" << std::endl;
os << "private:" << std::endl;
os << " " << class_name << " generator_;" << std::endl;
os << " variate_generator_" << class_name << " variator_;" << std::endl;
os << "public:" << std::endl;
os << " algo_" << class_name << "( ";
if( array_number == NTH_ecuyer1988 ) {
os << result_name << " seed1, " << result_name << " seed2);" << std::endl;
} else if( array_number >= NTH_lagged_fibonacci607 ) {
os << ");" << std::endl;
} else {
os << result_name << " seed);" << std::endl;
}
os << " double random();" << std::endl;
os << " " << result_name << " numeric_random();" << std::endl;
os << "};" << std::endl;
}
#define PRINT_CLASS_X( x, i ) { \
print_class( ofs, BOOST_PP_STRINGIZE(x), typeid( x::result_type ).name(), i ); \
NEXT_LINE \
}
#define PRINT_CLASS( r, i ) PRINT_CLASS_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY), i )

// for random.cpp
void print_implement( std::ostream& os, const char* class_name, const char* result_name, int array_number ) {
os << "///////////////////////////////////////" << std::endl;
os << "// " << class_name << std::endl;
os << "///////////////////////////////////////" << std::endl;
os << class_name << "::" << class_name << "(";
if( array_number == NTH_ecuyer1988 ) {
os << result_name << " seed1, " << result_name << " seed2) :" << std::endl;
os << " generator_(seed1,seed2)," << std::endl;
} else if( array_number >= NTH_lagged_fibonacci607 ) {
os << ") :" << std::endl;
os << " generator_()," << std::endl;
} else {
os << result_name << " seed) :" << std::endl;
os << " generator_(seed)," << std::endl;
}
os << " variator_(generator_,uniform_real<>())" << std::endl;
os << "{}" << std::endl;
os << std::endl;
os << "double " << class_name << "::random() { return variator_(); }" << std::endl;
os << result_name << " " << class_name << "::numeric_random() { return generator_(); }" << std::endl;
os << std::endl;
}
#define PRINT_IMPLEMENT_X( x, i ) { \
print_implement( ofs, ALGO_CLASS_NAME(x), typeid( x::result_type ).name(), i ); \
}
#define PRINT_IMPLEMENT( r, i ) PRINT_IMPLEMENT_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY), i )

// for random.i
void print_ignore( std::ostream& os, const char* class_name ) {
os << "%ignore " << class_name << "::generator_;" << std::endl;
os << "%ignore " << class_name << "::variator_;" << std::endl;
}
#define PRINT_IGNORE_X( x ) print_ignore( ofs, ALGO_CLASS_NAME(x) );
#define PRINT_IGNORE( r, i ) PRINT_IGNORE_X( BOOST_PP_ARRAY_ELEM(i,RANDOM_TYPE_ARRAY) )

using namespace boost;

void print_random_def() {
std::ofstream ofs( "random_def.hpp" );

ofs << "// random_def.hpp\n";
NEXT_LINE
BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_TYPE )
NEXT_LINE
print_type( ofs, "uniform_base", sizeof(uniform_real<>) );
}

void print_random_retype() {
std::ofstream ofs( "random_retype.hpp" );

ofs << "#include <boost/random.hpp>\n";
ofs << "using namespace boost;\n";
NEXT_LINE
BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_RETYPE )
NEXT_LINE
ofs << "typedef uniform_real<> uniform_base;" << std::endl;

}

void print_random_hpp() {
std::ofstream ofs( "random.hpp" );

ofs << "#ifdef SWIG\n";
ofs << "#include \"random_def.hpp\"\n";
ofs << "#else\n";
ofs << "#include \"random_retype.hpp\"\n";
ofs << "#endif\n";
NEXT_LINE

BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_CLASS )
}

void print_random_cpp() {
std::ofstream ofs( "random.cpp" );

ofs << "#include \"random.hpp\"\n";
NEXT_LINE
BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_IMPLEMENT )
}

void print_random_i() {
std::ofstream ofs( "random.i" );

ofs << "/* File : random.i */\n";
NEXT_LINE
ofs << "%module boost_random\n";
NEXT_LINE
ofs << "%{\n";
ofs << "#include \"random.hpp\"\n";
ofs << "%}\n";
NEXT_LINE
BOOST_PP_FOR( 0, PRED, INC_OP, PRINT_IGNORE )
NEXT_LINE
ofs << "%ignore uniform_base;\n";
NEXT_LINE
ofs << "/* Let's just grab the original header file here */\n";
ofs << "%include \"random.hpp\"\n";
}

int main() {

print_random_def();
print_random_retype();
print_random_hpp();
print_random_cpp();
print_random_i();

return 0;
}

0 件のコメント: