- debugmsg("numeric constructor from string",LOGLEVEL_CONSTRUCT);
- value = new ::cl_N(0);
- // parse complex numbers (functional but not completely safe, unfortunately
- // std::string does not understand regexpese):
- // ss should represent a simple sum like 2+5*I
- std::string ss(s);
- // make it safe by adding explicit sign
- if (ss.at(0) != '+' && ss.at(0) != '-' && ss.at(0) != '#')
- ss = '+' + ss;
- std::string::size_type delim;
- do {
- // chop ss into terms from left to right
- std::string term;
- bool imaginary = false;
- delim = ss.find_first_of(std::string("+-"),1);
- // Do we have an exponent marker like "31.415E-1"? If so, hop on!
- if (delim != std::string::npos &&
- ss.at(delim-1) == 'E')
- delim = ss.find_first_of(std::string("+-"),delim+1);
- term = ss.substr(0,delim);
- if (delim != std::string::npos)
- ss = ss.substr(delim);
- // is the term imaginary?
- if (term.find("I") != std::string::npos) {
- // erase 'I':
- term = term.replace(term.find("I"),1,"");
- // erase '*':
- if (term.find("*") != std::string::npos)
- term = term.replace(term.find("*"),1,"");
- // correct for trivial +/-I without explicit factor on I:
- if (term.size() == 1)
- term += "1";
- imaginary = true;
- }
- const char *cs = term.c_str();
- // CLN's short types are not useful within the GiNaC framework, hence
- // we go straight to the construction of a long float. Simply using
- // cl_N(s) would require us to use add a CLN exponent mark, otherwise
- // we would not be save from over-/underflows.
- if (strchr(cs, '.'))
- if (imaginary)
- *value = *value + ::complex(cl_I(0),::cl_LF(cs));
- else
- *value = *value + ::cl_LF(cs);
- else
- if (imaginary)
- *value = *value + ::complex(cl_I(0),::cl_R(cs));
- else
- *value = *value + ::cl_R(cs);
- } while(delim != std::string::npos);
- calchash();
- setflag(status_flags::evaluated|
- status_flags::hash_calculated);
+ debugmsg("numeric constructor from string",LOGLEVEL_CONSTRUCT);
+ cln::cl_N ctorval = 0;
+ // parse complex numbers (functional but not completely safe, unfortunately
+ // std::string does not understand regexpese):
+ // ss should represent a simple sum like 2+5*I
+ std::string ss(s);
+ // make it safe by adding explicit sign
+ if (ss.at(0) != '+' && ss.at(0) != '-' && ss.at(0) != '#')
+ ss = '+' + ss;
+ std::string::size_type delim;
+ do {
+ // chop ss into terms from left to right
+ std::string term;
+ bool imaginary = false;
+ delim = ss.find_first_of(std::string("+-"),1);
+ // Do we have an exponent marker like "31.415E-1"? If so, hop on!
+ if ((delim != std::string::npos) && (ss.at(delim-1) == 'E'))
+ delim = ss.find_first_of(std::string("+-"),delim+1);
+ term = ss.substr(0,delim);
+ if (delim != std::string::npos)
+ ss = ss.substr(delim);
+ // is the term imaginary?
+ if (term.find("I") != std::string::npos) {
+ // erase 'I':
+ term = term.replace(term.find("I"),1,"");
+ // erase '*':
+ if (term.find("*") != std::string::npos)
+ term = term.replace(term.find("*"),1,"");
+ // correct for trivial +/-I without explicit factor on I:
+ if (term.size() == 1)
+ term += "1";
+ imaginary = true;
+ }
+ if (term.find(".") != std::string::npos) {
+ // CLN's short type cl_SF is not very useful within the GiNaC
+ // framework where we are mainly interested in the arbitrary
+ // precision type cl_LF. Hence we go straight to the construction
+ // of generic floats. In order to create them we have to convert
+ // our own floating point notation used for output and construction
+ // from char * to CLN's generic notation:
+ // 3.14 --> 3.14e0_<Digits>
+ // 31.4E-1 --> 31.4e-1_<Digits>
+ // and s on.
+ // No exponent marker? Let's add a trivial one.
+ if (term.find("E") == std::string::npos)
+ term += "E0";
+ // E to lower case
+ term = term.replace(term.find("E"),1,"e");
+ // append _<Digits> to term
+#if defined(HAVE_SSTREAM)
+ std::ostringstream buf;
+ buf << unsigned(Digits) << std::ends;
+ term += "_" + buf.str();
+#else
+ char buf[14];
+ std::ostrstream(buf,sizeof(buf)) << unsigned(Digits) << std::ends;
+ term += "_" + string(buf);
+#endif
+ // construct float using cln::cl_F(const char *) ctor.
+ if (imaginary)
+ ctorval = ctorval + cln::complex(cln::cl_I(0),cln::cl_F(term.c_str()));
+ else
+ ctorval = ctorval + cln::cl_F(term.c_str());
+ } else {
+ // not a floating point number...
+ if (imaginary)
+ ctorval = ctorval + cln::complex(cln::cl_I(0),cln::cl_R(term.c_str()));
+ else
+ ctorval = ctorval + cln::cl_R(term.c_str());
+ }
+ } while(delim != std::string::npos);
+ value = ctorval;
+ calchash();
+ setflag(status_flags::evaluated |
+ status_flags::expanded |
+ status_flags::hash_calculated);