Changeset 2031


Ignore:
Timestamp:
Jul 27, 2011 10:37:25 AM (9 years ago)
Author:
bradbell
Message:

Implement the tanh function as an atomic operation.

Location:
trunk
Files:
1 added
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/cppad/local/ad.hpp

    r2028 r2031  
    181181        inline AD sqrt(void) const;
    182182        inline AD tan(void) const;
     183        inline AD tanh(void) const;
    183184
    184185        // ----------------------------------------------------------
  • trunk/cppad/local/for_jac_sweep.hpp

    r2030 r2031  
    485485                        case TanOp:
    486486                        // tan(x)^2, tan(x)
     487                        CPPAD_ASSERT_NARG_NRES(op, 1, 2);
     488                        forward_sparse_jacobian_unary_op(
     489                                i_var, arg[0], var_sparsity
     490                        );
     491                        break;
     492                        // -------------------------------------------------
     493
     494                        case TanhOp:
     495                        // tanh(x)^2, tanh(x)
    487496                        CPPAD_ASSERT_NARG_NRES(op, 1, 2);
    488497                        forward_sparse_jacobian_unary_op(
  • trunk/cppad/local/forward0sweep.hpp

    r2030 r2031  
    486486                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
    487487                        forward_tan_op_0(i_var, arg[0], J, Taylor);
     488                        break;
     489                        // -------------------------------------------------
     490
     491                        case TanhOp:
     492                        // tanh(x)^2, tanh(x)
     493                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
     494                        forward_tanh_op_0(i_var, arg[0], J, Taylor);
    488495                        break;
    489496                        // -------------------------------------------------
  • trunk/cppad/local/forward_sweep.hpp

    r2030 r2031  
    540540                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
    541541                        forward_tan_op(d, i_var, arg[0], J, Taylor);
     542                        break;
     543                        // -------------------------------------------------
     544
     545                        case TanhOp:
     546                        // tanh(x)^2, tanh(x)
     547                        CPPAD_ASSERT_UNKNOWN( i_var < numvar  );
     548                        forward_tanh_op(d, i_var, arg[0], J, Taylor);
    542549                        break;
    543550                        // -------------------------------------------------
  • trunk/cppad/local/hash_code.hpp

    r2028 r2031  
    8282\li unary operators:
    8383AbsOp, AcosOp, AsinOp, AtanOp, CosOp, CoshOp, DisOp,
    84 ExpOp, LogOp, SinOp, SinhOp, SqrtOp, TanOp
     84ExpOp, LogOp, SinOp, SinhOp, SqrtOp, TanOp, TanhOp
    8585
    8686\li binary operators where first argument is a parameter:
     
    219219                case SqrtOp:
    220220                case TanOp:
     221                case TanhOp:
    221222                v = reinterpret_cast<const unsigned short*>(arg + 0);
    222223                i = short_addr_t;
  • trunk/cppad/local/op.hpp

    r2028 r2031  
    4747# include <cppad/local/store_op.hpp>
    4848# include <cppad/local/tan_op.hpp>
     49# include <cppad/local/tanh_op.hpp>
    4950
    5051
  • trunk/cppad/local/op_code.hpp

    r2028 r2031  
    8484        SubvpOp,  //      variable   - parameter
    8585        SubvvOp,  //      variable   - variable
     86        TanhOp,   //  tan(variable)
    8687        TanOp,    //  tan(variable)
    8788        // user atomic operation codes (note yet implemented)
     
    148149        2, // SubvpOp
    149150        2, // SubvvOp
     151        1, // TanhOp
    150152        1, // TanOp
    151153        4, // UserOp
     
    245247        1, // SubvpOp
    246248        1, // SubvvOp
     249        2, // TanhOp
    247250        2, // TanOp
    248251        0, // UserOp
     
    445448                "Subvp" ,
    446449                "Subvv" ,
     450                "Tanh"  ,
    447451                "Tan"   ,
    448452                "User"  ,
     
    569573                case SqrtOp:
    570574                case UsravOp:
     575                case TanhOp:
    571576                case TanOp:
    572577                CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
  • trunk/cppad/local/optimize.hpp

    r2028 r2031  
    927927                        case SqrtOp:
    928928                        case TanOp:
     929                        case TanhOp:
    929930                        if( tape[i_var].connect != not_connected )
    930931                                tape[arg[0]].connect = yes_connected;
     
    12891290                        case SqrtOp:
    12901291                        case TanOp:
     1292                        case TanhOp:
    12911293                        match_var = optimize_unary_match(
    12921294                                tape                ,  // inputs
  • trunk/cppad/local/rev_hes_sweep.hpp

    r2030 r2031  
    536536                        case TanOp:
    537537                        // tan(x)^2, tan(x)
     538                        CPPAD_ASSERT_NARG_NRES(op, 1, 2)
     539                        reverse_sparse_hessian_nonlinear_unary_op(
     540                        i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse
     541                        );
     542                        break;
     543                        // -------------------------------------------------
     544
     545                        case TanhOp:
     546                        // tanh(x)^2, tanh(x)
    538547                        CPPAD_ASSERT_NARG_NRES(op, 1, 2)
    539548                        reverse_sparse_hessian_nonlinear_unary_op(
  • trunk/cppad/local/rev_jac_sweep.hpp

    r2030 r2031  
    488488                        case TanOp:
    489489                        // tan(x)^2, tan(x)
     490                        CPPAD_ASSERT_NARG_NRES(op, 1, 2);
     491                        reverse_sparse_jacobian_unary_op(
     492                                i_var, arg[0], var_sparsity
     493                        );
     494                        break;
     495                        // -------------------------------------------------
     496
     497                        case TanhOp:
     498                        // tanh(x)^2, tanh(x)
    490499                        CPPAD_ASSERT_NARG_NRES(op, 1, 2);
    491500                        reverse_sparse_jacobian_unary_op(
  • trunk/cppad/local/reverse_sweep.hpp

    r2030 r2031  
    497497                        );
    498498                        break;
     499                        // -------------------------------------------------
     500
     501                        case TanhOp:
     502                        CPPAD_ASSERT_UNKNOWN( i_var < numvar );
     503                        reverse_tanh_op(
     504                                d, i_var, arg[0], J, Taylor, K, Partial
     505                        );
     506                        break;
    499507                        // --------------------------------------------------
    500508
  • trunk/cppad/local/std_math_ad.hpp

    r2028 r2031  
    238238
    239239$subhead tanh$$
    240 This function is also special in that it's derivatives are calculated
    241 using the relation
    242 $latex \[
    243 \begin{array}{lcr}
    244         \tanh (x) & = & \sinh(x) / \cosh(x)
     240$latex \[
     241\begin{array}{lcr}
     242        \D{[ \tanh (x) ]}{x} & = & 1 - \tanh (x)^2
    245243\end{array}
    246244\] $$
     
    253251
    254252# define CPPAD_STANDARD_MATH_UNARY_AD(Name, Op)                   \
     253    template <class Base>                                         \
     254    inline AD<Base> Name(const AD<Base> &x)                       \
     255    {   return x.Name(); }                                        \
    255256    template <class Base>                                         \
    256257    inline AD<Base> AD<Base>::Name (void) const                   \
     
    264265            CPPAD_ASSERT_UNKNOWN( NumArg(Op) == 1 );              \
    265266            ADTape<Base> *tape = tape_this();                     \
    266             tape->Rec_.PutArg(taddr_);                             \
    267             result.taddr_ = tape->Rec_.PutOp(Op);                  \
     267            tape->Rec_.PutArg(taddr_);                            \
     268            result.taddr_ = tape->Rec_.PutOp(Op);                 \
    268269            result.id_    = tape->id_;                            \
    269270        }                                                         \
    270271        return result;                                            \
    271272    }                                                             \
    272     template <class Base>                                         \
    273     inline AD<Base> Name(const AD<Base> &x)                       \
    274     {   return x.Name(); }                                        \
    275273    template <class Base>                                         \
    276274    inline AD<Base> Name(const VecAD_reference<Base> &x)          \
     
    291289     CPPAD_STANDARD_MATH_UNARY_AD(sqrt, SqrtOp)
    292290     CPPAD_STANDARD_MATH_UNARY_AD(tan, TanOp)
     291     CPPAD_STANDARD_MATH_UNARY_AD(tanh, TanhOp)
    293292
    294293     // log10
    295294     template <class Base>
    296295     inline AD<Base> log10(const AD<Base> &x)
    297      {  return CppAD::log(x) / CppAD::log( Base(10) ); }
     296     {    return CppAD::log(x) / CppAD::log( Base(10) ); }
    298297     template <class Base>
    299298     inline AD<Base> log10(const VecAD_reference<Base> &x)
    300      {  return CppAD::log(x.ADBase()) / CppAD::log( Base(10) ); }
    301      // tanh
    302      template <class Base>
    303      inline AD<Base> tanh(const AD<Base> &x)
    304      {  return CppAD::sinh(x) / CppAD::cosh(x); }
    305      template <class Base>
    306      inline AD<Base> tanh(const VecAD_reference<Base> &x)
    307      {  return CppAD::sinh(x.ADBase()) / CppAD::cosh(x.ADBase()); }
     299     {    return CppAD::log(x.ADBase()) / CppAD::log( Base(10) ); }
    308300}
    309301
  • trunk/cppad/std_math_unary.hpp

    r1370 r2031  
    44
    55/* --------------------------------------------------------------------------
    6 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-07 Bradley M. Bell
     6CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-11 Bradley M. Bell
    77
    88CppAD is distributed under multiple licenses. This distribution is under
     
    105105# include <cmath>
    106106
    107 # define CPPAD_STANDARD_MATH_UNARY(Name)                             \
    108                                                                      \
    109         inline float Name(const float &x)                            \
    110         {       return std::Name(x); }                               \
    111                                                                      \
    112         inline double Name(const double &x)                          \
    113         {       return std::Name(x); }
     107# define CPPAD_STANDARD_MATH_UNARY(Name)   \
     108                                           \
     109     inline float Name(const float &x)     \
     110     {    return std::Name(x); }           \
     111                                           \
     112     inline double Name(const double &x)   \
     113     {    return std::Name(x); }
    114114
    115115namespace CppAD {
  • trunk/makefile.am

    r2028 r2031  
    223223        cppad/local/sub.hpp \
    224224        cppad/local/sub_op.hpp \
     225        cppad/local/tanh_op.hpp \
    225226        cppad/local/tan_op.hpp \
    226227        cppad/local/tape_link.hpp \
  • trunk/makefile.in

    r2028 r2031  
    471471        cppad/local/sub.hpp \
    472472        cppad/local/sub_op.hpp \
     473        cppad/local/tanh_op.hpp \
    473474        cppad/local/tan_op.hpp \
    474475        cppad/local/tape_link.hpp \
  • trunk/omh/tan_forward.omh

    r2015 r2031  
    2121
    2222$section Tangent and Hyperbolic Tangent Forward Taylor Polynomial Theory$$
    23 $center (Not Yet Implemented) $$
    2423
    2524$head Derivatives$$
  • trunk/omh/tan_reverse.omh

    r2019 r2031  
    2121
    2222$section Tangent and Hyperbolic Tangent Reverse Mode Theory$$
    23 $center (Not Yet Implemented) $$
    2423
    2524$head Notation$$
  • trunk/omh/whats_new_11.omh

    r2024 r2031  
    6060assist you in learning about changes between various versions of CppAD.
    6161
     62$head 07-27$$
     63Make $code tan$$ and $code tanh$$ $cref/atomic/glossary/Operation/Atomic/$$
     64operations; see $cref tan_forward$$ and $cref tan_reverse$$.
     65
    6266$head 07-25$$
    6367Finish the $cref/user_atomic/$$ example $cref user_tan.cpp$$.
     
    8084Derive the theory for including the tangent and hyperbolic tangent
    8185as CppAD atomic operations $cref/tan_forward/$$ and $cref/tan_reverse/$$;
    82 see the wish list item $cref/Tan and Tanh/WishList/Tan and Tanh/$$.
     86see the wish list item $code Tan and Tanh$$.
    8387$lnext
    8488Implement and test forward mode calculation of derivative for
  • trunk/omh/wish_list.omh

    r2022 r2031  
    195195and operating systems.
    196196
    197 $head Tan and Tanh$$
    198 $index tanh$$
    199 $index tan$$
    200 The AD $code tan$$ and $code tanh$$ functions
    201 are implemented using the AD $code sin$$, $code cos$$, $code sinh$$
    202 and $code cosh$$ functions.
    203 They could be improved by making them atomic using the equations
    204 $latex \[
    205 \begin{array}{rcl}
    206         \tan^{(1)} (x)  & = & 1 + \tan (x)^2 \\
    207         \tanh^{(1)} (x) & = & 1 - \tanh (x)^2
    208 \end{array}
    209 \] $$
    210 see $cref/tan_forward/$$ and  $cref/tan_reverse/$$.
    211 
    212197$head Tracing$$
    213198$index operation, sequence tracing$$
  • trunk/test_more/mul_level.cpp

    r1697 r2031  
    11/* $Id$ */
    22/* --------------------------------------------------------------------------
    3 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-10 Bradley M. Bell
     3CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-11 Bradley M. Bell
    44
    55CppAD is distributed under multiple licenses. This distribution is under
     
    154154# ifdef CPPAD_ADOLC_TEST
    155155
    156 bool Three(void)
     156bool adolc(void)
    157157{       bool ok = true;                   // initialize test result
    158158
     
    221221# endif // CPPAD_ADOLC_TEST
    222222
     223bool std_math(void)
     224{       bool ok = true;
     225        using CppAD::AD;
     226        using CppAD::Independent;
     227        using CppAD::ADFun;
     228        double eps = std::numeric_limits<double>::epsilon();
     229
     230
     231        typedef AD<double>      ADdouble; // for first level of taping
     232        typedef AD<ADdouble>   ADDdouble; // for second level of taping
     233        size_t n = 1;         // number independent variables
     234        size_t m = 1;         // number dependent and independent variables
     235
     236        CPPAD_TEST_VECTOR<double>       x(n),   y(m);
     237        CPPAD_TEST_VECTOR<ADdouble>    ax(n),  ay(m);
     238        CPPAD_TEST_VECTOR<ADDdouble>  aax(n), aay(m);
     239
     240        // create af(x) = tanh(x)
     241        aax[0] = 1.;
     242        Independent( aax );
     243        aay[0] = tanh(aax[0]);
     244        ADFun<ADdouble> af(aax, aay);
     245
     246        // create g(x) = af(x)
     247        ax[0] = 1.;
     248        Independent( ax );
     249        ay = af.Forward(0, ax);
     250        ADFun<double> g(ax, ay);
     251
     252        // evaluate h(x) = g(x)
     253        x[0] = 1.;
     254        y = g.Forward(0, x);
     255
     256        // check result
     257        double check  = tanh(x[0]);
     258        ok &= CppAD::NearEqual(y[0], check, eps, eps);
     259
     260        return ok;
     261}
     262
    223263} // END empty namespace
    224264
     
    228268        ok     &= Two();
    229269# ifdef CPPAD_ADOLC_TEST
    230         ok     &= Three();
     270        ok     &= adolc();
    231271# endif
    232         return ok;
    233 }
     272        ok     &= std_math();
     273
     274        return ok;
     275}
  • trunk/test_more/tan.cpp

    r2028 r2031  
    2121        bool tan_case(bool tan_first)
    2222        {       bool ok = true;
    23                 double eps = 10. * std::numeric_limits<double>::epsilon();
     23                double eps = 100. * std::numeric_limits<double>::epsilon();
    2424                using CppAD::AD;
    2525                using CppAD::NearEqual;
     
    6666                return ok;
    6767        }
     68        bool tanh_case(bool tanh_first)
     69        {       bool ok = true;
     70                double eps = 100. * std::numeric_limits<double>::epsilon();
     71                using CppAD::AD;
     72                using CppAD::NearEqual;
     73       
     74                // independent variable vector, indices, values, and declaration
     75                size_t n = 1;
     76                CPPAD_TEST_VECTOR< AD<double> > ax(n);
     77                ax[0]     = .5;
     78                Independent(ax);
     79       
     80                // dependent variable vector and indices
     81                size_t m = 1;
     82                CPPAD_TEST_VECTOR< AD<double> > ay(m);
     83                AD<double> z;
     84                if( tanh_first )
     85                {       z     = tanh( ax[0] );
     86                        ay[0] = .5 * log( (1. + z) / (1. - z) );
     87                }
     88                else
     89                {       z     = .5 * log( (1. + ax[0]) / (1. - ax[0]) );
     90                        ay[0] = tanh(z);
     91                }
     92                // check value
     93                ok &= NearEqual(ax[0] , ay[0],  eps, eps);
     94       
     95                // create f: x -> y and vectors used for derivative calculations
     96                CppAD::ADFun<double> f(ax, ay);
     97                CPPAD_TEST_VECTOR<double> dx(n), dy(m);
     98       
     99                // forward computation of partials w.r.t. x
     100                dx[0] = 1.;
     101                dy    = f.Forward(1, dx);
     102                ok   &= NearEqual(dy[0], 1e0, eps, eps);
     103                size_t p, order = 5;
     104                dx[0] = 0.;
     105                for(p = 2; p < order; p++)
     106                {       dy    = f.Forward(p, dx);
     107                        ok   &= NearEqual(dy[0], 0e0, eps, eps);
     108                }
     109       
     110                // reverse computation of order partial
     111                CPPAD_TEST_VECTOR<double>  w(m), dw(n * order);
     112                w[0] = 1.;
     113                dw   = f.Reverse(order, w);
     114                ok   &= NearEqual(dw[0], 1e0, eps, eps);
     115                for(p = 1; p < order; p++)
     116                        ok   &= NearEqual(dw[p], 0e0, eps, eps);
     117       
     118                return ok;
     119        }
    68120}
    69121bool tan(void)
     
    71123        ok     &= tan_case(true);
    72124        ok     &= tan_case(false);
     125        ok     &= tanh_case(true);
     126        ok     &= tanh_case(false);
    73127        return ok;
    74128}
Note: See TracChangeset for help on using the changeset viewer.