1 #include "reductions.h"
2 
3 const int autoconstant = 524267083;
4 
5 struct autolink {
6   uint32_t d; // degree of the polynomial
7   uint32_t stride_shift;
8 };
9 
10 template <bool is_learn>
predict_or_learn(autolink & b,LEARNER::base_learner & base,example & ec)11 void predict_or_learn(autolink& b, LEARNER::base_learner& base, example& ec)
12 {
13   base.predict(ec);
14   float base_pred = ec.pred.scalar;
15   // add features of label
16   ec.indices.push_back(autolink_namespace);
17   float sum_sq = 0;
18   for (size_t i = 0; i < b.d; i++)
19     if (base_pred != 0.)
20       {
21 	feature f = { base_pred, (uint32_t) (autoconstant + (i << b.stride_shift)) };
22 	ec.atomics[autolink_namespace].push_back(f);
23 	sum_sq += base_pred*base_pred;
24 	base_pred *= ec.pred.scalar;
25       }
26   ec.total_sum_feat_sq += sum_sq;
27 
28   if (is_learn)
29     base.learn(ec);
30   else
31     base.predict(ec);
32 
33   ec.atomics[autolink_namespace].erase();
34   ec.indices.pop();
35   ec.total_sum_feat_sq -= sum_sq;
36 }
37 
autolink_setup(vw & all)38 LEARNER::base_learner* autolink_setup(vw& all)
39 {
40   if (missing_option<size_t, true>(all, "autolink", "create link function with polynomial d"))
41     return NULL;
42 
43   autolink& data = calloc_or_die<autolink>();
44   data.d = (uint32_t)all.vm["autolink"].as<size_t>();
45   data.stride_shift = all.reg.stride_shift;
46 
47   LEARNER::learner<autolink>& ret =
48     init_learner(&data, setup_base(all), predict_or_learn<true>, predict_or_learn<false>);
49 
50   return make_base(ret);
51 }
52