"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "ling_class/EST_relation_compare.cc" between
speech_tools-2.4-release.tar.gz and speech_tools-2.5.0-release.tar.gz

About: The speech_tools - Edinburgh Speech Tools Library (used by the Festival Speech Synthesis System).

EST_relation_compare.cc  (speech_tools-2.4-release):EST_relation_compare.cc  (speech_tools-2.5.0-release)
skipping to change at line 62 skipping to change at line 62
int close_enough(EST_Item &a, EST_Item &b) int close_enough(EST_Item &a, EST_Item &b)
{ {
return ((start(&b) < a.F("end")) && (start(&a) < b.F("end"))); return ((start(&b) < a.F("end")) && (start(&a) < b.F("end")));
} }
// WATCH - this uses what should be private access to Keyval class. // WATCH - this uses what should be private access to Keyval class.
void monotonic_match(EST_II_KVL &a, EST_II_KVL &b) void monotonic_match(EST_II_KVL &a, EST_II_KVL &b)
{ {
EST_Litem *ptr; EST_Litem *ptr;
for (ptr = a.list.head(); ptr != 0; ptr= ptr->next()) for (ptr = a.list.head(); ptr != 0; ptr = ptr->next())
{ {
if (a.val(ptr) == -1) if (a.val(ptr) == -1)
continue; continue;
if (b.val(a.val(ptr)) == a.key(ptr)) if (b.val(a.val(ptr)) == a.key(ptr))
// cout << "ok\n"; // cout << "ok\n";
continue; continue;
else else
a.change_key(ptr, -1); a.change_key(ptr, -1);
} }
for (ptr = b.list.head(); ptr != 0; ptr= ptr->next()) for (ptr = b.list.head(); ptr != 0; ptr = ptr->next())
{ {
if (b.val(ptr) == -1) if (b.val(ptr) == -1)
continue; continue;
if (a.val(b.val(ptr)) == b.key(ptr)) if (a.val(b.val(ptr)) == b.key(ptr))
// cout << "ok\n"; // cout << "ok\n";
continue; continue;
else else
a.change_key(ptr, -1); a.change_key(ptr, -1);
} }
} }
skipping to change at line 94 skipping to change at line 94
void function_match(EST_II_KVL &u, EST_Relation &a, EST_Relation &b) void function_match(EST_II_KVL &u, EST_Relation &a, EST_Relation &b)
{ {
(void)u; (void)u;
(void)a; (void)a;
(void)b; (void)b;
#if 0 #if 0
EST_Item *a_ptr; EST_Item *a_ptr;
EST_Litem *i_ptr; EST_Litem *i_ptr;
int i; int i;
for (i = 0, a_ptr = a.head(); a_ptr != 0; a_ptr = a_ptr->next(), ++i) for (i = 0, a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr), ++i)
{ {
if (a_ptr->f("pos")==1) if (a_ptr->f("pos")==1)
{ {
u.add_item(a_ptr->addr(), -1); u.add_item(a_ptr->addr(), -1);
for (i_ptr = a_ptr->link(b.stream_name())->head(); i_ptr != 0; for (i_ptr = a_ptr->link(b.stream_name())->head(); i_ptr != 0;
i_ptr = i_ptr->next()) i_ptr = i_ptr->next())
u.change_val(a_ptr->addr(), a_ptr->link(b.stream_name())->item(i_ ptr)); u.change_val(a_ptr->addr(), a_ptr->link(b.stream_name())->item(i_ ptr));
} }
} }
#endif #endif
} }
void relation_match(EST_Relation &a, EST_Relation &b) void relation_match(EST_Relation &a, EST_Relation &b)
{ {
EST_Item *a_ptr, *b_ptr; EST_Item *a_ptr, *b_ptr;
for (a_ptr = a.head(); a_ptr != 0; a_ptr = a_ptr->next()) for (a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr))
if (a_ptr->f("pos")==1) if (a_ptr->f("pos")==1)
for (b_ptr = b.head(); b_ptr != 0; b_ptr = b_ptr->next()) for (b_ptr = b.head(); b_ptr != 0; b_ptr = inext(b_ptr))
{ {
if ((b_ptr->f("pos")==1) if ((b_ptr->f("pos")==1)
&&(close_enough(*a_ptr, *b_ptr))) &&(close_enough(*a_ptr, *b_ptr)))
{ {
// cout << "linked\n"; // cout << "linked\n";
#if 0 #if 0
link(*a_ptr, *b_ptr); link(*a_ptr, *b_ptr);
#endif #endif
} }
} }
skipping to change at line 176 skipping to change at line 176
cout << insdel(uref); cout << insdel(uref);
cout << "Insertions: "; cout << "Insertions: ";
cout.width(10); cout.width(10);
cout<< insdel(utest) << endl; cout<< insdel(utest) << endl;
} }
EST_Item *nthpos(EST_Relation &a, int n) EST_Item *nthpos(EST_Relation &a, int n)
{ {
EST_Item *a_ptr; EST_Item *a_ptr;
int i = 0; int i = 0;
for (a_ptr = a.head(); a_ptr != 0; a_ptr = a_ptr->next()) for (a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr))
if (a_ptr->f("pos") == 1) if (a_ptr->f("pos") == 1)
{ {
if (n == i) if (n == i)
return a_ptr; return a_ptr;
++i; ++i;
} }
return 0; return 0;
} }
// measures amount of total overlap between segments // measures amount of total overlap between segments
skipping to change at line 360 skipping to change at line 360
void threshold_labels(EST_Relation &reflab, float t) void threshold_labels(EST_Relation &reflab, float t)
{ {
(void)reflab; (void)reflab;
(void)t; (void)t;
#if 0 #if 0
EST_Item *r_ptr; EST_Item *r_ptr;
float score=0.0; float score=0.0;
int a; int a;
for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = r_ptr->next()) for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
if (r_ptr->f("pos")==1) if (r_ptr->f("pos")==1)
{ {
// REORG - temp comment // REORG - temp comment
// score = atof(r_ptr->fields()); // score = atof(r_ptr->fields());
cout << "score is" << score << endl; cout << "score is" << score << endl;
a = r_ptr->rlink("blank").first(); a = r_ptr->rlink("blank").first();
cout << "score is" << score << " address: " << a << endl; cout << "score is" << score << " address: " << a << endl;
if (score > t) if (score > t)
cout << "delete\n"; cout << "delete\n";
skipping to change at line 395 skipping to change at line 395
{ {
(void)reflab; (void)reflab;
#if 0 #if 0
EST_Item *r_ptr, *s_ptr, *t_ptr;; EST_Item *r_ptr, *s_ptr, *t_ptr;;
EST_Litem *p; EST_Litem *p;
int a, pos, i; int a, pos, i;
EST_TList<int> la; EST_TList<int> la;
float *score; float *score;
score = new float[reflab.length()]; score = new float[reflab.length()];
for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = r_ptr->next()) for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
if (r_ptr->f("pos")==1) if (r_ptr->f("pos")==1)
{ {
la.clear(); // clear list and add address of current ref label la.clear(); // clear list and add address of current ref label
la.append(r_ptr->addr()); la.append(r_ptr->addr());
a = r_ptr->rlink("test").first(); a = r_ptr->rlink("test").first();
cout << a << endl; cout << a << endl;
// check remainer of ref labels and add any that have same // check remainer of ref labels and add any that have same
// relations address as r_ptr. // relations address as r_ptr.
for (s_ptr = r_ptr->next(); s_ptr != 0; s_ptr = s_ptr->next()) for (s_ptr = inext(r_ptr); s_ptr != 0; s_ptr = inext(s_ptr))
if (s_ptr->f("pos")==1) if (s_ptr->f("pos")==1)
if (s_ptr->rlink("test").first() == a) if (s_ptr->rlink("test").first() == a)
la.append(s_ptr->addr()); la.append(s_ptr->addr());
cout << "la: " << la; cout << "la: " << la;
if (la.length() > 1) // true if the are multiple relations if (la.length() > 1) // true if the are multiple relations
{ {
// find scores of all relevant labels // find scores of all relevant labels
for (i = 0, p = la.head(); p!= 0; p = p->next(), ++i) for (i = 0, p = la.head(); p!= 0; p = p->next(), ++i)
{ {
skipping to change at line 449 skipping to change at line 449
calculating the distance from each label in the test set to each label calculating the distance from each label in the test set to each label
in the reference set. The lowest score for each reference is then in the reference set. The lowest score for each reference is then
recorded. A test is carried out to make sure that no two reference recorded. A test is carried out to make sure that no two reference
labels point to the same test label. Then any ref label above a labels point to the same test label. Then any ref label above a
certain distance is classified as incorrect. The numbers of insertions certain distance is classified as incorrect. The numbers of insertions
and deletions are then calculated. */ and deletions are then calculated. */
EST_FMatrix matrix_compare(EST_Relation &reflab, EST_Relation &testlab, int meth od, EST_FMatrix matrix_compare(EST_Relation &reflab, EST_Relation &testlab, int meth od,
float t, int v) float t, int v)
{ {
int i, j, pos; int i, j;
int num_ref, num_test; int num_ref, num_test;
EST_Item *r_ptr, *t_ptr; EST_Item *r_ptr, *t_ptr;
EST_String fns; EST_String fns;
(void)v; (void)v;
num_ref = num_test = 0; num_ref = num_test = 0;
// calculate size of matrix, based on *significant* labels // calculate size of matrix, based on *significant* labels
for (r_ptr = testlab.head(); r_ptr != 0; r_ptr = r_ptr->next()) for (r_ptr = testlab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
if (r_ptr->f("pos")==1) if (r_ptr->f("pos")==1)
++num_test; ++num_test;
for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = r_ptr->next()) for (r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
if (r_ptr->f("pos")==1) if (r_ptr->f("pos")==1)
++num_ref; ++num_ref;
EST_FMatrix m(num_test, num_ref); EST_FMatrix m(num_test, num_ref);
if ((m.num_rows() == 0) || (m.num_columns() == 0)) if ((m.num_rows() == 0) || (m.num_columns() == 0))
return m; // nothing to analyse, hence empty matrix return m; // nothing to analyse, hence empty matrix
// fill matrix values by comparing each test with each reference // fill matrix values by comparing each test with each reference
// reference is columns, test is rows // reference is columns, test is rows
for (i = 0, t_ptr = testlab.head(); t_ptr != 0; t_ptr = t_ptr->next()) for (i = 0, t_ptr = testlab.head(); t_ptr != 0; t_ptr = inext(t_ptr))
if (t_ptr->f("pos")==1) if (t_ptr->f("pos")==1)
{ {
for (j = 0, r_ptr = reflab.head(); r_ptr != 0; r_ptr = r_ptr->next()) for (j = 0, r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
if (r_ptr->f("pos")==1) if (r_ptr->f("pos")==1)
{ {
if (method == 1) if (method == 1)
m(i, j) = label_distance1(*r_ptr, *t_ptr); m(i, j) = label_distance1(*r_ptr, *t_ptr);
else if (method == 2) else if (method == 2)
m(i, j) = label_distance2(*r_ptr, *t_ptr); m(i, j) = label_distance2(*r_ptr, *t_ptr);
else else
cerr << "Unknown comparision method" << method << endl; cerr << "Unknown comparision method" << method << endl;
++j; ++j;
} }
++i; ++i;
} }
// cout << "orig M\n"; // cout << "orig M\n";
// print_matrix_scores(reflab, testlab, m); // print_matrix_scores(reflab, testlab, m);
minimise_matrix_by_column(m); minimise_matrix_by_column(m);
minimise_matrix_by_row(m); minimise_matrix_by_row(m);
matrix_ceiling(m, t); matrix_ceiling(m, t);
#if 0
/* This doesn't do anything */
// for each ref label, find closest matching test label. // for each ref label, find closest matching test label.
for (j = 0, r_ptr = reflab.head(); r_ptr != 0; r_ptr = r_ptr->next()) for (j = 0, r_ptr = reflab.head(); r_ptr != 0; r_ptr = inext(r_ptr))
{ {
if (r_ptr->f("pos")==1) if (r_ptr->f("pos")==1)
{ {
pos = lowest_pos(m, j); pos = lowest_pos(m, j);
// REORG - temp comment // REORG - temp comment
// r_ptr->set_field_names(r_ptr->fields() +ftoString(m(pos, j))); // r_ptr->set_field_names(r_ptr->fields() +ftoString(m(pos, j)));
++j; ++j;
} }
} }
#endif
return m; return m;
} }
void multiple_matrix_compare(EST_RelationList &rlist, EST_RelationList void multiple_matrix_compare(EST_RelationList &rlist, EST_RelationList
&tlist, EST_FMatrix &m, EST_String rpos, &tlist, EST_FMatrix &m, EST_String rpos,
EST_String tpos, int method, float t, int v) EST_String tpos, int method, float t, int v)
{ {
EST_Litem *pr, *pt; EST_Litem *pr, *pt;
EST_String filename; EST_String filename;
EST_Relation reflab, testlab; EST_Relation reflab, testlab;
skipping to change at line 590 skipping to change at line 593
} }
void error_location(EST_Relation &e, EST_FMatrix &m, int ref) void error_location(EST_Relation &e, EST_FMatrix &m, int ref)
{ {
int i; int i;
EST_Item *s; EST_Item *s;
// reference // reference
if (ref) if (ref)
{ {
for (i = 0, s = e.head(); s; s = s->next()) for (i = 0, s = e.head(); s; s = inext(s))
if ((int)s->f("pos")) if ((int)s->f("pos"))
{ {
if (column_hit(m, i) >= 0) if (column_hit(m, i) >= 0)
s->set("hit", 1); s->set("hit", 1);
else else
s->set("hit", 0); s->set("hit", 0);
++i; ++i;
} }
} }
else else
for (i = 0, s = e.head(); s; s = s->next()) for (i = 0, s = e.head(); s; s = inext(s))
if ((int)s->f("pos")) if ((int)s->f("pos"))
{ {
if (row_hit(m, i) >= 0) if (row_hit(m, i) >= 0)
s->set("hit", 1); s->set("hit", 1);
else else
s->set("hit", 0); s->set("hit", 0);
++i; ++i;
} }
} }
skipping to change at line 661 skipping to change at line 664
void reassign_links(EST_Relation &a, EST_Relation &b, EST_II_KVL &ua, EST_II_KVL &ub) void reassign_links(EST_Relation &a, EST_Relation &b, EST_II_KVL &ua, EST_II_KVL &ub)
{ {
(void)a; (void)a;
(void)b; (void)b;
(void)ua; (void)ua;
(void)ub; (void)ub;
#if 0 #if 0
EST_Item *a_ptr, *b_ptr; EST_Item *a_ptr, *b_ptr;
for (a_ptr = a.head(); a_ptr != 0; a_ptr = a_ptr->next()) for (a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr))
{ {
a_ptr->link(b.stream_name())->clear(); a_ptr->link(b.stream_name())->clear();
if ((a_ptr->f("pos")==1) && (ua.val(a_ptr->addr()) != -1)) if ((a_ptr->f("pos")==1) && (ua.val(a_ptr->addr()) != -1))
a_ptr->make_link(b.stream_name(), ua.val(a_ptr->addr())); a_ptr->make_link(b.stream_name(), ua.val(a_ptr->addr()));
} }
for (b_ptr = b.head(); b_ptr != 0; b_ptr = b_ptr->next()) for (b_ptr = b.head(); b_ptr != 0; b_ptr = inext(b_ptr))
{ {
b_ptr->link(a.stream_name())->clear(); b_ptr->link(a.stream_name())->clear();
if ((b_ptr->f("pos")==1) && (ub.val(b_ptr->addr()) != -1)) if ((b_ptr->f("pos")==1) && (ub.val(b_ptr->addr()) != -1))
b_ptr->make_link(a.stream_name(), ub.val(b_ptr->addr())); b_ptr->make_link(a.stream_name(), ub.val(b_ptr->addr()));
} }
#endif #endif
} }
void reassign_links(EST_Relation &a, EST_II_KVL &u, EST_String stream_type) void reassign_links(EST_Relation &a, EST_II_KVL &u, EST_String stream_type)
{ {
(void)a; (void)a;
(void)u; (void)u;
(void)stream_type; (void)stream_type;
#if 0 #if 0
EST_Item *a_ptr; EST_Item *a_ptr;
for (a_ptr = a.head(); a_ptr != 0; a_ptr = a_ptr->next()) for (a_ptr = a.head(); a_ptr != 0; a_ptr = inext(a_ptr))
{ {
a_ptr->link(stream_type)->clear(); a_ptr->link(stream_type)->clear();
if ((a_ptr->f("pos")==1) && (u.val(a_ptr->addr()) != -1)) if ((a_ptr->f("pos")==1) && (u.val(a_ptr->addr()) != -1))
a_ptr->make_link(stream_type, u.val(a_ptr->addr())); a_ptr->make_link(stream_type, u.val(a_ptr->addr()));
} }
#endif #endif
} }
int commutate(EST_Item *a_ptr, EST_II_KVL &f1, EST_II_KVL &f2, int commutate(EST_Item *a_ptr, EST_II_KVL &f1, EST_II_KVL &f2,
EST_II_KVL &lref, EST_II_KVL &ltest) EST_II_KVL &lref, EST_II_KVL &ltest)
skipping to change at line 775 skipping to change at line 778
cout << "Lref\n" << lref; cout << "Lref\n" << lref;
cout << "Ltest\n" << ltest; cout << "Ltest\n" << ltest;
cout << "f1\n" << f1; cout << "f1\n" << f1;
cout << "f2\n" << f2; cout << "f2\n" << f2;
} }
EST_Item *a_ptr; EST_Item *a_ptr;
int correct, n_ev, n_syl; int correct, n_ev, n_syl;
correct = n_ev = n_syl = 0; correct = n_ev = n_syl = 0;
for (a_ptr = ref.stream("Event").head(); a_ptr != 0; a_ptr = a_ptr->next()) for (a_ptr = ref.stream("Event").head(); a_ptr != 0; a_ptr = inext(a_ptr))
if (a_ptr->f("pos")==1) if (a_ptr->f("pos")==1)
{ {
++n_ev; ++n_ev;
if (lref.val(a_ptr->addr()) if (lref.val(a_ptr->addr())
== commutate(a_ptr, f1, f2, lref, ltest)) == commutate(a_ptr, f1, f2, lref, ltest))
++correct; ++correct;
} }
for (a_ptr = ref.stream("Syllable").head();a_ptr != 0; a_ptr = a_ptr->next() ) for (a_ptr = ref.stream("Syllable").head();a_ptr != 0; a_ptr = inext(a_ptr))
if (a_ptr->f("pos")==1) if (a_ptr->f("pos")==1)
++n_syl; ++n_syl;
if (op.present("print_syllable") && op.present("print_total")) if (op.present("print_syllable") && op.present("print_total"))
cout << "Number_of_Syllables: " << n_syl << endl; cout << "Number_of_Syllables: " << n_syl << endl;
if (op.present("print_event") && op.present("print_total")) if (op.present("print_event") && op.present("print_total"))
cout << "Number_of_Events: " << n_ev << endl; cout << "Number_of_Events: " << n_ev << endl;
if (op.present("print_link")) if (op.present("print_link"))
cout << "Correct_links: " << correct <<endl; cout << "Correct_links: " << correct <<endl;
if (op.present("print_derivation")) if (op.present("print_derivation"))
{ {
for (a_ptr = ref.stream("Event").head();a_ptr!= 0; a_ptr = a_ptr->next()) for (a_ptr = ref.stream("Event").head();a_ptr!= 0; a_ptr = inext(a_ptr))
{ {
if (a_ptr->f("pos")==1) if (a_ptr->f("pos")==1)
{ {
cout << "Lr(ei): " << lref.val(a_ptr->addr()) << endl; cout << "Lr(ei): " << lref.val(a_ptr->addr()) << endl;
cout << "f2(ei): " << f2.val(a_ptr->addr()) << endl; cout << "f2(ei): " << f2.val(a_ptr->addr()) << endl;
cout << "Lt(f2(ei)): " << ltest.val(f2.val(a_ptr->addr())) cout << "Lt(f2(ei)): " << ltest.val(f2.val(a_ptr->addr()))
<< endl; << endl;
cout << "f1(Lt(f2(ei))): " cout << "f1(Lt(f2(ei))): "
<< f1.val(ltest.val(f2.val(a_ptr->addr()))) << endl; << f1.val(ltest.val(f2.val(a_ptr->addr()))) << endl;
} }
skipping to change at line 839 skipping to change at line 842
cout.width(10); cout.width(10);
cout<< matrix_insertions(m) << endl; cout<< matrix_insertions(m) << endl;
} }
void print_matrix_scores(EST_Relation &ref, EST_Relation &test, EST_FMatrix &a) void print_matrix_scores(EST_Relation &ref, EST_Relation &test, EST_FMatrix &a)
{ {
int i, j; int i, j;
EST_Item *r_ptr, *t_ptr; EST_Item *r_ptr, *t_ptr;
cout << " "; cout << " ";
for (r_ptr = ref.head(); r_ptr != 0; r_ptr = r_ptr->next()) for (r_ptr = ref.head(); r_ptr != 0; r_ptr = inext(r_ptr))
{ {
if (r_ptr->f("pos")==1) if (r_ptr->f("pos")==1)
{ {
// cout.width(5); // cout.width(5);
// cout.setf(ios::right); // cout.setf(ios::right);
cout << r_ptr->name() << " "; cout << r_ptr->name() << " ";
cout.width(6); cout.width(6);
cout.setf(ios::right); cout.setf(ios::right);
cout<< r_ptr->F("end") << " "; cout<< r_ptr->F("end") << " ";
} }
} }
cout << endl; cout << endl;
for (t_ptr = test.head(), i = 0; i < a.num_rows(); t_ptr = t_ptr->next()) for (t_ptr = test.head(), i = 0; i < a.num_rows(); t_ptr = inext(t_ptr))
{ {
if (t_ptr->f("pos")==1) if (t_ptr->f("pos")==1)
{ {
cout << t_ptr->name() << " "; cout << t_ptr->name() << " ";
for (j = 0; j < a.num_columns(); ++j) for (j = 0; j < a.num_columns(); ++j)
{ {
cout.width(10); cout.width(10);
cout.precision(3); cout.precision(3);
cout.setf(ios::right); cout.setf(ios::right);
cout.setf(ios::fixed, ios::floatfield); cout.setf(ios::fixed, ios::floatfield);
skipping to change at line 933 skipping to change at line 936
} }
} }
*/ */
cout << endl; cout << endl;
} }
void make_hit_and_miss(EST_Relation &a) void make_hit_and_miss(EST_Relation &a)
{ {
EST_Item *s; EST_Item *s;
for (s = a.head(); s; s = s->next()) for (s = a.head(); s; s = inext(s))
{ {
if (s->f("pos") == 0) if (s->f("pos") == 0)
s->set_name("."); s->set_name(".");
else if (s->f("hit") == 1) else if (s->f("hit") == 1)
s->set_name("HIT"); s->set_name("HIT");
else else
s->set_name("MISS"); s->set_name("MISS");
s->features().clear(); s->features().clear();
} }
} }
void pos_only(EST_Relation &lab) void pos_only(EST_Relation &lab)
{ {
EST_Item *a, *n; EST_Item *a, *n;
for (a = lab.head(); a; a = n) for (a = lab.head(); a; a = n)
{ {
n = a->next(); n = inext(a);
if (!a->f_present("pos")) if (!a->f_present("pos"))
lab.remove_item(a); lab.remove_item(a);
} }
} }
// Warning this is bugged - slight misalignments occur. // Warning this is bugged - slight misalignments occur.
void print_aligned_trans(EST_Relation &ref, EST_Relation &test, EST_FMatrix &m) void print_aligned_trans(EST_Relation &ref, EST_Relation &test, EST_FMatrix &m)
{ {
(void)ref; (void)ref;
(void)test; (void)test;
 End of changes. 29 change blocks. 
27 lines changed or deleted 30 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)