From c50d4c1dd2deb5e47eb4be0814d847374d991ca7 Mon Sep 17 00:00:00 2001
From: Elias Pipping <elias.pipping@fu-berlin.de>
Date: Mon, 10 Oct 2011 19:21:39 +0200
Subject: [PATCH] Test horrible functions

---
 src/nicefunction.hh         | 55 +++++++++++++++++++++++++++
 src/test-gradient-method.cc | 74 +++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+)

diff --git a/src/nicefunction.hh b/src/nicefunction.hh
index 2c86abcd..449e2f63 100644
--- a/src/nicefunction.hh
+++ b/src/nicefunction.hh
@@ -35,5 +35,60 @@ class TrivialFunction : public NiceFunction {
 
   double virtual rightDifferential(const double) const { return 0; }
 };
+
+// slope in [n-1,n] is n
+class HorribleFunction : public NiceFunction {
+public:
+  void virtual evaluate(const double& x, double& y) const {
+    double const fl = floor(x);
+    double const sum = fl * (fl + 1) / 2;
+    y = sum + (fl + 1) * (x - fl);
+  }
+
+  double virtual leftDifferential(const double x) const {
+    double const fl = floor(x);
+    if (x - fl < 1e-14)
+      return fl;
+    else
+      return fl + 1;
+  }
+
+  double virtual rightDifferential(const double x) const {
+    double const c = ceil(x);
+    if (c - x < 1e-14)
+      return c + 1;
+    else
+      return c;
+  }
+};
+
+// slope in [n-1,n] is log(n+1)
+class HorribleFunctionLogarithmic : public NiceFunction {
+public:
+  void virtual evaluate(const double& x, double& y) const {
+    y = 0;
+    size_t const fl = floor(x);
+    for (size_t i = 1; i <= fl;)
+      y += log(++i); // factorials grow to fast so we compute this incrementally
+
+    y += log(fl + 2) * (x - fl);
+  }
+
+  double virtual leftDifferential(const double x) const {
+    double const fl = floor(x);
+    if (x - fl < 1e-14)
+      return log(fl + 1);
+    else
+      return log(fl + 2);
+  }
+
+  double virtual rightDifferential(const double x) const {
+    double const c = ceil(x);
+    if (c - x < 1e-14)
+      return log(c + 2);
+    else
+      return log(c + 1);
+  }
+};
 }
 #endif
diff --git a/src/test-gradient-method.cc b/src/test-gradient-method.cc
index 4443b527..eb7b5e5c 100644
--- a/src/test-gradient-method.cc
+++ b/src/test-gradient-method.cc
@@ -182,6 +182,76 @@ void testTrivialFunction() {
   assert(std::abs(ret1 - ret2) < 1e-5);
 }
 
+void testHorribleFunction() {
+  int const dim = 2;
+  typedef Dune::SampleFunctional<dim> SampleFunctional;
+
+  SampleFunctional::SmallMatrix A;
+  A[0][0] = 3;
+  A[0][1] = 1.5;
+  A[1][0] = 1.5;
+  A[1][1] = 4;
+  SampleFunctional::SmallVector b;
+  b[0] = 1;
+  b[1] = 2;
+
+  Dune::HorribleFunction f;
+  SampleFunctional J(A, b, Dune::MyNonlinearity<dim>(f));
+
+  SampleFunctional::SmallVector start = b;
+  start *= 17;
+
+  double const ret1 = functionTester(J, start, 7);
+
+  // Something random
+  start[0] = 279;
+  start[1] = -96;
+
+  double const ret2 = functionTester(J, start, 8);
+  assert(std::abs(ret1 - ret2) < 1e-5);
+
+  start[0] = 0;
+  start[1] = 0;
+
+  double const ret3 = functionTester(J, start, 4);
+  assert(std::abs(ret1 - ret3) < 1e-5);
+}
+
+void testHorribleFunctionLogarithmic() {
+  int const dim = 2;
+  typedef Dune::SampleFunctional<dim> SampleFunctional;
+
+  SampleFunctional::SmallMatrix A;
+  A[0][0] = 3;
+  A[0][1] = 1.5;
+  A[1][0] = 1.5;
+  A[1][1] = 4;
+  SampleFunctional::SmallVector b;
+  b[0] = 1;
+  b[1] = 2;
+
+  Dune::HorribleFunctionLogarithmic f;
+  SampleFunctional J(A, b, Dune::MyNonlinearity<dim>(f));
+
+  SampleFunctional::SmallVector start = b;
+  start *= 17;
+
+  double const ret1 = functionTester(J, start, 6);
+
+  // Something random
+  start[0] = 279;
+  start[1] = -96;
+
+  double const ret2 = functionTester(J, start, 12);
+  assert(std::abs(ret1 - ret2) < 1e-5);
+
+  start[0] = 0;
+  start[1] = 0;
+
+  double const ret3 = functionTester(J, start, 4);
+  assert(std::abs(ret1 - ret3) < 1e-5);
+}
+
 int main() {
   try {
     testSampleFunction();
@@ -189,6 +259,10 @@ int main() {
     testSampleFunctionNonsmooth();
     std::cout << std::endl << std::endl << std::endl;
     testTrivialFunction();
+    std::cout << std::endl << std::endl << std::endl;
+    testHorribleFunction();
+    std::cout << std::endl << std::endl << std::endl;
+    testHorribleFunctionLogarithmic();
     return 0;
   }
   catch (Dune::Exception &e) {
-- 
GitLab