/*
  Copyright (C) 2012-2015 The University of Reading
  Copyright (C) 2015- European Centre for Medium-Range Weather Forecasts

  Licensed under the Apache License, Version 2.0 (the "License"); you
  may not use this file except in compliance with the License.  You
  may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  implied.  See the License for the specific language governing
  permissions and limitations under the License.
*/

#include <iostream>
#include <adept_arrays.h>                // include adept.h if array features not required              
int main() {
  using namespace adept;
  Stack stack;                           // Object to store differential statements
  aVector x(3);                          // Independent variables: active vector with 3 elements
  x << 1.0, 2.0, 3.0;                    // Fill vector x
  stack.new_recording();                 // Clear any existing differential statements
  aReal J = cbrt(sum(abs(x*x*x)));       // Compute dependent variable: L3-norm in this case
  J.set_gradient(1.0);                   // Seed the dependent variable
  stack.reverse();                       // Reverse-mode differentiation
  std::cout << "dJ/dx = "
            << x.get_gradient() << "\n"; // Print the vector of partial derivatives dJ/dx
  
  const double norm2 = (x.get_gradient()[0] - 0.0917202) * (x.get_gradient()[0] - 0.0917202)
                       +(x.get_gradient()[1] - 0.366881) * (x.get_gradient()[1] - 0.366881)
                       +(x.get_gradient()[2] - 0.825482) * (x.get_gradient()[2] - 0.825482);
  return (norm2 < 1.0E-5) ? 0 : 1;
}
