Created
February 18, 2012 13:45
-
-
Save ddk50/1859316 to your computer and use it in GitHub Desktop.
Bayse統計をつかった統計的デバッグ支援ツール
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Makefile.in b/Makefile.in | |
index 6b12187..9a6e1b8 100644 | |
--- a/Makefile.in | |
+++ b/Makefile.in | |
@@ -59,7 +59,7 @@ CPPFLAGS = @CPPFLAGS@ $(INCFLAGS) | |
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@ | |
EXTLDFLAGS = | |
XLDFLAGS = @XLDFLAGS@ $(EXTLDFLAGS) | |
-EXTLIBS = | |
+EXTLIBS = -lgsl -lgslcblas | |
LIBS = @LIBS@ $(EXTLIBS) | |
MISSING = @LIBOBJS@ @ALLOCA@ | |
LDSHARED = @LIBRUBY_LDSHARED@ | |
diff --git a/eval.c b/eval.c | |
index ddbe31a..ae6c0ea 100644 | |
--- a/eval.c | |
+++ b/eval.c | |
@@ -1174,6 +1174,8 @@ rb_f_method_name(void) | |
} | |
} | |
+void ruby_bayse_define_class(void); | |
+ | |
void | |
Init_eval(void) | |
{ | |
@@ -1213,3 +1215,121 @@ Init_eval(void) | |
OBJ_TAINT(exception_error); | |
OBJ_FREEZE(exception_error); | |
} | |
+ | |
+VALUE bayse_hash_sfn_to_ler; | |
+VALUE cBayse; | |
+ | |
+#include <gsl/gsl_math.h> | |
+#include <gsl/gsl_sf.h> | |
+#include <gsl/gsl_rng.h> | |
+#include <gsl/gsl_randist.h> | |
+ | |
+double | |
+kl_divergence(double a, double b, | |
+ double c, double d) | |
+{ | |
+ double val = gsl_sf_beta(a, b) / gsl_sf_beta(c, d); | |
+ double ret = | |
+ log(val) + ((c - a) * (gsl_sf_psi_int(c) - gsl_sf_psi_int(c + d))) | |
+ + ((d - b) * (gsl_sf_psi_int(d) - gsl_sf_psi_int(c + d))); | |
+ return ret; | |
+} | |
+ | |
+VALUE | |
+bayse_func_m_kl_divergence(VALUE self, | |
+ VALUE a, | |
+ VALUE b, | |
+ VALUE c, | |
+ VALUE d) | |
+{ | |
+ double ret; | |
+ ret = kl_divergence(NUM2DBL(a), NUM2DBL(b), NUM2DBL(c), NUM2DBL(d)); | |
+ return DBL2NUM(ret); | |
+} | |
+ | |
+VALUE | |
+bayse_func_m_results(VALUE self) | |
+{ | |
+ return bayse_hash_sfn_to_ler; | |
+} | |
+ | |
+VALUE | |
+bayse_func_m_clearlog(VALUE self) | |
+{ | |
+ bayse_hash_sfn_to_ler = Qnil; | |
+ bayse_hash_sfn_to_ler = rb_hash_new(); | |
+ rb_gc_register_mark_object(bayse_hash_sfn_to_ler); | |
+} | |
+ | |
+VALUE | |
+bayse_func_m_start_logging(VALUE self) | |
+{ | |
+ ID prof_id = 0; | |
+ prof_id = rb_intern("BayseProf"); | |
+} | |
+ | |
+VALUE | |
+bayse_func_m_stop_logging(VALUE self) | |
+{ | |
+ ID prof_id = 0; | |
+ prof_id = rb_intern("BayseProf"); | |
+} | |
+ | |
+/* | |
+ a = Bayse.results | |
+ a.each do |bayse| | |
+ # do something | |
+ end | |
+*/ | |
+ | |
+void | |
+Init_Bayse(void) | |
+{ | |
+ bayse_hash_sfn_to_ler = rb_hash_new(); | |
+ rb_gc_register_mark_object(bayse_hash_sfn_to_ler); | |
+ | |
+ cBayse = rb_define_class("Bayse", rb_cObject); | |
+ | |
+ rb_define_singleton_method(cBayse, "start", bayse_func_m_start_logging, 0); | |
+ rb_define_singleton_method(cBayse, "stop", bayse_func_m_stop_logging, 0); | |
+ rb_define_singleton_method(cBayse, "results", bayse_func_m_results, 0); | |
+ rb_define_singleton_method(cBayse, "clearlog", bayse_func_m_clearlog, 0); | |
+ rb_define_singleton_method(cBayse, "kldivergence", bayse_func_m_kl_divergence, 4); | |
+} | |
+ | |
+/* kazushi addition */ | |
+VALUE | |
+ruby_logging_branch(int unless, rb_control_frame_t *reg_cfp) | |
+{ | |
+ static ID prof_id = 0; | |
+ VALUE sfn_to_ler, conds, ret; | |
+ | |
+ prof_id = rb_intern("BayseProf"); | |
+ | |
+ /* rb_const_defは遅いhashを引いている */ | |
+ /* 例えば:ProfileをONにすると、定義されているbranchunlessを全部俺のブランチアクセスバイトコードに変える */ | |
+ /* 2種類ある:すでに生成されているバイトコードを書き換える方法と、これから生成されるやるも書き換える。 */ | |
+ | |
+ if (rb_const_defined(rb_cObject, prof_id) == Qfalse || | |
+ rb_const_get(rb_cObject, prof_id) == Qfalse) { | |
+ return; | |
+ } else { | |
+ sfn_to_ler = rb_hash_lookup(bayse_hash_sfn_to_ler, reg_cfp->iseq->filename); | |
+ if (sfn_to_ler == Qnil) { | |
+ sfn_to_ler = rb_hash_new(); | |
+ rb_gc_register_mark_object(sfn_to_ler); | |
+ rb_hash_aset(bayse_hash_sfn_to_ler, reg_cfp->iseq->filename, sfn_to_ler); | |
+ } | |
+ | |
+ conds = rb_hash_lookup(sfn_to_ler, LONG2FIX(rb_vm_get_sourceline(reg_cfp))); | |
+ if (conds == Qnil) { | |
+ conds = rb_ary_new(); | |
+ rb_gc_register_mark_object(conds); | |
+ rb_hash_aset(sfn_to_ler, LONG2FIX(rb_vm_get_sourceline(reg_cfp)), conds); | |
+ } | |
+ | |
+ ret = unless ? INT2FIX(0) : INT2FIX(1); | |
+ rb_ary_push(conds, ret); | |
+ } | |
+} | |
+ | |
diff --git a/inits.c b/inits.c | |
index 73b9eb4..bf81e6d 100644 | |
--- a/inits.c | |
+++ b/inits.c | |
@@ -60,5 +60,6 @@ rb_call_inits(void) | |
CALL(Rational); | |
CALL(Complex); | |
CALL(version); | |
+ CALL(Bayse); | |
} | |
#undef CALL | |
diff --git a/insns.def b/insns.def | |
index 2b4c3db..87149eb 100644 | |
--- a/insns.def | |
+++ b/insns.def | |
@@ -1164,9 +1164,12 @@ branchif | |
() | |
{ | |
if (RTEST(val)) { | |
+ ruby_logging_branch(0, GET_CFP()); | |
RUBY_VM_CHECK_INTS(); | |
JUMP(dst); | |
- } | |
+ } else { | |
+ ruby_logging_branch(1, GET_CFP()); | |
+ } | |
} | |
/** | |
@@ -1180,9 +1183,12 @@ branchunless | |
(VALUE val) | |
() | |
{ | |
- if (!RTEST(val)) { | |
+ if (!RTEST(val)) { | |
+ ruby_logging_branch(1, GET_CFP()); | |
RUBY_VM_CHECK_INTS(); | |
JUMP(dst); | |
+ } else { | |
+ ruby_logging_branch(0, GET_CFP()); | |
} | |
} | |
diff --git a/vm_core.h b/vm_core.h | |
index d44bd25..ba11a5d 100644 | |
--- a/vm_core.h | |
+++ b/vm_core.h | |
@@ -749,6 +749,9 @@ extern VALUE rb_get_coverages(void); | |
extern void rb_set_coverages(VALUE); | |
extern void rb_reset_coverages(void); | |
+extern VALUE ruby_logging_branch(int unless, | |
+ rb_control_frame_t *reg_cfp); | |
+ | |
#if defined __GNUC__ && __GNUC__ >= 4 | |
#pragma GCC visibility pop | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment