예제 #1
0
    // treat powers specially, because it's better to unroll them and
    // avoid a function call if we have an exact integral power
    std::string cpp_cse::print_power(const GiNaC::ex& expr, bool use_count)
      {
        std::ostringstream out;
        size_t n = expr.nops();

        if(n != 2)
          {
            error_context err_ctx = this->data_payload.make_error_context();
            err_ctx.error(ERROR_CSE_POWER_ARGUMENTS);
            out << "std::pow(" << this->print_operands(expr, ",", use_count) << ")";
            return std::string{};
          }

        // set up aliases for base and exponent expressions
        const auto& base_expr = expr.op(0);
        const auto& exponent_expr = expr.op(1);
    
        // perform use-counting on exponent, which is necessary since its values may have been
        // used elsewhere in the CSE tree, even if it is an integer that we will unroll and not use explicitly
        std::string exponent;
        if(use_count) exponent = this->get_symbol_with_use_count(exponent_expr);
        else exponent = this->get_symbol_without_use_count(exponent_expr);

        if(GiNaC::is_a<GiNaC::numeric>(exponent_expr))
          {
            const auto& exp_numeric = GiNaC::ex_to<GiNaC::numeric>(exponent_expr);
        
            std::string base;
            if(use_count) base = this->get_symbol_with_use_count(expr.op(0));
            else base = this->get_symbol_without_use_count(expr.op(0));

            if(GiNaC::is_integer(exp_numeric))
              {
                if(GiNaC::is_nonneg_integer(exp_numeric))
                  {
                    if(exp_numeric.to_int() == 0) out << "1.0";
                    else if(exp_numeric.to_int() == 1) out << unwrap_power(base, base_expr, 1);
                    else if(exp_numeric.to_int() == 2) out << "(" << unwrap_power(base, base_expr, 2) << ")";
                    else if(exp_numeric.to_int() == 3) out << "(" << unwrap_power(base, base_expr, 3) << ")";
                    else if(exp_numeric.to_int() == 4) out << "(" << unwrap_power(base, base_expr, 4) << ")";
                    else out << "std::pow(" << base << "," << exp_numeric.to_int() << ")";
                  }
                else  // negative integer
                  {
                    if(exp_numeric.to_int() == -0) out << "1.0";
                    else if(exp_numeric.to_int() == -1) out << "1.0/" << unwrap_power(base, base_expr, 1);
                    else if(exp_numeric.to_int() == -2) out << "1.0/" << "(" << unwrap_power(base, base_expr, 2) << ")";
                    else if(exp_numeric.to_int() == -3) out << "1.0/" << "(" << unwrap_power(base, base_expr, 3) << ")";
                    else if(exp_numeric.to_int() == -4) out << "1.0/" << "(" << unwrap_power(base, base_expr, 4) << ")";
                    else out << "std::pow(" << base << "," << exp_numeric.to_int() << ")";
                  }
              }
            else  // not an integer
              {
                out << "std::pow(" << base << "," << exponent << ")";
              }
          }

        return(out.str());
      }
// GetSymbols
set<GiNaC::symbol, GiNaC::less> GetSymbols(GiNaC::ex Ex) {
  set<GiNaC::symbol, GiNaC::less> Syms;
  for (auto EI = Ex.preorder_begin(), E = Ex.preorder_end(); EI != E; ++EI)
    if (GiNaC::is_a<GiNaC::symbol>(*EI))
      Syms.insert(GiNaC::ex_to<GiNaC::symbol>(*EI));

  return Syms;
}
// GetCoeffs
vector<GiNaC::ex> GetCoeffs(GiNaC::ex Ex, GiNaC::symbol Sym) {
  assert(Ex.is_polynomial(Sym));
  vector<GiNaC::ex> Coeffs;
  unsigned Degree = Ex.degree(Sym);
  for (unsigned Idx = 0; Idx <= Degree; ++Idx)
    Coeffs.push_back(Ex.coeff(Sym, Idx));
  return Coeffs;
}
Expr Expr::subs(std::vector<std::pair<Expr, Expr> > Subs) { 
  GiNaC::ex Ex = Expr_;
  for (auto& E : Subs) {
    //dbgs() << "Replacing " << E.first.getExpr() << " with " << E.second.getExpr() << " in " << Ex;
    Ex = Ex.subs(E.first.getExpr() == E.second.getExpr());
    //dbgs() << " giving " << Ex << "\n";
  }
  return Expr(Ex);
}
 const flattened_tensor& CovariantRiemannB3Cache::get()
   {
     if(this->B3) return *this->B3;
 
     auto args = res.generate_cache_arguments(printer);
 
     this->B3 = std::make_unique<flattened_tensor>(res.fl.get_flattened_size<field_index>(RESOURCE_INDICES::RIEMANN_B3_INDICES));
 
     const auto max = res.share.get_max_field_index(variance::covariant);
     const auto max_l = res.share.get_max_field_index(variance::contravariant);
 
     SubstitutionMapCache subs_cache(res, printer);
     DerivativeSymbolsCache deriv_cache(res, res.share, printer);
 
     for(field_index i = field_index(0, variance::covariant); i < max; ++i)
       {
         for(field_index j = field_index(0, variance::covariant); j < max; ++j)
           {
             for(field_index k = field_index(0, variance::covariant); k < max; ++k)
               {
                 unsigned int index = res.fl.flatten(i,j,k);
 
                 GiNaC::ex subs_expr = 0;
 
                 if(!res.cache.query(expression_item_types::Riemann_B3_item, index, args, subs_expr))
                   {
                     timing_instrument timer(res.compute_timer);
 
                     auto& deriv_syms = deriv_cache.get();
                     GiNaC::ex expr = 0;
 
                     for(field_index l = field_index(0, variance::contravariant); l < max_l; ++l)
                       {
                         auto Rie_ijk = (*res.Rie_T)(static_cast<unsigned int>(k), static_cast<unsigned int>(i),
                                                     static_cast<unsigned int>(j), static_cast<unsigned int>(l));
                         auto Rie_ikj = (*res.Rie_T)(static_cast<unsigned int>(k), static_cast<unsigned int>(j),
                                                     static_cast<unsigned int>(i), static_cast<unsigned int>(l));
                         
                         auto Rie_sym = (Rie_ijk + Rie_ikj) / 2;
                         
                         expr += Rie_sym * deriv_syms[res.fl.flatten(l)];
                       }
 
                     // get substitution map
                     GiNaC::exmap& subs_map = subs_cache.get();
                     subs_expr = expr.subs(subs_map, GiNaC::subs_options::no_pattern);
                     
                     res.cache.store(expression_item_types::Riemann_B3_item, index, args, subs_expr);
                   }
                 
                 (*this->B3)[index] = subs_expr;
               }
           }
       }
 
     return *this->B3;
   }
int Expr::getMaxDegree() const {
  int Max = 0;
  for (auto It = Expr_.preorder_begin(), E = Expr_.preorder_end();
       It != E; ++It) {
    GiNaC::ex Ex = *It;
    if (GiNaC::is_a<GiNaC::power>(Ex))
      Max = std::max(Max, GiNaC::ex_to<GiNaC::numeric>(Ex.op(1)).to_int());
    else if (GiNaC::is_a<GiNaC::symbol>(Ex))
      Max = std::max(Max, 1);
  }
  return Max;
}
  MatrixWrapper::SymmetricMatrix
  NonLinearAnalyticConditionalGaussian_Ginac::CovarianceGet() const
  {
    if (cond_size!=0)
      {
	MatrixWrapper::ColumnVector u_num   (u_size);
	MatrixWrapper::ColumnVector x_num   (x_size);
	GiNaC::ex substitute (func_size);
	MatrixWrapper::Matrix D             (func_size,cond_size);


	u_num = ConditionalArgumentGet(1);
	x_num = ConditionalArgumentGet(0);

	for (unsigned int i=0; i<cond_size; i++)
	  {
	    // temp variable to substitute in
	    substitute = dfunc_dcond[i];

	    // substitute all u_sym with u_num
	    for (unsigned int j=0; j<u_size; j++)
	      substitute = substitute.subs( u_sym[j]==u_num(j+1) );

	    // substitute all x_sym with x_num
	    for (unsigned int j=0; j<x_size; j++)
	      substitute = substitute.subs( x_sym[j]==x_num(j+1) );

	    // convert substitute back to matrix
	    GiNaC::matrix substitute_matrix = GiNaC::ex_to<GiNaC::matrix>(substitute);

	    // build matrix D
	    for (unsigned int j=0; j<func_size; j++)
	      D(j+1,i+1) = GiNaC::ex_to<GiNaC::numeric>( substitute_matrix(j,0).evalf() ).to_double();
	  }
	//cout << "D: " << D << endl;
	//cout << "CondCov:\n" << (Matrix)cond_covariance << endl;
	MatrixWrapper::Matrix temp = D * (MatrixWrapper::Matrix)AdditiveNoiseSigmaGet() * D.transpose();

	// convert func_covariance_matrix to symmetric matrix
	MatrixWrapper::SymmetricMatrix additiveNoise(temp.rows());
	temp.convertToSymmetricMatrix(additiveNoise);
	return additiveNoise;

      }
    else
      {
	return AdditiveNoiseSigmaGet();
      }
  }
GiNaC::ex operator_from_graph(KontsevichGraph graph, PoissonStructure poisson, std::vector<GiNaC::ex> arguments)
{
    // TODO: check if graph.external() == arguments.size()
    GiNaC::ex result = 0;
    map_operator_coefficients_from_graph(graph, poisson, [&result, &poisson, &arguments](std::vector< std::multiset<size_t> > derivatives, GiNaC::ex summand) {
        GiNaC::ex tail = 1;
        for (size_t m = 0; m != arguments.size(); ++m)
        {
            GiNaC::ex factor = arguments[m];
            for (size_t idx : derivatives[m])
                factor = factor.diff(poisson.coordinates[idx]);
            tail *= factor;
        }
        result += summand * tail;
    });
    return result;
}
  MatrixWrapper::ColumnVector
  NonLinearAnalyticConditionalGaussian_Ginac::ExpectedValueGet() const
  {
    MatrixWrapper::ColumnVector u_num   (u_size);
    MatrixWrapper::ColumnVector x_num   (x_size);
    MatrixWrapper::ColumnVector func_num(func_size);
    GiNaC::ex substitute (func_size);
    MatrixWrapper::ColumnVector expected(func_size);

    u_num = ConditionalArgumentGet(1);
    x_num = ConditionalArgumentGet(0);

    // use Mu of additive noise
    if (cond_size!=0)
      for (unsigned int i=0; i<u_size; i++)
	for (unsigned int j=0; j<cond_size; j++)
	  if (u_sym[i] == cond_sym[j])
	      u_num(i+1) += (this->AdditiveNoiseMuGet())(j+1);


    // evaluate func
    for (unsigned int i=0; i<func_size; i++)
      {
	// temp variable to substitute in
	substitute = func_sym(i,0);

	// substitute all u_sym with u_num
	for (unsigned int j=0; j<u_size; j++)
	  substitute = substitute.subs( u_sym[j]==u_num(j+1) );

	// substitute all x_sym with x_num
	for (unsigned int j=0; j<x_size; j++)
	  substitute = substitute.subs( x_sym[j]==x_num(j+1) );

	// build matrix func_num
	func_num(i+1) = GiNaC::ex_to<GiNaC::numeric>( substitute.evalf() ).to_double();
      }
    expected = func_num;

    if (cond_size==0)
      expected += AdditiveNoiseMuGet();

    return expected;
  }
예제 #10
0
파일: vf.cpp 프로젝트: iraikov/vfgen-nest
GiNaC::lst VectorField::FindVarsInEx(const GiNaC::ex &e)
    {
    unsigned k;
    GiNaC::lst vlist;
    for (k = 0; k < varname_list.nops(); ++k)
        {
        if (e.has(varname_list[k]))
            vlist.append(varname_list[k]);
        }
    return vlist;
    }
예제 #11
0
// NegativeOrdinate
// Returns the ranges for which the ordinate is negative.
vector<pair<GiNaC::ex, GiNaC::ex> >
    NegativeOrdinate(vector<double> Vec, GiNaC::symbol Sym, GiNaC::ex Ex) {
  vector<pair<GiNaC::ex, GiNaC::ex> > Negs;

  // No real roots - it's either all positive or all negative.
  if (Vec.empty()) {
    GiNaC::ex Subs = Ex.subs(Sym == 0);
    if (GiNaC::is_a<GiNaC::numeric>(Subs) &&
        GiNaC::ex_to<GiNaC::numeric>(Subs).is_negative())
        Negs.push_back(make_pair(GiNaC::inf(-1), GiNaC::inf(1)));
    return Negs;
  }

  sort(Vec.begin(), Vec.end());

  GiNaC::ex FirstSubs = Ex.subs(Sym == GiNaC::numeric(Round(Vec[0] - 1.0f)));
  // Negative at -inf to the first root minus one.
  if (GiNaC::is_a<GiNaC::numeric>(FirstSubs) &&
      GiNaC::ex_to<GiNaC::numeric>(FirstSubs).is_negative())
    Negs.push_back(make_pair(GiNaC::inf(-1), GiNaC::numeric(Vec[0] - 1.0f)));

  for (unsigned Idx = 1; Idx < Vec.size(); ++Idx) {
    long int E = Round(Vec[Idx]);
    // Check if it's negative to the right.
    GiNaC::ex Subs = Ex.subs(Sym == GiNaC::numeric(E + 1));
    if (GiNaC::is_a<GiNaC::numeric>(Subs))
      if (GiNaC::ex_to<GiNaC::numeric>(Subs).is_negative()) {
        // Last root, it's negative all the way to +inf.
        if (Idx == Vec.size() - 1)
          Negs.push_back(make_pair(GiNaC::numeric(E + 1), GiNaC::inf(1)));
        // Not the last root, it's negative from this root to the next.
        else
          Negs.push_back(make_pair(GiNaC::numeric(E + 1),
                                   GiNaC::numeric(Round(Vec[Idx + 1] - 1))));
      }
  }

  return Negs;
}
  MatrixWrapper::Matrix
  NonLinearAnalyticConditionalGaussian_Ginac::dfGet(unsigned int i) const
  {
    // Check if i = 0, since this is the old df_dxGet method!
    assert(i == 0);

    // evaluate function
    MatrixWrapper::ColumnVector u_num   (u_size);
    MatrixWrapper::ColumnVector x_num   (x_size);
    GiNaC::ex substitute (func_size);
    MatrixWrapper::Matrix F             (func_size, x_size);

    u_num = ConditionalArgumentGet(1);
    x_num = ConditionalArgumentGet(0);

    // numeric evaluation of derivative: dfunc_dx = F
    for (unsigned int i=0; i<x_size; i++)
      {
	// temp variable to substitute in
	substitute = dfunc_dx[i];

	// substitute all u_sym with u_num
	for (unsigned int j=0; j<u_size; j++)
	  substitute = substitute.subs( u_sym[j]==u_num(j+1) );

	// substitute all x_sym with x_num
	for (unsigned int j=0; j<x_size; j++)
	  substitute = substitute.subs( x_sym[j]==x_num(j+1) );

	// convert substitute to matrix. Now all elements in matrix are accessible
	GiNaC::matrix substitute_matrix = GiNaC::ex_to<GiNaC::matrix>(substitute);

	// build matrix F
	for (unsigned int j=0; j<func_size; j++)
	  F(j+1,i+1) = GiNaC::ex_to<GiNaC::numeric>( substitute_matrix(j,0).evalf() ).to_double();
      }

    return F;
  }
예제 #13
0
bool TestExpr::runOnModule(Module&) {
  Expr A("a");
  Expr B("b");

  assert(A + B == B + A);
  assert(A * B == B * A);
  assert(A - B != B - A);
  assert(A / B != B / A);

  //map<GiNaC::symbol, int> GetMaxExps(GiNaC::ex Ex); 
  GiNaC::symbol GA("a");
  GiNaC::symbol GB("b");
  GiNaC::ex EZ = 5 * GA * GA * GA + 4 * GB + 1;

  assert(EZ.is_polynomial(GA));
  assert(EZ.degree(GA) == 3);
  assert(EZ.coeff(GA, 3) == GiNaC::numeric(5));
  assert(EZ.coeff(GA, 2) == GiNaC::numeric(0));
  assert(EZ.coeff(GA, 1) == GiNaC::numeric(0));
  assert(EZ.coeff(GA, 0) == 4 * GB + 1);

  assert(EZ.is_polynomial(GB));
  assert(EZ.degree(GB) == 1);
  assert(EZ.coeff(GB, 1) == GiNaC::numeric(4));
  assert(EZ.coeff(GB, 0) == 5 * GA * GA * GA + 1);

  auto SEZ = GetSymbols(EZ);
  assert(SEZ.size() == 2);
  assert(SEZ.count(GA) && SEZ.count(GB));

  auto CEZGA = GetCoeffs(EZ, GA);
  assert(CEZGA.size() == 4);
  assert(CEZGA[3] == GiNaC::numeric(5));
  assert(CEZGA[2] == GiNaC::numeric(0));
  assert(CEZGA[1] == GiNaC::numeric(0));
  assert(CEZGA[0] == 4 * GB + 1);

  auto CEZGB = GetCoeffs(EZ, GB);
  assert(CEZGB.size() == 2);
  assert(CEZGB[1] == GiNaC::numeric(4));
  assert(CEZGB[0] == 5 * GA * GA * GA + 1);

  auto EF = GA * GA - 1;
  auto EFSolve = Solve(EF, GA);
  assert(EFSolve.size() == 2);
  assert(Round(EFSolve[0]) == -1 || Round(EFSolve[1]) == -1);
  assert(Round(EFSolve[0]) == 1  || Round(EFSolve[1]) == 1);
  auto EFNegs = NegativeOrdinate(EFSolve, GA, EF); 
  assert(EFNegs.empty());

  EF = GA * GA - 2 * GA + 1;
  EFSolve = Solve(EF, GA);
  assert(EFSolve.size() == 2);
  assert(Round(EFSolve[0]) == 1 && Round(EFSolve[1]) == 1);
  EFNegs = NegativeOrdinate(EFSolve, GA, EF); 
  assert(EFNegs.empty());

  EF = (-1) * GA * GA + GA - 1;
  EFSolve = Solve(EF, GA);
  assert(EFSolve.size() == 0);
  EFNegs = NegativeOrdinate(EFSolve, GA, EF); 
  assert(EFNegs.size() == 1);
  assert(EFNegs[0].first.is_equal(GiNaC::inf(-1)));
  assert(EFNegs[0].second.is_equal(GiNaC::inf(1)));

  return false;
}
예제 #14
0
 bool operator()(GiNaC::ex const& l, GiNaC::ex const& r) const {
   return l.compare(r) < 0;
 }
예제 #15
0
double Attribute::EvalCompiledExpression (double const val, std::string const attrib ) {

//cout << GetPrototype()->GetName() << " ??  at pointer num " << m_cur_fp << " -> compiled = " << m_compiled.at(m_cur_fp) << endl;
 	if (!m_compiled.at(m_cur_fp)) {
 		//substitute all attributes with numbers in GiNaC expression, except the attribute
 		//which serves as the free parameter for runtime compilation
 		GiNaC::lst symlist;
 		GiNaC::lst numlist;
 		for (unsigned int i=0; i<m_subjects.size() ; i++) {
 			Attribute* a = m_subjects.at(i);
 			if (a->GetName() == attrib) continue;
 	        symlist.append( get_symbol(a->GetSymbol()) );
 			if (a->GetTypeID()==typeid(  double*).name()) { numlist.append(a->GetMember  <double>() ); continue; }
 			if (a->GetTypeID()==typeid(     int*).name()) { numlist.append(a->GetMember     <int>() ); continue; }
 			if (a->GetTypeID()==typeid(    long*).name()) { numlist.append(a->GetMember    <long>() ); continue; }
 			if (a->GetTypeID()==typeid(unsigned*).name()) { numlist.append(a->GetMember<unsigned>() ); continue; }
 			if (a->GetTypeID()==typeid(    bool*).name()) { numlist.append(a->GetMember    <bool>() ); continue; }
 		}

		GiNaC::ex e = GiNaC::evalf((symlist.nops()==0)?m_expression:m_expression.subs(symlist,numlist));

		//add function pointers
		m_fp.push_back(NULL);
		m_fpi.push_back(NULL);
		//compile the GiNaC expression
		try {
			//fairly easy for real valued expressions
			if (!m_complex) {
				compile_ex(e, get_symbol(GetPrototype()->GetAttribute(attrib)->GetSymbol()), m_fp.at(m_num_fp));
			}
			//more work to do, since GiNaC::realsymbol does not behave as expected (and it is therefore not used at all)
			else {
				stringstream se; se << e; std::string formula = se.str();
				std::string sym  = GetPrototype()->GetAttribute(attrib)->GetSymbol();
				std::string asym = "abs(VarForEvalCompiledExpression)";
				Prototype::ReplaceString(formula,sym,asym);
				GiNaC::lst symlist;
				symlist.append( get_symbol("VarForEvalCompiledExpression") );
				GiNaC::ex ea = GiNaC::ex(formula,symlist);
				symlist.remove_all();
				symlist.append( get_symbol(sym) );

				GiNaC::ex ear = ea.real_part();
				stringstream ser;  ser << ear; formula = ser.str();
				if ( Prototype::ReplaceString(formula,asym,sym) ) {
					ear  = GiNaC::ex(formula,symlist);
					compile_ex(ear, get_symbol(GetPrototype()->GetAttribute(attrib)->GetSymbol()), m_fp.at(m_num_fp));
				}

				GiNaC::ex eai = ea.imag_part();
				stringstream sei;  sei << eai; formula = sei.str();
				if ( Prototype::ReplaceString(formula,asym,sym) ) {
					eai  = GiNaC::ex(formula,symlist);
					compile_ex(eai, get_symbol(GetPrototype()->GetAttribute(attrib)->GetSymbol()), m_fpi.at(m_num_fp));
				}
			}
 			//cout << " compiling expression " << e << " of attribute " << GetName() << " in module " << GetPrototype()->GetName() << endl;
 		 	m_num_fp++;
		}
	 	catch (exception &p) {
 			cout << " Warning: attribute " << GetName() << " of module " << GetPrototype()->GetName() << endl << endl
 				 << " function Attribute::EvalCompiledExpression" << endl
 				 << " No external runtime compiler available: " << p.what() << endl
				 << " Falling back to (slow) analytic evaluation!" << endl << endl
				 << " Hint: if you have a shell and gcc on your system, create the one-liner " << endl << endl
				 << "    #!/bin/sh" << endl
				 << "    gcc -x c -fPIC -shared -o $1.so $1" << endl << endl
 		         << " name it \"ginac-excompiler\", and put it somewhere in your search path." << endl << endl;
	 		m_ginac_excomp = false;
	 	}
		m_compiled.at(m_cur_fp) = true; //even if compilation failed, as we don't have to try a second time!
 	}

	//if compilation failed, invoke slow analytic evaluation
	if (!m_ginac_excomp ) {
		*((double*) GetPrototype()->GetAttribute(attrib)-> GetAddress()) = val;
 		EvalExpression();
 		return *((double*) GetAddress());
 	}

	//invoke fast runtime compiled routines
 	if (m_fpi.at(m_cur_fp) != NULL ) m_imaginary = m_fpi.at(m_cur_fp)(val);
	if ( m_fp.at(m_cur_fp) != NULL ) return m_fp.at(m_cur_fp)(val);

	return 0.0;

}
예제 #16
0
파일: main.cpp 프로젝트: Murtaught/CompMath
double eval_at(const math::ex &expr, double x_val, double y_val)
{
    math::ex temp = expr.subs(x == x_val).subs(y == y_val).evalf();
    return math::ex_to<math::numeric>( temp ).to_double();
}
예제 #17
0
// Solve
vector<double> Solve(GiNaC::ex Ex, GiNaC::symbol Sym) {
  vector<double> Roots;

  unsigned Degree = Ex.degree(Sym);
  auto Coeffs = GetCoeffs(Ex, Sym);
  // Bhaskara.
  if (Degree == 2) {
    GiNaC::ex A = Coeffs[2];
    GiNaC::ex B = Coeffs[1];
    GiNaC::ex C = Coeffs[0];

    GiNaC::ex Delta = B*B - 4 * A * C;
    // Guaranteed real roots.
    if (GiNaC::is_a<GiNaC::numeric>(Delta) &&
        !GiNaC::ex_to<GiNaC::numeric>(Delta).is_negative()) {
      GiNaC::ex Delta = GiNaC::sqrt(B*B - 4 * A * C).evalf();
      GiNaC::ex One = ((-B) + Delta)/(2*A);
      GiNaC::ex Two = ((-B) - Delta)/(2*A);
      if (GiNaC::is_a<GiNaC::numeric>(One))
        Roots.push_back(GiNaC::ex_to<GiNaC::numeric>(One.evalf()).to_double());
      if (GiNaC::is_a<GiNaC::numeric>(Two))
        Roots.push_back(GiNaC::ex_to<GiNaC::numeric>(Two.evalf()).to_double());
    }
  }
  // Cardano.
  else if (Degree == 3) {
    GiNaC::ex A = Coeffs[3];
    GiNaC::ex B = Coeffs[2];
    GiNaC::ex C = Coeffs[1];
    GiNaC::ex D = Coeffs[1];

    GiNaC::ex Delta0 = B*B - 3 * A * C;
    GiNaC::ex Delta1 = 2 * B*B*B - 9 * A * B * C + 27 * A * A * D;
    GiNaC::ex CD = Delta1 + GiNaC::sqrt(Delta1 * Delta1 - 4 * GiNaC::pow(Delta0, 3));
    CD = CD/2;
    CD = GiNaC::pow(CD, GiNaC::numeric(1)/3);

    GiNaC::symbol U("u");
    GiNaC::ex Var = GiNaC::numeric(-1)/(3 * A) * (B + U * CD + Delta0/(U * CD));
    GiNaC::ex One   = Var.subs(U == 1);
    GiNaC::ex Two   = Var.subs(U == ((-1 + GiNaC::sqrt(GiNaC::numeric(-3)))/2));
    GiNaC::ex Three = Var.subs(U == ((-1 - GiNaC::sqrt(GiNaC::numeric(-3)))/2));
    if (GiNaC::is_a<GiNaC::numeric>(One))
      Roots.push_back(GiNaC::ex_to<GiNaC::numeric>(One.evalf()).to_double());
    if (GiNaC::is_a<GiNaC::numeric>(Two))
      Roots.push_back(GiNaC::ex_to<GiNaC::numeric>(Two.evalf()).to_double());
    if (GiNaC::is_a<GiNaC::numeric>(Three))
      Roots.push_back(GiNaC::ex_to<GiNaC::numeric>(Three.evalf()).to_double());
  }

  return Roots;
}
예제 #18
0
void Attribute::EvalExpression () {
  
	if (m_formula.empty()) return;
	
	//strings: simply replace attribute symbol by its value
	if (GetTypeID()==typeid(std::string*).name()) {
		std::string expr = m_formula;
		for (unsigned int i=0; i<m_subjects.size() ; i++) {
			Attribute* a = m_subjects.at(i);
			stringstream key;
			if (a->GetTypeID()==typeid(  double*).name()) key << a->GetMember  <double>() ; 
			if (a->GetTypeID()==typeid(     int*).name()) key << a->GetMember     <int>() ; 
			if (a->GetTypeID()==typeid(    long*).name()) key << a->GetMember    <long>() ; 
			if (a->GetTypeID()==typeid(unsigned*).name()) key << a->GetMember<unsigned>() ; 
			if (a->GetTypeID()==typeid(    bool*).name()) key << a->GetMember    <bool>() ; 
			std::string  SymbolName = a->GetPrototype()->GetName() + "x" + a->GetName();
			Prototype::ReplaceString(expr,SymbolName,key.str());
		}
		WriteMember(expr);
		//if (GetName()=="Filename") cout << " Eval: " << expr <<  endl;
		return;	  
	}

	//collect symbols and corresponding member-values from observed attributes
	GiNaC::lst numlist;
	for (unsigned int i=0; i<m_subjects.size() ; i++) {
		Attribute* a = m_subjects.at(i);
		if (a->GetTypeID()==typeid(  double*).name()) { numlist.append(a->GetMember  <double>() ); continue; }
		if (a->GetTypeID()==typeid(     int*).name()) { numlist.append(a->GetMember     <int>() ); continue; }
		if (a->GetTypeID()==typeid(    long*).name()) { numlist.append(a->GetMember    <long>() ); continue; }
		if (a->GetTypeID()==typeid(unsigned*).name()) { numlist.append(a->GetMember<unsigned>() ); continue; }
		if (a->GetTypeID()==typeid(    bool*).name()) { numlist.append(a->GetMember    <bool>() ); continue; }
	}

	
	//numeric evaluation of GiNaC expression
	GiNaC::ex e = m_expression.subs(m_symlist,numlist);	
	m_static_vector = m_prototype->GetVector(); // static pointer to evaluate the Vector function
	e = GiNaC::evalf(e);
	double d = 0.0;
	if (GiNaC::is_a<GiNaC::numeric>(e)) {
		if ( m_complex ) m_imaginary = -0.5 * GiNaC::ex_to<GiNaC::numeric>( (e-e.conjugate())*GiNaC::I ).to_double();
		d = GiNaC::ex_to<GiNaC::numeric>( e ).to_double();//default is real-part
	}


	//overwrite private member
	if (m_datatype==typeid(  double*).name() ) WriteMember((double)   d );
	if (m_datatype==typeid(     int*).name() ) WriteMember((int)      d );
	if (m_datatype==typeid(    long*).name() ) WriteMember((long)     d );
	if (m_datatype==typeid(unsigned*).name() ) WriteMember((unsigned) d );
	if (m_datatype==typeid(    bool*).name() ) WriteMember((bool)     d );

	//  for dynamic change of runtime compiled attributes after notification!
	if (m_ginac_excomp && m_cur_fp==m_num_fp && m_num_fp>0) {
		//cout << "!!! " << GetName() << " : NFP =" << GetNumberFunctionPointers() << endl;
		//cout << "!!! " << GetName() << " : CFP =" << GetCurrentFunctionPointer() << endl;
		//cout << "!!! " << GetName() << " : size=" << m_compiled.size() << endl;

			if (m_compiled.size() == m_cur_fp ) m_compiled.push_back(false);
		}
}