From 47e48287057b49645c5bd880f80fa9a2f1a76c6d Mon Sep 17 00:00:00 2001
From: Andre Anjos <andre.anjos@idiap.ch>
Date: Tue, 14 Jan 2014 08:59:24 +0100
Subject: [PATCH] Add linear activation

---
 setup.py                                      |   7 +-
 .../{identity.cpp => identity_activation.cpp} |  25 ++--
 xbob/machine/linear_activation.cpp            | 134 ++++++++++++++++++
 .../{logistic.cpp => logistic_activation.cpp} |  25 ++--
 .../machine/{tanh.cpp => tanh_activation.cpp} |  26 ++--
 5 files changed, 181 insertions(+), 36 deletions(-)
 rename xbob/machine/{identity.cpp => identity_activation.cpp} (82%)
 create mode 100644 xbob/machine/linear_activation.cpp
 rename xbob/machine/{logistic.cpp => logistic_activation.cpp} (82%)
 rename xbob/machine/{tanh.cpp => tanh_activation.cpp} (80%)

diff --git a/setup.py b/setup.py
index 77a3d0e..5cbc90e 100644
--- a/setup.py
+++ b/setup.py
@@ -53,9 +53,10 @@ setup(
       Extension("xbob.machine._library",
         [
           "xbob/machine/activation.cpp",
-          "xbob/machine/identity.cpp",
-          "xbob/machine/tanh.cpp",
-          "xbob/machine/logistic.cpp",
+          "xbob/machine/identity_activation.cpp",
+          "xbob/machine/tanh_activation.cpp",
+          "xbob/machine/logistic_activation.cpp",
+          "xbob/machine/linear_activation.cpp",
           "xbob/machine/main.cpp",
           ],
         packages = packages,
diff --git a/xbob/machine/identity.cpp b/xbob/machine/identity_activation.cpp
similarity index 82%
rename from xbob/machine/identity.cpp
rename to xbob/machine/identity_activation.cpp
index 31ba779..56fa88e 100644
--- a/xbob/machine/identity.cpp
+++ b/xbob/machine/identity_activation.cpp
@@ -7,9 +7,10 @@
 
 #include <xbob.machine/api.h>
 
-PyDoc_STRVAR(s_activationsubtype_str, XBOB_EXT_MODULE_PREFIX ".IdentityActivation");
+PyDoc_STRVAR(s_identityactivation_str,
+    XBOB_EXT_MODULE_PREFIX ".IdentityActivation");
 
-PyDoc_STRVAR(s_activationsubtype_doc,
+PyDoc_STRVAR(s_identityactivation_doc,
 "IdentityActivation() -> new IdentityActivation\n\
 \n\
 Computes :math:`f(z) = z` as activation function.\n\
@@ -22,9 +23,10 @@ typedef struct {
   /* Type-specific fields go here. */
   bob::machine::IdentityActivation* base;
 
-} PyBobMachineActivationSubtypeObject;
+} PyBobMachineIdentityActivationObject;
 
-static int PyBobMachineActivationSubtype_init(PyBobMachineActivationSubtypeObject* self, PyObject* args, PyObject* kwds) {
+static int PyBobMachineIdentityActivation_init
+(PyBobMachineIdentityActivationObject* self, PyObject* args, PyObject* kwds) {
 
   /* Parses input arguments in a single shot */
   static const char* const_kwlist[] = {0};
@@ -39,7 +41,7 @@ static int PyBobMachineActivationSubtype_init(PyBobMachineActivationSubtypeObjec
     PyErr_SetString(PyExc_RuntimeError, ex.what());
   }
   catch (...) {
-    PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_activationsubtype_str);
+    PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_identityactivation_str);
   }
 
   self->parent.base = self->base;
@@ -50,7 +52,8 @@ static int PyBobMachineActivationSubtype_init(PyBobMachineActivationSubtypeObjec
 
 }
 
-static void PyBobMachineActivationSubtype_delete (PyBobMachineActivationSubtypeObject* self) {
+static void PyBobMachineIdentityActivation_delete
+(PyBobMachineIdentityActivationObject* self) {
 
   delete self->base;
   self->parent.base = 0;
@@ -59,13 +62,13 @@ static void PyBobMachineActivationSubtype_delete (PyBobMachineActivationSubtypeO
 
 }
 
-PyTypeObject PyBobMachineActivationSubtype_Type = {
+PyTypeObject PyBobMachineIdentityActivation_Type = {
     PyObject_HEAD_INIT(0)
     0,                                                  /*ob_size*/
     0,                                                  /*tp_name*/
-    sizeof(PyBobMachineActivationSubtypeObject),        /*tp_basicsize*/
+    sizeof(PyBobMachineIdentityActivationObject),       /*tp_basicsize*/
     0,                                                  /*tp_itemsize*/
-    (destructor)PyBobMachineActivationSubtype_delete,   /*tp_dealloc*/
+    (destructor)PyBobMachineIdentityActivation_delete,  /*tp_dealloc*/
     0,                                                  /*tp_print*/
     0,                                                  /*tp_getattr*/
     0,                                                  /*tp_setattr*/
@@ -81,7 +84,7 @@ PyTypeObject PyBobMachineActivationSubtype_Type = {
     0,                                                  /*tp_setattro*/
     0,                                                  /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,           /*tp_flags*/
-    s_activationsubtype_doc,                            /* tp_doc */
+    s_identityactivation_doc,                           /* tp_doc */
     0,		                                              /* tp_traverse */
     0,		                                              /* tp_clear */
     0,                                                  /* tp_richcompare */
@@ -96,7 +99,7 @@ PyTypeObject PyBobMachineActivationSubtype_Type = {
     0,                                                  /* tp_descr_get */
     0,                                                  /* tp_descr_set */
     0,                                                  /* tp_dictoffset */
-    (initproc)PyBobMachineActivationSubtype_init,       /* tp_init */
+    (initproc)PyBobMachineIdentityActivation_init,      /* tp_init */
     0,                                                  /* tp_alloc */
     0,                                                  /* tp_new */
 };
diff --git a/xbob/machine/linear_activation.cpp b/xbob/machine/linear_activation.cpp
new file mode 100644
index 0000000..3c43316
--- /dev/null
+++ b/xbob/machine/linear_activation.cpp
@@ -0,0 +1,134 @@
+/**
+ * @author Andre Anjos <andre.anjos@idiap.ch>
+ * @date Mon 13 Jan 2014 17:25:32 CET
+ *
+ * @brief Implementation of the Linear Activation function
+ */
+
+#include <xbob.machine/api.h>
+
+PyDoc_STRVAR(s_linearactivation_str,
+    XBOB_EXT_MODULE_PREFIX ".LinearActivation");
+
+PyDoc_STRVAR(s_linearactivation_doc,
+"LinearActivation([C=1.0]) -> new LinearActivation\n\
+\n\
+Computes :math:`f(z) = C \\cdot z` as activation function.\n\
+\n\
+The constructor builds a new linear activation function\n\
+with a given constant. Don't use this if you just want to\n\
+set constant to the default value (1.0). In such a case,\n\
+prefer to use the more efficient :py:class:`IdentityActivation`.\n\
+");
+
+typedef struct {
+  PyBobMachineActivationObject parent;
+
+  /* Type-specific fields go here. */
+  bob::machine::LinearActivation* base;
+
+} PyBobMachineLinearActivationObject;
+
+static int PyBobMachineLinearActivation_init
+(PyBobMachineLinearActivationObject* self, PyObject* args, PyObject* kwds) {
+
+  /* Parses input arguments in a single shot */
+  static const char* const_kwlist[] = {0};
+  static char** kwlist = const_cast<char**>(const_kwlist);
+
+  double C = 1.0;
+
+  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|d", kwlist, &C)) return -1;
+
+  try {
+    self->base = new bob::machine::LinearActivation(C);
+  }
+  catch (std::exception& ex) {
+    PyErr_SetString(PyExc_RuntimeError, ex.what());
+  }
+  catch (...) {
+    PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_linearactivation_str);
+  }
+
+  self->parent.base = self->base;
+
+  if (PyErr_Occurred()) return -1;
+
+  return 0;
+
+}
+
+static void PyBobMachineLinearActivation_delete
+(PyBobMachineLinearActivationObject* self) {
+
+  delete self->base;
+  self->parent.base = 0;
+  self->base = 0;
+  self->parent.ob_type->tp_free((PyObject*)self);
+
+}
+
+PyDoc_STRVAR(s_C_str, "C");
+PyDoc_STRVAR(s_C_doc,
+"The multiplication factor for the linear function (read-only)"
+);
+
+static PyObject* PyBobMachineLinearActivation_C
+(PyBobMachineLinearActivationObject* self) {
+
+  return Py_BuildValue("d", self->base->C());
+
+}
+
+static PyGetSetDef PyBobMachineLinearActivation_getseters[] = {
+    {
+      s_C_str,
+      (getter)PyBobMachineLinearActivation_C,
+      0,
+      s_C_doc,
+      0
+    },
+    {0}  /* Sentinel */
+};
+
+PyTypeObject PyBobMachineLinearActivation_Type = {
+    PyObject_HEAD_INIT(0)
+    0,                                                  /*ob_size*/
+    0,                                                  /*tp_name*/
+    sizeof(PyBobMachineLinearActivationObject),         /*tp_basicsize*/
+    0,                                                  /*tp_itemsize*/
+    (destructor)PyBobMachineLinearActivation_delete,    /*tp_dealloc*/
+    0,                                                  /*tp_print*/
+    0,                                                  /*tp_getattr*/
+    0,                                                  /*tp_setattr*/
+    0,                                                  /*tp_compare*/
+    0,                                                  /*tp_repr*/
+    0,                                                  /*tp_as_number*/
+    0,                                                  /*tp_as_sequence*/
+    0,                                                  /*tp_as_mapping*/
+    0,                                                  /*tp_hash */
+    0,                                                  /*tp_call*/
+    0,                                                  /*tp_str*/
+    0,                                                  /*tp_getattro*/
+    0,                                                  /*tp_setattro*/
+    0,                                                  /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,           /*tp_flags*/
+    s_linearactivation_doc,                             /* tp_doc */
+    0,		                                              /* tp_traverse */
+    0,		                                              /* tp_clear */
+    0,                                                  /* tp_richcompare */
+    0,		                                              /* tp_weaklistoffset */
+    0,		                                              /* tp_iter */
+    0,		                                              /* tp_iternext */
+    0,                                                  /* tp_methods */
+    0,                                                  /* tp_members */
+    PyBobMachineLinearActivation_getseters,             /* tp_getset */
+    0,                                                  /* tp_base */
+    0,                                                  /* tp_dict */
+    0,                                                  /* tp_descr_get */
+    0,                                                  /* tp_descr_set */
+    0,                                                  /* tp_dictoffset */
+    (initproc)PyBobMachineLinearActivation_init,        /* tp_init */
+    0,                                                  /* tp_alloc */
+    0,                                                  /* tp_new */
+};
diff --git a/xbob/machine/logistic.cpp b/xbob/machine/logistic_activation.cpp
similarity index 82%
rename from xbob/machine/logistic.cpp
rename to xbob/machine/logistic_activation.cpp
index 2fe3279..8a5e669 100644
--- a/xbob/machine/logistic.cpp
+++ b/xbob/machine/logistic_activation.cpp
@@ -7,9 +7,10 @@
 
 #include <xbob.machine/api.h>
 
-PyDoc_STRVAR(s_activationsubtype_str, XBOB_EXT_MODULE_PREFIX ".LogisticActivation");
+PyDoc_STRVAR(s_logisticactivation_str,
+    XBOB_EXT_MODULE_PREFIX ".LogisticActivation");
 
-PyDoc_STRVAR(s_activationsubtype_doc,
+PyDoc_STRVAR(s_logisticactivation_doc,
 "LogisticActivation() -> new LogisticActivation\n\
 \n\
 Computes :math:`f(z) = 1/(1+ e^{-z})` as activation function.\n\
@@ -22,9 +23,10 @@ typedef struct {
   /* Type-specific fields go here. */
   bob::machine::LogisticActivation* base;
 
-} PyBobMachineActivationSubtypeObject;
+} PyBobMachineLogisticActivationObject;
 
-static int PyBobMachineActivationSubtype_init(PyBobMachineActivationSubtypeObject* self, PyObject* args, PyObject* kwds) {
+static int PyBobMachineLogisticActivation_init
+(PyBobMachineLogisticActivationObject* self, PyObject* args, PyObject* kwds) {
 
   /* Parses input arguments in a single shot */
   static const char* const_kwlist[] = {0};
@@ -39,7 +41,7 @@ static int PyBobMachineActivationSubtype_init(PyBobMachineActivationSubtypeObjec
     PyErr_SetString(PyExc_RuntimeError, ex.what());
   }
   catch (...) {
-    PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_activationsubtype_str);
+    PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_logisticactivation_str);
   }
 
   self->parent.base = self->base;
@@ -50,7 +52,8 @@ static int PyBobMachineActivationSubtype_init(PyBobMachineActivationSubtypeObjec
 
 }
 
-static void PyBobMachineActivationSubtype_delete (PyBobMachineActivationSubtypeObject* self) {
+static void PyBobMachineLogisticActivation_delete
+(PyBobMachineLogisticActivationObject* self) {
 
   delete self->base;
   self->parent.base = 0;
@@ -59,13 +62,13 @@ static void PyBobMachineActivationSubtype_delete (PyBobMachineActivationSubtypeO
 
 }
 
-PyTypeObject PyBobMachineActivationSubtype_Type = {
+PyTypeObject PyBobMachineLogisticActivation_Type = {
     PyObject_HEAD_INIT(0)
     0,                                                  /*ob_size*/
     0,                                                  /*tp_name*/
-    sizeof(PyBobMachineActivationSubtypeObject),        /*tp_basicsize*/
+    sizeof(PyBobMachineLogisticActivationObject),       /*tp_basicsize*/
     0,                                                  /*tp_itemsize*/
-    (destructor)PyBobMachineActivationSubtype_delete,   /*tp_dealloc*/
+    (destructor)PyBobMachineLogisticActivation_delete,  /*tp_dealloc*/
     0,                                                  /*tp_print*/
     0,                                                  /*tp_getattr*/
     0,                                                  /*tp_setattr*/
@@ -81,7 +84,7 @@ PyTypeObject PyBobMachineActivationSubtype_Type = {
     0,                                                  /*tp_setattro*/
     0,                                                  /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,           /*tp_flags*/
-    s_activationsubtype_doc,                            /* tp_doc */
+    s_logisticactivation_doc,                           /* tp_doc */
     0,		                                              /* tp_traverse */
     0,		                                              /* tp_clear */
     0,                                                  /* tp_richcompare */
@@ -96,7 +99,7 @@ PyTypeObject PyBobMachineActivationSubtype_Type = {
     0,                                                  /* tp_descr_get */
     0,                                                  /* tp_descr_set */
     0,                                                  /* tp_dictoffset */
-    (initproc)PyBobMachineActivationSubtype_init,       /* tp_init */
+    (initproc)PyBobMachineLogisticActivation_init,      /* tp_init */
     0,                                                  /* tp_alloc */
     0,                                                  /* tp_new */
 };
diff --git a/xbob/machine/tanh.cpp b/xbob/machine/tanh_activation.cpp
similarity index 80%
rename from xbob/machine/tanh.cpp
rename to xbob/machine/tanh_activation.cpp
index 39692a6..1a05363 100644
--- a/xbob/machine/tanh.cpp
+++ b/xbob/machine/tanh_activation.cpp
@@ -7,9 +7,10 @@
 
 #include <xbob.machine/api.h>
 
-PyDoc_STRVAR(s_activationsubtype_str, XBOB_EXT_MODULE_PREFIX ".HyperbolicTangentActivation");
+PyDoc_STRVAR(s_hyperbolictangentactivation_str,
+    XBOB_EXT_MODULE_PREFIX ".HyperbolicTangentActivation");
 
-PyDoc_STRVAR(s_activationsubtype_doc,
+PyDoc_STRVAR(s_hyperbolictangentactivation_doc,
 "HyperbolicTangentActivation() -> new HyperbolicTangentActivation\n\
 \n\
 Computes :math:`f(z) = \\tanh(z)` as activation function.\n\
@@ -22,9 +23,11 @@ typedef struct {
   /* Type-specific fields go here. */
   bob::machine::HyperbolicTangentActivation* base;
 
-} PyBobMachineActivationSubtypeObject;
+} PyBobMachineHyperbolicTangentActivationObject;
 
-static int PyBobMachineActivationSubtype_init(PyBobMachineActivationSubtypeObject* self, PyObject* args, PyObject* kwds) {
+static int PyBobMachineHyperbolicTangentActivation_init
+(PyBobMachineHyperbolicTangentActivationObject* self,
+ PyObject* args, PyObject* kwds) {
 
   /* Parses input arguments in a single shot */
   static const char* const_kwlist[] = {0};
@@ -39,7 +42,7 @@ static int PyBobMachineActivationSubtype_init(PyBobMachineActivationSubtypeObjec
     PyErr_SetString(PyExc_RuntimeError, ex.what());
   }
   catch (...) {
-    PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_activationsubtype_str);
+    PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_hyperbolictangentactivation_str);
   }
 
   self->parent.base = self->base;
@@ -50,7 +53,8 @@ static int PyBobMachineActivationSubtype_init(PyBobMachineActivationSubtypeObjec
 
 }
 
-static void PyBobMachineActivationSubtype_delete (PyBobMachineActivationSubtypeObject* self) {
+static void PyBobMachineHyperbolicTangentActivation_delete
+(PyBobMachineHyperbolicTangentActivationObject* self) {
 
   delete self->base;
   self->parent.base = 0;
@@ -59,13 +63,13 @@ static void PyBobMachineActivationSubtype_delete (PyBobMachineActivationSubtypeO
 
 }
 
-PyTypeObject PyBobMachineActivationSubtype_Type = {
+PyTypeObject PyBobMachineHyperbolicTangentActivation_Type = {
     PyObject_HEAD_INIT(0)
     0,                                                  /*ob_size*/
     0,                                                  /*tp_name*/
-    sizeof(PyBobMachineActivationSubtypeObject),        /*tp_basicsize*/
+    sizeof(PyBobMachineHyperbolicTangentActivationObject),  /*tp_basicsize*/
     0,                                                  /*tp_itemsize*/
-    (destructor)PyBobMachineActivationSubtype_delete,   /*tp_dealloc*/
+    (destructor)PyBobMachineHyperbolicTangentActivation_delete, /*tp_dealloc*/
     0,                                                  /*tp_print*/
     0,                                                  /*tp_getattr*/
     0,                                                  /*tp_setattr*/
@@ -81,7 +85,7 @@ PyTypeObject PyBobMachineActivationSubtype_Type = {
     0,                                                  /*tp_setattro*/
     0,                                                  /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,           /*tp_flags*/
-    s_activationsubtype_doc,                            /* tp_doc */
+    s_hyperbolictangentactivation_doc,                  /* tp_doc */
     0,		                                              /* tp_traverse */
     0,		                                              /* tp_clear */
     0,                                                  /* tp_richcompare */
@@ -96,7 +100,7 @@ PyTypeObject PyBobMachineActivationSubtype_Type = {
     0,                                                  /* tp_descr_get */
     0,                                                  /* tp_descr_set */
     0,                                                  /* tp_dictoffset */
-    (initproc)PyBobMachineActivationSubtype_init,       /* tp_init */
+    (initproc)PyBobMachineHyperbolicTangentActivation_init, /* tp_init */
     0,                                                  /* tp_alloc */
     0,                                                  /* tp_new */
 };
-- 
GitLab