Repository: MTG/essentia (language: python)

Issue:
UnaryOperator skips scale and shift with certain operators 
[UnaryOperator](https://essentia.upf.edu/reference/std_UnaryOperator.html) implements the following pipeline:
1. Optionally apply a non-linear function (`type`)
2. Optionally `scale` the result by a given value
3. Optionally `shift` the result by a given a value

A number of non-linear functions (lin2db, db2lin, sin, cos) [are implemented](https://github.com/MTG/essentia/blob/e11821f9619e47ffe0bf567c5a21240dd5a0d1ba/src/algorithms/standard/unaryoperator.cpp#L57) in a way that UnaryOperator returns the values before computing steps 2 and 3.




Discussion / hints:

Fix patch:
diff --git a/src/algorithms/standard/unaryoperator.cpp b/src/algorithms/standard/unaryoperator.cpp
index a5f436be0..5a41d15da 100644
--- a/src/algorithms/standard/unaryoperator.cpp
+++ b/src/algorithms/standard/unaryoperator.cpp
@@ -58,7 +58,7 @@ inline Real square_func(Real x) {
   for (int i=0; i<int(input.size()); ++i) { \
     output[i] = f(input[i]);            \
   }                                     \
-  return;                               \
+  break;                                \
 }
 
 void UnaryOperator::compute() {


Test patch:
diff --git a/test/src/unittests/standard/test_unaryoperator.py b/test/src/unittests/standard/test_unaryoperator.py
index e37d19fe3..eb6a80779 100644
--- a/test/src/unittests/standard/test_unaryoperator.py
+++ b/test/src/unittests/standard/test_unaryoperator.py
@@ -46,7 +46,7 @@ def testLog10(self):
     def testLog10LowX(self):
         self.assertAlmostEqualVector(
             UnaryOperator(type="log10")(self.testInputLowX),
-             [-30., -30., -30., -30.])        
+             [-30., -30., -30., -30.])
 
     def testLog(self):
         self.assertAlmostEqualVector(
@@ -55,15 +55,15 @@ def testLog(self):
 
     def testLogLowX(self):
         self.assertAlmostEqualVector(
-            UnaryOperator(type="log")(self.testInputLowX),[-69.07755, -69.07755, -69.07755, -69.07755])        
+            UnaryOperator(type="log")(self.testInputLowX),[-69.07755, -69.07755, -69.07755, -69.07755])
 
     def testLn(self):
         self.assertAlmostEqualVector(UnaryOperator(type="ln")(self.testInput),
             [0, 0.693147181, 1.098612289, 1.386294361, 1.223775432, -69.07755279, 11.513265407])
 
-    def testLnLowX(self):        
+    def testLnLowX(self):
         self.assertAlmostEqualVector(UnaryOperator(type="ln")(self.testInputLowX),
-            [-69.07755, -69.07755, -69.07755, -69.07755])            
+            [-69.07755, -69.07755, -69.07755, -69.07755])
 
     def testLin2Db(self):
         self.assertAlmostEqualVector(
@@ -107,6 +107,20 @@ def testSquare(self):
     def testInvalidParam(self):
         self.assertConfigureFails(UnaryOperator(), {'type':'exp'})
 
+    def testOperatorScaleShift(self):
+        functions = ["identity", "abs", "log10", "log", "ln", "lin2db", "db2lin", "sin", "cos", "sqrt", "square"]
+
+        shift = 1
+        scale = 2
+        test_data = [1]
+
+        for type in functions:
+            with self.subTest(i=type):
+
+                expected = UnaryOperator(type=type)(test_data) * scale + shift
+                found = UnaryOperator(type=type, shift=shift, scale=scale)(test_data)
+
+                self.assertAlmostEqualVector(expected, found)
 
 suite = allTests(TestUnaryOperator)