bool AbstractLinAlgPack::max_inequ_viol(
  const AbstractLinAlgPack::Vector   &v
  ,const AbstractLinAlgPack::Vector  &vL
  ,const AbstractLinAlgPack::Vector  &vU
  ,AbstractLinAlgPack::size_type     *max_viol_i
  ,AbstractLinAlgPack::value_type    *max_viol
  ,AbstractLinAlgPack::value_type    *v_i
  ,int                               *bnd_type
  ,AbstractLinAlgPack::value_type    *vLU_i
  )
{
  RTOpPack::RTOpC op;
  TEST_FOR_EXCEPT(0!=RTOp_ROp_max_inequ_viol_construct(&op.op()));
  Teuchos::RCP<RTOpPack::ReductTarget> reduct_obj = op.reduct_obj_create();
  const int num_vecs = 3;
  const Vector*
    vecs[num_vecs] = { &v, &vL, &vU };
  apply_op(
    op, num_vecs, vecs, 0, NULL
    ,&*reduct_obj
    );
  const RTOp_ROp_max_inequ_viol_reduct_obj_t
    ro = RTOp_ROp_max_inequ_viol_val(op(*reduct_obj));
  *max_viol_i = ro.max_viol_i;
  *max_viol   = ro.max_viol;
  *v_i        = ro.v_i;
  *bnd_type   = ro.bnd_type;
  *vLU_i      = ro.vLU_i;
  return *max_viol_i > 0.0;
}
AbstractLinAlgPack::value_type
AbstractLinAlgPack::sum( const Vector& v_rhs )
{
  sum_op.reduct_obj_reinit(&*sum_targ);
  const Vector* vecs[1] = { &v_rhs };
  apply_op(sum_op,1,vecs,0,NULL,&*sum_targ);
  return RTOp_ROp_sum_val(sum_op(*sum_targ));
}
AbstractLinAlgPack::value_type
AbstractLinAlgPack::dot( const Vector& v_rhs1, const Vector& v_rhs2 )
{
  dot_prod_op.reduct_obj_reinit(&*dot_prod_targ);
  const Vector* vecs[2] = { &v_rhs1, &v_rhs2 };
  apply_op(dot_prod_op,2,vecs,0,NULL,&*dot_prod_targ);
  return RTOp_ROp_dot_prod_val(dot_prod_op(*dot_prod_targ));
}
void AbstractLinAlgPack::Vp_S( VectorMutable* v_lhs, const value_type& alpha )
{
#ifdef TEUCHOS_DEBUG
  TEST_FOR_EXCEPTION(v_lhs==NULL,std::logic_error,"Vp_S(...), Error!");
#endif
  TEST_FOR_EXCEPT(0!=RTOp_TOp_add_scalar_set_alpha(alpha,&add_scalar_op.op()));
  VectorMutable* targ_vecs[1] = { v_lhs };
  apply_op(add_scalar_op,0,NULL,1,targ_vecs,NULL);
}
AbstractLinAlgPack::value_type
AbstractLinAlgPack::max_element( const Vector& v )
{
  RTOpPack::RTOpC op;
  TEST_FOR_EXCEPT(0!=RTOp_ROp_max_construct(&op.op()));
  Teuchos::RCP<RTOpPack::ReductTarget> reduct_obj = op.reduct_obj_create();
  const Vector* vecs[1] = { &v };
  apply_op(op,1,vecs,0,NULL,&*reduct_obj);
  return RTOp_ROp_max_val(op(*reduct_obj));
}
void AbstractLinAlgPack::sign(
  const Vector      &v
  ,VectorMutable    *z
  )
{
  RTOpPack::RTOpC op;
  TEST_FOR_EXCEPT( !( 0==RTOp_TOp_sign_construct(&op.op()) ) );
  const Vector*   vecs[1]      = { &v };
  VectorMutable*  targ_vecs[1] = { z  };
  apply_op(op,1,vecs,1,targ_vecs,NULL);
}
void AbstractLinAlgPack::Vp_StV(
  VectorMutable* v_lhs, const value_type& alpha, const Vector& v_rhs)
{
#ifdef TEUCHOS_DEBUG
  TEST_FOR_EXCEPTION(v_lhs==NULL,std::logic_error,"Vp_StV(...), Error!");
#endif
  TEST_FOR_EXCEPT(0!=RTOp_TOp_axpy_set_alpha( alpha, &axpy_op.op() ));
  const Vector*  vecs[1]      = { &v_rhs };
  VectorMutable* targ_vecs[1] = { v_lhs  };
  apply_op(axpy_op,1,vecs,1,targ_vecs,NULL);
}
void AbstractLinAlgPack::random_vector( value_type l, value_type u, VectorMutable* v )
{
#ifdef TEUCHOS_DEBUG
  TEST_FOR_EXCEPTION(v==NULL,std::logic_error,"Vt_S(...), Error");
#endif
  //TEST_FOR_EXCEPT(0!=RTOp_TOp_random_vector_set_bounds( l, u, &random_vector_op.op() ));
  random_vector_op.set_bounds(l,u);
  VectorMutable* targ_vecs[1] = { v };
  apply_op(random_vector_op,0,NULL,1,targ_vecs,NULL);
  
}
void AbstractLinAlgPack::inv_of_difference(
  const value_type      alpha
  ,const Vector   &v0
  ,const Vector   &v1
  ,VectorMutable  *z
  )
{
  TEST_FOR_EXCEPT(0!=RTOp_TOp_inv_of_difference_init( alpha, &inv_of_difference_op.op()));
  const Vector*  vecs[2]      = { &v0, &v1 };
  VectorMutable* targ_vecs[1] = { z };
  apply_op(inv_of_difference_op,2,vecs,1,targ_vecs,NULL);
}
void AbstractLinAlgPack::force_in_bounds(
  const Vector& xl, const Vector& xu
  ,VectorMutable* x
  )
{
#ifdef TEUCHOS_DEBUG
  TEST_FOR_EXCEPTION(x==NULL,std::logic_error,"force_in_bounds(...), Error");
#endif
  const Vector*  vecs[2]      = { &xl, &xu };
  VectorMutable* targ_vecs[1] = { x };
  apply_op(force_in_bounds_op,2,vecs,1,targ_vecs,NULL);
}
void AbstractLinAlgPack::ele_wise_prod(
  const value_type& alpha, const Vector& v_rhs1, const Vector& v_rhs2
  , VectorMutable* v_lhs )
{
#ifdef TEUCHOS_DEBUG
  TEST_FOR_EXCEPTION(v_lhs==NULL,std::logic_error,"ele_wise_prod(...), Error");
#endif
  TEST_FOR_EXCEPT(0!=RTOp_TOp_ele_wise_prod_set_alpha(alpha,&ele_wise_prod_op.op()));
  const Vector*   vecs[2]      = { &v_rhs1, &v_rhs2 };
  VectorMutable*  targ_vecs[1] = { v_lhs };
  apply_op(ele_wise_prod_op,2,vecs,1,targ_vecs,NULL);
}
void AbstractLinAlgPack::force_in_bounds_buffer(
  const value_type rel_push,
  const value_type abs_push,
  const Vector& xl, 
  const Vector& xu,
  VectorMutable* x
  )
{
  TEST_FOR_EXCEPT(0!=RTOp_TOp_force_in_bounds_buffer_init( rel_push, abs_push, &force_in_bounds_buffer_op.op()));
  const Vector*  vecs[2]      = { &xl, &xu };
  VectorMutable* targ_vecs[1] = { x };
  apply_op(force_in_bounds_buffer_op,2,vecs,1,targ_vecs,NULL);
}
void AbstractLinAlgPack::Vt_S( VectorMutable* v_lhs, const value_type& alpha )
{
#ifdef TEUCHOS_DEBUG
  TEST_FOR_EXCEPTION(v_lhs==NULL,std::logic_error,"Vt_S(...), Error!");
#endif
  if( alpha == 0.0 ) {
    *v_lhs = 0.0;
  }
  else if( alpha != 1.0 ) {
    TEST_FOR_EXCEPT(0!=RTOp_TOp_scale_vector_set_alpha( alpha, &scale_vector_op.op() ));
    VectorMutable* targ_vecs[1] = { v_lhs };
    apply_op(scale_vector_op,0,NULL,1,targ_vecs,NULL);
  }
}
AbstractLinAlgPack::value_type
AbstractLinAlgPack::max_rel_step(
  const Vector& x, const Vector& d
  )
{
  const int num_vecs = 2;
  const Vector*
    vecs[num_vecs] = { &x, &d };
  max_rel_step_op.reduct_obj_reinit(&*max_rel_step_targ);
  apply_op(
    max_rel_step_op, num_vecs, vecs, 0, NULL
    ,&*max_rel_step_targ );
  return RTOp_ROp_max_rel_step_val(max_rel_step_op(*max_rel_step_targ));
}
void AbstractLinAlgPack::max_abs_ele(
  const Vector& v, value_type* max_v_j, index_type* max_j
  )
{
  TEST_FOR_EXCEPT( !(  max_v_j && max_j  ) );
  RTOpPack::RTOpC op;
  TEST_FOR_EXCEPT(0!=RTOp_ROp_max_abs_ele_construct(&op.op()));
  Teuchos::RCP<RTOpPack::ReductTarget> reduct_obj = op.reduct_obj_create();
  const Vector* vecs[1] = { &v };
  apply_op(op,1,vecs,0,NULL,&*reduct_obj);
  RTOp_value_index_type val = RTOp_ROp_max_abs_ele_val(op(*reduct_obj));
  *max_v_j = val.value;
  *max_j   = val.index;
}
AbstractLinAlgPack::size_type
AbstractLinAlgPack:: num_bounded(
  const Vector& xl, const Vector& xu
  ,value_type inf_bound
  )
{
  TEST_FOR_EXCEPT(0!=RTOp_ROp_num_bounded_set_inf_bnd( inf_bound, &num_bounded_op.op() ));
  num_bounded_op.reduct_obj_reinit(&*num_bounded_targ);
  const int num_vecs = 2;
  const Vector*
    vecs[num_vecs] = { &xl, &xu };
  apply_op(
    num_bounded_op, num_vecs, vecs, 0, NULL
    ,&*num_bounded_targ );
  return RTOp_ROp_num_bounded_val(num_bounded_op(*num_bounded_targ));
}
AbstractLinAlgPack::value_type
AbstractLinAlgPack::fraction_to_zero_boundary(
  const value_type tau,
  const Vector& x,
  const Vector& d
  )
{
  TEST_FOR_EXCEPT(0!=RTOp_ROp_fraction_to_zero_boundary_init( tau, &fraction_to_zero_boundary_op.op() ));
  fraction_to_zero_boundary_op.reduct_obj_reinit(&*fraction_to_zero_boundary_targ);
  const int num_vecs = 2;
  const Vector*
    vecs[num_vecs] = { &x, &d };
  apply_op(
    fraction_to_zero_boundary_op, num_vecs, vecs, 0, NULL
    ,&*fraction_to_zero_boundary_targ );
  return RTOp_ROp_fraction_to_zero_boundary_val(fraction_to_zero_boundary_op(*fraction_to_zero_boundary_targ));
}
AbstractLinAlgPack::value_type
AbstractLinAlgPack::combined_nu_comp_err_upper(
  const Vector    &v
  ,const Vector   &x
  ,const Vector   &xu
  )
{
  combined_nu_comp_err_upper_op.reduct_obj_reinit(&*combined_nu_comp_err_upper_targ);
  const int num_vecs = 3;
  const Vector*
    vecs[num_vecs] = {&v, &xu, &x};
  apply_op(
    combined_nu_comp_err_upper_op, num_vecs, vecs, 0, NULL
    ,&*combined_nu_comp_err_upper_targ
    );
  return RTOp_ROp_combined_nu_comp_err_one_only_val(combined_nu_comp_err_upper_op(*combined_nu_comp_err_upper_targ));
}
AbstractLinAlgPack::value_type
AbstractLinAlgPack::log_bound_barrier(
  const Vector    &x
  ,const Vector   &xl
  ,const Vector   &xu
  )
{
  log_bound_barrier_op.reduct_obj_reinit(&*log_bound_barrier_targ);
  const int num_vecs = 3;
  const Vector*
    vecs[num_vecs] = { &x, &xl, &xu };
  apply_op(
    log_bound_barrier_op, num_vecs, vecs, 0, NULL
    ,&*log_bound_barrier_targ
    );

  return RTOp_ROp_log_bound_barrier_val(log_bound_barrier_op(*log_bound_barrier_targ));
}
Esempio n. 20
0
/* evaluate all possible (according to order of precedence) operators	*/
static void eval_stack (void)
{
	/* uses globals par[], op[], val[]	*/

	/* # of operators >= 2 and prev. op-level >= current op-level ?	*/
	while ((op.idx > par.opx[par.idx]) && get_level (-1) >= get_level (0)) {

		/* shorten value stacks by one	*/
		/* + calculate resulting value	*/
		op.idx -= 1;
		val.idx -= 1;
		val.buf[val.idx] = apply_op(op.buf[op.idx],
			val.buf[val.idx], val.buf[val.idx + 1]);

		/* pull the just used operator out of the stack		*/
		op.buf[op.idx] = op.buf[op.idx + 1];
	}
}
std::pair<AbstractLinAlgPack::value_type,AbstractLinAlgPack::value_type>
AbstractLinAlgPack::max_near_feas_step(
  const Vector& x, const Vector& d
  ,const Vector& xl, const Vector& xu
  ,value_type max_bnd_viol
  )
{
  const int num_vecs = 4;
  const Vector*
    vecs[num_vecs] = { &xl, &x, &d, &xu };
  TEST_FOR_EXCEPT(0!=RTOp_ROp_max_near_feas_step_set_beta( max_bnd_viol, &max_near_feas_step_op.op() ));
  max_near_feas_step_op.reduct_obj_reinit(&*max_near_feas_step_targ);
  apply_op(
    max_near_feas_step_op, num_vecs, vecs, 0, NULL
    ,&*max_near_feas_step_targ );
  RTOp_ROp_max_near_feas_step_reduct_obj_t
    u = RTOp_ROp_max_near_feas_step_val(max_near_feas_step_op(*max_near_feas_step_targ));;
  return std::pair<value_type,value_type>(u.alpha_pos,u.alpha_neg);
}
AbstractLinAlgPack::value_type
AbstractLinAlgPack::IP_comp_err_with_mu(
  const value_type mu
  ,const value_type inf_bound
  ,const Vector &x
  ,const Vector &xl
  ,const Vector &xu
  ,const Vector &vl
  ,const Vector &vu
  )
{
  TEST_FOR_EXCEPT(0!=RTOp_ROp_comp_err_with_mu_init(mu, inf_bound, &comp_err_with_mu_op.op()));
  comp_err_with_mu_op.reduct_obj_reinit(&*comp_err_with_mu_targ);
  const int num_vecs = 5;
  const Vector*
    vecs[num_vecs] = {&x, &xl, &xu, &vl, &vu};
  apply_op(
    comp_err_with_mu_op, num_vecs, vecs, 0, NULL
    ,&*comp_err_with_mu_targ
    );
  return RTOp_ROp_comp_err_with_mu_val(comp_err_with_mu_op(*comp_err_with_mu_targ));
}
Esempio n. 23
0
//------------------------------------------------------------------------------------------------------------------------------
void BiCGStab(level_type * level, int x_id, int R_id, double a, double b, double desired_reduction_in_norm){
  // Algorithm 7.7 in Iterative Methods for Sparse Linear Systems(Yousef Saad)
  // uses "right" preconditioning...  AD^{-1}(Dx) = b ... AD^{-1}y = b ... solve for y, then solve for x = D^{-1}y
  int  r0_id = VECTORS_RESERVED+0;
  int  r_id  = VECTORS_RESERVED+1;
  int   p_id = VECTORS_RESERVED+2;
  int   s_id = VECTORS_RESERVED+3;
  int  Ap_id = VECTORS_RESERVED+4;
  int  As_id = VECTORS_RESERVED+5;

  int jMax=200;
  int j=0;
  int BiCGStabFailed    = 0;
  int BiCGStabConverged = 0;
  residual(level,r0_id,x_id,R_id,a,b);                                          // r0[] = R_id[] - A(x_id)
  scale_vector(level,r_id,1.0,r0_id);                                             // r[] = r0[]
  scale_vector(level,p_id,1.0,r0_id);                                             // p[] = r0[]
  double r_dot_r0 = dot(level,r_id,r0_id);                                      // r_dot_r0 = dot(r,r0)
  double norm_of_r0 = norm(level,r_id);                                         // the norm of the initial residual...
  if(r_dot_r0   == 0.0){BiCGStabConverged=1;}                                   // entered BiCGStab with exact solution
  if(norm_of_r0 == 0.0){BiCGStabConverged=1;}                                   // entered BiCGStab with exact solution
  while( (j<jMax) && (!BiCGStabFailed) && (!BiCGStabConverged) ){               // while(not done){
    j++;level->Krylov_iterations++;                                             //
    #ifdef KRYLOV_DIAGONAL_PRECONDITION                                         //
    mul_vectors(level,VECTOR_TEMP,1.0,VECTOR_DINV,p_id);                              //   temp[] = Dinv[]*p[]
    apply_op(level,Ap_id,VECTOR_TEMP,a,b);                                           //   Ap = AD^{-1}(p)
    #else                                                                       //
    apply_op(level,Ap_id,p_id,a,b);                                            //   Ap = A(p)
    #endif                                                                      //
    double Ap_dot_r0 = dot(level,Ap_id,r0_id);                                  //   Ap_dot_r0 = dot(Ap,r0)
    if(Ap_dot_r0 == 0.0){BiCGStabFailed=1;break;}                               //   pivot breakdown ???
    double alpha = r_dot_r0 / Ap_dot_r0;                                        //   alpha = r_dot_r0 / Ap_dot_r0
    if(isinf(alpha)){BiCGStabFailed=2;break;}                                   //   pivot breakdown ???
    add_vectors(level,x_id,1.0,x_id, alpha, p_id);                                //   x_id[] = x_id[] + alpha*p[]
    add_vectors(level,s_id,1.0,r_id,-alpha,Ap_id);                                //   s[]    = r[]    - alpha*Ap[]   (intermediate residual?)
    double norm_of_s = norm(level,s_id);                                        //   FIX - redundant??  norm of intermediate residual
  //if(level->my_rank==0)printf("norm(s)/norm(r0) = %e\n",norm_of_s/norm_of_r0);
    if(norm_of_s == 0.0){BiCGStabConverged=1;break;}                            //   FIX - redundant??  if As_dot_As==0, then As must be 0 which implies s==0
    if(norm_of_s < desired_reduction_in_norm*norm_of_r0){BiCGStabConverged=1;break;}
    #ifdef KRYLOV_DIAGONAL_PRECONDITION                                         //
    mul_vectors(level,VECTOR_TEMP,1.0,VECTOR_DINV,s_id);                              //   temp[] = Dinv[]*s[]
    apply_op(level,As_id,VECTOR_TEMP,a,b);                                           //   As = AD^{-1}(s)
    #else                                                                       //
    apply_op(level,As_id,s_id,a,b);                                             //   As = A(s)
    #endif                                                                      //
    double As_dot_As = dot(level,As_id,As_id);                                  //   As_dot_As = dot(As,As)
    double As_dot_s  = dot(level,As_id, s_id);                                  //   As_dot_s  = dot(As, s)
    if(As_dot_As == 0.0){BiCGStabConverged=1;break;}                            //   converged ?
    double omega = As_dot_s / As_dot_As;                                        //   omega = As_dot_s / As_dot_As
    if(omega == 0.0){BiCGStabFailed=3;break;}                                   //   stabilization breakdown ???
    if(isinf(omega)){BiCGStabFailed=4;break;}                                   //   stabilization breakdown ???
    add_vectors(level,x_id,1.0,x_id, omega, s_id);                                //   x_id[] = x_id[] + omega*s[]
    add_vectors(level,r_id,1.0,s_id,-omega,As_id);                                //   r[]    = s[]    - omega*As[]  (recursively computed / updated residual)
    double norm_of_r = norm(level,r_id);                                        //   norm of recursively computed residual (good enough??)
  //if(level->my_rank==0)printf("norm(r)/norm(r0) = %e\n",norm_of_r/norm_of_r0);
    if(norm_of_r == 0.0){BiCGStabConverged=1;break;}                            //
    if(norm_of_r < desired_reduction_in_norm*norm_of_r0){BiCGStabConverged=1;break;}
    #ifdef __DEBUG                                                              //
    residual(level,VECTOR_TEMP,x_id,R_id,a,b);                                       //
    double norm_of_residual = norm(level,VECTOR_TEMP);                               //
    if(level->my_rank==0)fprintf(stdout,"j=%8d, norm=%12.6e, norm_inital=%12.6e, reduction=%e\n",j,norm_of_residual,norm_of_r0,norm_of_residual/norm_of_r0);   //
    #endif                                                                      //
    double r_dot_r0_new = dot(level,r_id,r0_id);                                //   r_dot_r0_new = dot(r,r0)
    if(r_dot_r0_new == 0.0){BiCGStabFailed=5;break;}                            //   Lanczos breakdown ???
    double beta = (r_dot_r0_new/r_dot_r0) * (alpha/omega);                      //   beta = (r_dot_r0_new/r_dot_r0) * (alpha/omega)
    if(isinf(beta)){BiCGStabFailed=6;break;}                                    //   ???
    add_vectors(level,VECTOR_TEMP,1.0,p_id,-omega, Ap_id);                             //   VECTOR_TEMP =         (p[]-omega*Ap[])
    add_vectors(level,        p_id,1.0,r_id,  beta,VECTOR_TEMP);                             //   p[] = r[] + beta*(p[]-omega*Ap[])
    r_dot_r0 = r_dot_r0_new;                                                    //   r_dot_r0 = r_dot_r0_new   (save old r_dot_r0)
  }                                                                             // }
    #ifdef KRYLOV_DIAGONAL_PRECONDITION                                         //
    mul_vectors(level,x_id,1.0,VECTOR_DINV,x_id);                                //   x_id[] = Dinv[]*x_id[] // i.e. x = D^{-1}x'
    #endif                                                                      //
  #ifdef __DEBUG
  if(BiCGStabFailed)if(level->my_rank==0)fprintf(stderr,"BiCGStab Failed... error = %d\n",BiCGStabFailed);
  #endif
}
long double evaluate(string_t* expr) {
    int i, length;
    double result, a, b;
    char as_string[2] = "\0";
    char top, op, unused;
    stack values, ops;

    string_t formatted;
    init_string(&formatted, "");
    format_expression_string(expr, &formatted);

    stack_new(&values, sizeof(double));
    stack_new(&ops, sizeof(char));

    length = strlen(formatted.string);

    for(i = 0; i < length; i++) {
        /* Current token is a whitespace, skip it */
        if (formatted.string[i] == ' ')
            continue;

        /* Current token is a number, push it to stack for numbers */
        if((formatted.string[i] >= '0' && formatted.string[i] <= '9') || (formatted.string[i] == '.')) {
            string_t buf;
            init_string(&buf, "");

            /* There may be more than one digits in number */
            while((i < length) &&
                (((formatted.string[i] >= '0') && (formatted.string[i] <= '9')) || (formatted.string[i] == '.'))) {
                as_string[0] = formatted.string[i++];
                append(&buf, as_string);
            }

            result = atof(buf.string);
            stack_push(&values, &result);
        } else if(formatted.string[i] == '(') {
            /* Current token is an opening brace, push it to 'ops' */
            as_string[0] = formatted.string[i];
            stack_push(&ops, as_string);
        } else if(formatted.string[i] == ')') {
            /* Closing brace encountered, solve entire brace */
            while(TRUE) {
                stack_peek(&ops, &top);
                if(top == '(') break;

                stack_pop(&values, &a);
                stack_pop(&values, &b);

                stack_pop(&ops, &op);

                result = apply_op(op, a, b);
                stack_push(&values, &result);
            }

            stack_pop(&ops, &unused); /* pop ( */
        } else if(is_operator(formatted.string[i])) {
            /* While top of 'ops' has same or greater precedence to current
               token, which is an operator. Apply operator on top of 'ops'
               to top two elements in values stack */
            while(TRUE) {
                top = '(';
                if(!stack_empty(&ops))
                    stack_peek(&ops, &top);
                if(stack_empty(&ops) || !has_precedence(formatted.string[i], top)) break;

                stack_pop(&values, &a);
                stack_pop(&values, &b);
                stack_pop(&ops, &op);

                result = apply_op(op, a, b);
                
                /* !!!!!!!!!!!!!!!!!!!!
                    if(division_by_zero) {
                        return -255;
                    } */

                stack_push(&values, &result);
            }
        
            /* Push current token to 'ops'. */
            as_string[0] = formatted.string[i];
            stack_push(&ops, as_string);
        }
    }
    
    /* Entire expression has been parsed at this point, apply remaining
       ops to remaining values */
    while(!stack_empty(&ops)) {
        stack_pop(&values, &a);
        stack_pop(&values, &b);

        stack_pop(&ops, &op);
        result = apply_op(op, a, b);
        stack_push(&values, &result);
    }

    /* Top of 'values' contains result, return it */
    stack_pop(&values, &result);
    return result;
}
Esempio n. 25
0
/*-
 *---------------------------------------------------------------------
 * ParseDoSrc  --
 *	Given the name of a source, figure out if it is an attribute
 *	and apply it to the targets if it is. Else decide if there is
 *	some attribute which should be applied *to* the source because
 *	of some special target and apply it if so. Otherwise, make the
 *	source be a child of the targets in the list 'targets'
 *
 * Side Effects:
 *	Operator bits may be added to the list of targets or to the source.
 *	The targets may have a new source added to their lists of children.
 *---------------------------------------------------------------------
 */
static void
ParseDoSrc(
    struct growableArray *targets,
    struct growableArray *sources,
    int 	tOp,	/* operator (if any) from special targets */
    const char	*src,	/* name of the source to handle */
    const char *esrc)
{
	GNode *gn = Targ_FindNodei(src, esrc, TARG_CREATE);
	if ((gn->special & SPECIAL_SOURCE) != 0) {
		if (gn->special_op) {
			Array_FindP(targets, ParseDoOp, gn->special_op);
			return;
		} else {
			assert((gn->special & SPECIAL_MASK) == SPECIAL_WAIT);
			waiting++;
			return;
		}
	}

	switch (specType) {
	case SPECIAL_MAIN:
		/*
		 * If we have noted the existence of a .MAIN, it means we need
		 * to add the sources of said target to the list of things
		 * to create.  Note that this will only be invoked if the user
		 * didn't specify a target on the command line. This is to
		 * allow #ifmake's to succeed, or something...
		 */
		Lst_AtEnd(create, gn->name);
		/*
		 * Add the name to the .TARGETS variable as well, so the user
		 * can employ that, if desired.
		 */
		Var_Append(".TARGETS", gn->name);
		return;

	case SPECIAL_ORDER:
		/*
		 * Create proper predecessor/successor links between the
		 * previous source and the current one.
		 */
		if (predecessor != NULL) {
			Lst_AtEnd(&predecessor->successors, gn);
			Lst_AtEnd(&gn->preds, predecessor);
		}
		predecessor = gn;
		break;

	default:
		/*
		 * In the case of a source that was the object of a :: operator,
		 * the attribute is applied to all of its instances (as kept in
		 * the 'cohorts' list of the node) or all the cohorts are linked
		 * to all the targets.
		 */
		apply_op(targets, tOp, gn);
		if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
			LstNode	ln;

			for (ln=Lst_First(&gn->cohorts); ln != NULL;
			    ln = Lst_Adv(ln)){
			    	apply_op(targets, tOp,
				    (GNode *)Lst_Datum(ln));
			}
		}
		break;
	}

	gn->order = waiting;
	Array_AtEnd(sources, gn);
	if (waiting)
		Array_Find(sources, ParseAddDep, gn);
}