     for (int row = 0; row < len; ++row)
     {
         if ((pad_p == NULL) || !(*pad_p)) {
-            const auto g1 = sigmoidf((*(up+1)) + wc1*cur + bias1);
-            const auto g2 = sigmoidf((*(up+2)) + wc2*cur + bias2);
-            const auto u_val = *up;
-            cur = (cur-u_val)*g1 + u_val;
+            const auto u0 = *up;
+            const auto u1 = *(up + 1);
+            const auto u2 = *(up + 2);
+            const auto x_val = *xp;
+            const auto g1 = sigmoidf(u1 + wc1*cur + bias1);
+            const auto g2 = sigmoidf(u2 + wc2*cur + bias2);
+            cur = (cur-u0)*g1 + u0;
             const auto val = calc_activation(activation_type, cur);
-            *hp = skip_type ? ((val * mask - (*xp)) * g2 + (*xp)) : (val * mask * g2);
+            *hp = skip_type ? ((val * mask - x_val) * g2 + x_val) : (val * mask * g2);
         } 
         //else {
         //    *hp = 0;  // output 0 for a pad token

                        const int activation_type,
                        const int skip_type)
{
    assert ((skip_type >= 0) || (skip_type <= 2));
    assert ((skip_type != 1) || (k == 3));
    assert ((skip_type != 2) || (k == 4));


    {
        if ((pad_p == NULL) || !(*pad_p)) {
            const auto prev_c_val = (cnt<len-1) ? (*(cp-ncols_)) : (*(init+col));
            const auto cp_val = *cp;
            const auto u0 = *up;
            const auto u1 = *(up + 1);
            const auto u2 = *(up + 2);
            const auto x_val = (skip_type) ? (*xp) : 0;
            const auto gh_val = *ghp;
            const auto g1 = sigmoidf(u1 + wc1*prev_c_val + bias1);
            const auto g2 = sigmoidf(u2 + wc2*prev_c_val + bias2);
            const auto c_val = calc_activation(activation_type, cp_val);

            // h = c*g2 + x*(1-g2) = (c-x)*g2 + x
            // c = c'*g1 + u0*(1-g1) = (c'-u0)*g1 + u0

            // gradient with respect to values in the second gate g2
            const auto gg2 = gh_val*(c_val*mask-x_val)*(g2*(1-g2));
            gbias2 += gg2;
            gwc2 += gg2*prev_c_val;

            // gradient with respect to c[t]
            const auto tmp = g2*calc_grad_activation(activation_type, c_val);
            const auto gc = gh_val*mask*tmp + cur;

            // gradient with respect to values in the first gate g1
            const auto gg1 = gc*(prev_c_val-u0)*(g1*(1-g1));
            gbias1 += gg1;
            gwc1 += gg1*prev_c_val;

            // gradient with respect to c[t-1]
            cur = gc*g1 + gg1*wc1 + gg2*wc2;

            // gradient with respect to U
            *gup = gc*(1-g1);
            *(gup + 1) = gg1;
            *(gup + 2) = gg2;

            // gradient with respect to x[t]
            if (skip_type)
                *gxp = gh_val*(1-g2);
        }

        up -= ncols_u_;
        cp -= ncols_;
        gup -= ncols_u_;
        ghp -= ncols_;
        xp = skip_type ? (xp - ncols_x_) : NULL;
        gxp = skip_type ? (gxp - ncols_x_) : NULL;
        pad_p = mask_pad ? (pad_p - batch_) : NULL;
    }

    //const int bias_idx = col % d2;
