main.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. // (C) Copyright John Maddock 2006.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #define BOOST_TEST_MODULE foobar
  6. #define BOOST_UBLAS_TYPE_CHECK_EPSILON (type_traits<real_type>::type_sqrt (boost::math::tools::epsilon <real_type>()))
  7. #define BOOST_UBLAS_TYPE_CHECK_MIN (type_traits<real_type>::type_sqrt ( boost::math::tools::min_value<real_type>()))
  8. #define BOOST_UBLAS_NDEBUG
  9. #include "multiprecision.hpp"
  10. #include <boost/math/tools/remez.hpp>
  11. #include <boost/math/tools/test.hpp>
  12. #include <boost/math/special_functions/binomial.hpp>
  13. #include <boost/spirit/include/classic_core.hpp>
  14. #include <boost/spirit/include/classic_actor.hpp>
  15. #include <boost/lexical_cast.hpp>
  16. #include <iostream>
  17. #include <iomanip>
  18. #include <string>
  19. #include <boost/test/included/unit_test.hpp> // for test_main
  20. #include <boost/multiprecision/cpp_bin_float.hpp>
  21. extern mp_type f(const mp_type& x, int variant);
  22. extern void show_extra(
  23. const boost::math::tools::polynomial<mp_type>& n,
  24. const boost::math::tools::polynomial<mp_type>& d,
  25. const mp_type& x_offset,
  26. const mp_type& y_offset,
  27. int variant);
  28. using namespace boost::spirit::classic;
  29. mp_type a(0), b(1); // range to optimise over
  30. bool rel_error(true);
  31. bool pin(false);
  32. int orderN(3);
  33. int orderD(1);
  34. int target_precision = boost::math::tools::digits<long double>();
  35. int working_precision = target_precision * 2;
  36. bool started(false);
  37. int variant(0);
  38. int skew(0);
  39. int brake(50);
  40. mp_type x_offset(0), y_offset(0), x_scale(1);
  41. bool auto_offset_y;
  42. boost::shared_ptr<boost::math::tools::remez_minimax<mp_type> > p_remez;
  43. mp_type the_function(const mp_type& val)
  44. {
  45. return f(x_scale * (val + x_offset), variant) + y_offset;
  46. }
  47. void step_some(unsigned count)
  48. {
  49. try{
  50. set_working_precision(working_precision);
  51. if(!started)
  52. {
  53. //
  54. // If we have an automatic y-offset calculate it now:
  55. //
  56. if(auto_offset_y)
  57. {
  58. mp_type fa, fb, fm;
  59. fa = f(x_scale * (a + x_offset), variant);
  60. fb = f(x_scale * (b + x_offset), variant);
  61. fm = f(x_scale * ((a+b)/2 + x_offset), variant);
  62. y_offset = -(fa + fb + fm) / 3;
  63. set_output_precision(5);
  64. std::cout << "Setting auto-y-offset to " << y_offset << std::endl;
  65. }
  66. //
  67. // Truncate offsets to float precision:
  68. //
  69. x_offset = round_to_precision(x_offset, 20);
  70. y_offset = round_to_precision(y_offset, 20);
  71. //
  72. // Construct new Remez state machine:
  73. //
  74. p_remez.reset(new boost::math::tools::remez_minimax<mp_type>(
  75. &the_function,
  76. orderN, orderD,
  77. a, b,
  78. pin,
  79. rel_error,
  80. skew,
  81. working_precision));
  82. std::cout << "Max error in interpolated form: " << std::setprecision(3) << std::scientific << boost::math::tools::real_cast<double>(p_remez->max_error()) << std::endl;
  83. //
  84. // Signal that we've started:
  85. //
  86. started = true;
  87. }
  88. unsigned i;
  89. for(i = 0; i < count; ++i)
  90. {
  91. std::cout << "Stepping..." << std::endl;
  92. p_remez->set_brake(brake);
  93. mp_type r = p_remez->iterate();
  94. set_output_precision(3);
  95. std::cout
  96. << "Maximum Deviation Found: " << std::setprecision(3) << std::scientific << boost::math::tools::real_cast<double>(p_remez->max_error()) << std::endl
  97. << "Expected Error Term: " << std::setprecision(3) << std::scientific << boost::math::tools::real_cast<double>(p_remez->error_term()) << std::endl
  98. << "Maximum Relative Change in Control Points: " << std::setprecision(3) << std::scientific << boost::math::tools::real_cast<double>(r) << std::endl;
  99. }
  100. }
  101. catch(const std::exception& e)
  102. {
  103. std::cout << "Step failed with exception: " << e.what() << std::endl;
  104. }
  105. }
  106. void step(const char*, const char*)
  107. {
  108. step_some(1);
  109. }
  110. void show(const char*, const char*)
  111. {
  112. set_working_precision(working_precision);
  113. if(started)
  114. {
  115. boost::math::tools::polynomial<mp_type> n = p_remez->numerator();
  116. boost::math::tools::polynomial<mp_type> d = p_remez->denominator();
  117. std::vector<mp_type> cn = n.chebyshev();
  118. std::vector<mp_type> cd = d.chebyshev();
  119. int prec = 2 + (target_precision * 3010LL)/10000;
  120. std::cout << std::scientific << std::setprecision(prec);
  121. set_output_precision(prec);
  122. boost::numeric::ublas::vector<mp_type> v = p_remez->zero_points();
  123. std::cout << " Zeros = {\n";
  124. unsigned i;
  125. for(i = 0; i < v.size(); ++i)
  126. {
  127. std::cout << " " << v[i] << std::endl;
  128. }
  129. std::cout << " }\n";
  130. v = p_remez->chebyshev_points();
  131. std::cout << " Chebeshev Control Points = {\n";
  132. for(i = 0; i < v.size(); ++i)
  133. {
  134. std::cout << " " << v[i] << std::endl;
  135. }
  136. std::cout << " }\n";
  137. std::cout << "X offset: " << x_offset << std::endl;
  138. std::cout << "X scale: " << x_scale << std::endl;
  139. std::cout << "Y offset: " << y_offset << std::endl;
  140. std::cout << "P = {";
  141. for(i = 0; i < n.size(); ++i)
  142. {
  143. std::cout << " " << n[i] << "L," << std::endl;
  144. }
  145. std::cout << " }\n";
  146. std::cout << "Q = {";
  147. for(i = 0; i < d.size(); ++i)
  148. {
  149. std::cout << " " << d[i] << "L," << std::endl;
  150. }
  151. std::cout << " }\n";
  152. std::cout << "CP = {";
  153. for(i = 0; i < cn.size(); ++i)
  154. {
  155. std::cout << " " << cn[i] << "L," << std::endl;
  156. }
  157. std::cout << " }\n";
  158. std::cout << "CQ = {";
  159. for(i = 0; i < cd.size(); ++i)
  160. {
  161. std::cout << " " << cd[i] << "L," << std::endl;
  162. }
  163. std::cout << " }\n";
  164. show_extra(n, d, x_offset, y_offset, variant);
  165. }
  166. else
  167. {
  168. std::cerr << "Nothing to display" << std::endl;
  169. }
  170. }
  171. void do_graph(unsigned points)
  172. {
  173. set_working_precision(working_precision);
  174. mp_type step = (b - a) / (points - 1);
  175. mp_type x = a;
  176. while(points > 1)
  177. {
  178. set_output_precision(10);
  179. std::cout << std::setprecision(10) << std::setw(30) << std::left
  180. << boost::lexical_cast<std::string>(x) << the_function(x) << std::endl;
  181. --points;
  182. x += step;
  183. }
  184. std::cout << std::setprecision(10) << std::setw(30) << std::left
  185. << boost::lexical_cast<std::string>(b) << the_function(b) << std::endl;
  186. }
  187. void graph(const char*, const char*)
  188. {
  189. do_graph(3);
  190. }
  191. template <class T>
  192. mp_type convert_to_rr(const T& val)
  193. {
  194. return val;
  195. }
  196. template <class Backend, boost::multiprecision::expression_template_option ET>
  197. mp_type convert_to_rr(const boost::multiprecision::number<Backend, ET>& val)
  198. {
  199. return boost::lexical_cast<mp_type>(val.str());
  200. }
  201. template <class T>
  202. void do_test(T, const char* name)
  203. {
  204. set_working_precision(working_precision);
  205. if(started)
  206. {
  207. //
  208. // We want to test the approximation at fixed precision:
  209. // either float, double or long double. Begin by getting the
  210. // polynomials:
  211. //
  212. boost::math::tools::polynomial<T> n, d;
  213. boost::math::tools::polynomial<mp_type> nr, dr;
  214. nr = p_remez->numerator();
  215. dr = p_remez->denominator();
  216. n = nr;
  217. d = dr;
  218. std::vector<mp_type> cn1, cd1;
  219. cn1 = nr.chebyshev();
  220. cd1 = dr.chebyshev();
  221. std::vector<T> cn, cd;
  222. for(unsigned i = 0; i < cn1.size(); ++i)
  223. {
  224. cn.push_back(boost::math::tools::real_cast<T>(cn1[i]));
  225. }
  226. for(unsigned i = 0; i < cd1.size(); ++i)
  227. {
  228. cd.push_back(boost::math::tools::real_cast<T>(cd1[i]));
  229. }
  230. //
  231. // We'll test at the Chebeshev control points which is where
  232. // (in theory) the largest deviation should occur. For good
  233. // measure we'll test at the zeros as well:
  234. //
  235. boost::numeric::ublas::vector<mp_type>
  236. zeros(p_remez->zero_points()),
  237. cheb(p_remez->chebyshev_points());
  238. mp_type max_error(0), cheb_max_error(0);
  239. //
  240. // Do the tests at the zeros:
  241. //
  242. std::cout << "Starting tests at " << name << " precision...\n";
  243. std::cout << "Absissa Error (Poly) Error (Cheb)\n";
  244. for(unsigned i = 0; i < zeros.size(); ++i)
  245. {
  246. mp_type true_result = the_function(zeros[i]);
  247. T absissa = boost::math::tools::real_cast<T>(zeros[i]);
  248. mp_type test_result = convert_to_rr(n.evaluate(absissa) / d.evaluate(absissa));
  249. mp_type cheb_result = convert_to_rr(boost::math::tools::evaluate_chebyshev(cn, absissa) / boost::math::tools::evaluate_chebyshev(cd, absissa));
  250. mp_type err, cheb_err;
  251. if(rel_error)
  252. {
  253. err = boost::math::tools::relative_error(test_result, true_result);
  254. cheb_err = boost::math::tools::relative_error(cheb_result, true_result);
  255. }
  256. else
  257. {
  258. err = fabs(test_result - true_result);
  259. cheb_err = fabs(cheb_result - true_result);
  260. }
  261. if(err > max_error)
  262. max_error = err;
  263. if(cheb_err > cheb_max_error)
  264. cheb_max_error = cheb_err;
  265. std::cout << std::setprecision(6) << std::setw(15) << std::left << absissa
  266. << std::setw(15) << std::left << boost::math::tools::real_cast<T>(err) << boost::math::tools::real_cast<T>(cheb_err) << std::endl;
  267. }
  268. //
  269. // Do the tests at the Chebeshev control points:
  270. //
  271. for(unsigned i = 0; i < cheb.size(); ++i)
  272. {
  273. mp_type true_result = the_function(cheb[i]);
  274. T absissa = boost::math::tools::real_cast<T>(cheb[i]);
  275. mp_type test_result = convert_to_rr(n.evaluate(absissa) / d.evaluate(absissa));
  276. mp_type cheb_result = convert_to_rr(boost::math::tools::evaluate_chebyshev(cn, absissa) / boost::math::tools::evaluate_chebyshev(cd, absissa));
  277. mp_type err, cheb_err;
  278. if(rel_error)
  279. {
  280. err = boost::math::tools::relative_error(test_result, true_result);
  281. cheb_err = boost::math::tools::relative_error(cheb_result, true_result);
  282. }
  283. else
  284. {
  285. err = fabs(test_result - true_result);
  286. cheb_err = fabs(cheb_result - true_result);
  287. }
  288. if(err > max_error)
  289. max_error = err;
  290. std::cout << std::setprecision(6) << std::setw(15) << std::left << absissa
  291. << std::setw(15) << std::left << boost::math::tools::real_cast<T>(err) <<
  292. boost::math::tools::real_cast<T>(cheb_err) << std::endl;
  293. }
  294. std::string msg = "Max Error found at ";
  295. msg += name;
  296. msg += " precision = ";
  297. msg.append(62 - 17 - msg.size(), ' ');
  298. std::cout << msg << std::setprecision(6) << "Poly: " << std::setw(20) << std::left
  299. << boost::math::tools::real_cast<T>(max_error) << "Cheb: " << boost::math::tools::real_cast<T>(cheb_max_error) << std::endl;
  300. }
  301. else
  302. {
  303. std::cout << "Nothing to test: try converging an approximation first!!!" << std::endl;
  304. }
  305. }
  306. void test_float(const char*, const char*)
  307. {
  308. do_test(float(0), "float");
  309. }
  310. void test_double(const char*, const char*)
  311. {
  312. do_test(double(0), "double");
  313. }
  314. void test_long(const char*, const char*)
  315. {
  316. do_test((long double)(0), "long double");
  317. }
  318. void test_float80(const char*, const char*)
  319. {
  320. do_test((boost::multiprecision::cpp_bin_float_double_extended)(0), "float80");
  321. }
  322. void test_float128(const char*, const char*)
  323. {
  324. do_test((boost::multiprecision::cpp_bin_float_quad)(0), "float128");
  325. }
  326. void test_all(const char*, const char*)
  327. {
  328. do_test(float(0), "float");
  329. do_test(double(0), "double");
  330. do_test((long double)(0), "long double");
  331. }
  332. template <class T>
  333. void do_test_n(T, const char* name, unsigned count)
  334. {
  335. set_working_precision(working_precision);
  336. if(started)
  337. {
  338. //
  339. // We want to test the approximation at fixed precision:
  340. // either float, double or long double. Begin by getting the
  341. // polynomials:
  342. //
  343. boost::math::tools::polynomial<T> n, d;
  344. boost::math::tools::polynomial<mp_type> nr, dr;
  345. nr = p_remez->numerator();
  346. dr = p_remez->denominator();
  347. n = nr;
  348. d = dr;
  349. std::vector<mp_type> cn1, cd1;
  350. cn1 = nr.chebyshev();
  351. cd1 = dr.chebyshev();
  352. std::vector<T> cn, cd;
  353. for(unsigned i = 0; i < cn1.size(); ++i)
  354. {
  355. cn.push_back(boost::math::tools::real_cast<T>(cn1[i]));
  356. }
  357. for(unsigned i = 0; i < cd1.size(); ++i)
  358. {
  359. cd.push_back(boost::math::tools::real_cast<T>(cd1[i]));
  360. }
  361. mp_type max_error(0), max_cheb_error(0);
  362. mp_type step = (b - a) / count;
  363. //
  364. // Do the tests at the zeros:
  365. //
  366. std::cout << "Starting tests at " << name << " precision...\n";
  367. std::cout << "Absissa Error (poly) Error (Cheb)\n";
  368. for(mp_type x = a; x <= b; x += step)
  369. {
  370. mp_type true_result = the_function(x);
  371. //std::cout << true_result << std::endl;
  372. T absissa = boost::math::tools::real_cast<T>(x);
  373. mp_type test_result = convert_to_rr(n.evaluate(absissa) / d.evaluate(absissa));
  374. //std::cout << test_result << std::endl;
  375. mp_type cheb_result = convert_to_rr(boost::math::tools::evaluate_chebyshev(cn, absissa) / boost::math::tools::evaluate_chebyshev(cd, absissa));
  376. //std::cout << cheb_result << std::endl;
  377. mp_type err, cheb_err;
  378. if(rel_error)
  379. {
  380. err = boost::math::tools::relative_error(test_result, true_result);
  381. cheb_err = boost::math::tools::relative_error(cheb_result, true_result);
  382. }
  383. else
  384. {
  385. err = fabs(test_result - true_result);
  386. cheb_err = fabs(cheb_result - true_result);
  387. }
  388. if(err > max_error)
  389. max_error = err;
  390. if(cheb_err > max_cheb_error)
  391. max_cheb_error = cheb_err;
  392. std::cout << std::setprecision(6) << std::setw(15) << std::left << boost::math::tools::real_cast<double>(absissa)
  393. << (test_result < true_result ? "-" : "") << std::setw(20) << std::left
  394. << boost::math::tools::real_cast<double>(err)
  395. << boost::math::tools::real_cast<double>(cheb_err) << std::endl;
  396. }
  397. std::string msg = "Max Error found at ";
  398. msg += name;
  399. msg += " precision = ";
  400. //msg.append(62 - 17 - msg.size(), ' ');
  401. std::cout << msg << "Poly: " << std::setprecision(6)
  402. //<< std::setw(15) << std::left
  403. << boost::math::tools::real_cast<T>(max_error)
  404. << " Cheb: " << boost::math::tools::real_cast<T>(max_cheb_error) << std::endl;
  405. }
  406. else
  407. {
  408. std::cout << "Nothing to test: try converging an approximation first!!!" << std::endl;
  409. }
  410. }
  411. void test_n(unsigned n)
  412. {
  413. do_test_n(mp_type(), "mp_type", n);
  414. }
  415. void test_float_n(unsigned n)
  416. {
  417. do_test_n(float(0), "float", n);
  418. }
  419. void test_double_n(unsigned n)
  420. {
  421. do_test_n(double(0), "double", n);
  422. }
  423. void test_long_n(unsigned n)
  424. {
  425. do_test_n((long double)(0), "long double", n);
  426. }
  427. void test_float80_n(unsigned n)
  428. {
  429. do_test_n((boost::multiprecision::cpp_bin_float_double_extended)(0), "float80", n);
  430. }
  431. void test_float128_n(unsigned n)
  432. {
  433. do_test_n((boost::multiprecision::cpp_bin_float_quad)(0), "float128", n);
  434. }
  435. void rotate(const char*, const char*)
  436. {
  437. if(p_remez)
  438. {
  439. p_remez->rotate();
  440. }
  441. else
  442. {
  443. std::cerr << "Nothing to rotate" << std::endl;
  444. }
  445. }
  446. void rescale(const char*, const char*)
  447. {
  448. if(p_remez)
  449. {
  450. p_remez->rescale(a, b);
  451. }
  452. else
  453. {
  454. std::cerr << "Nothing to rescale" << std::endl;
  455. }
  456. }
  457. void graph_poly(const char*, const char*)
  458. {
  459. int i = 50;
  460. set_working_precision(working_precision);
  461. if(started)
  462. {
  463. //
  464. // We want to test the approximation at fixed precision:
  465. // either float, double or long double. Begin by getting the
  466. // polynomials:
  467. //
  468. boost::math::tools::polynomial<mp_type> n, d;
  469. n = p_remez->numerator();
  470. d = p_remez->denominator();
  471. mp_type max_error(0);
  472. mp_type step = (b - a) / i;
  473. std::cout << "Evaluating Numerator...\n";
  474. mp_type val;
  475. for(val = a; val <= b; val += step)
  476. std::cout << n.evaluate(val) << std::endl;
  477. std::cout << "Evaluating Denominator...\n";
  478. for(val = a; val <= b; val += step)
  479. std::cout << d.evaluate(val) << std::endl;
  480. }
  481. else
  482. {
  483. std::cout << "Nothing to test: try converging an approximation first!!!" << std::endl;
  484. }
  485. }
  486. BOOST_AUTO_TEST_CASE( test_main )
  487. {
  488. std::string line;
  489. real_parser<long double/*mp_type*/ > const rr_p;
  490. while(std::getline(std::cin, line))
  491. {
  492. if(parse(line.c_str(), str_p("quit"), space_p).full)
  493. return;
  494. if(false == parse(line.c_str(),
  495. (
  496. str_p("range")[assign_a(started, false)] && real_p[assign_a(a)] && real_p[assign_a(b)]
  497. ||
  498. str_p("relative")[assign_a(started, false)][assign_a(rel_error, true)]
  499. ||
  500. str_p("absolute")[assign_a(started, false)][assign_a(rel_error, false)]
  501. ||
  502. str_p("pin")[assign_a(started, false)] && str_p("true")[assign_a(pin, true)]
  503. ||
  504. str_p("pin")[assign_a(started, false)] && str_p("false")[assign_a(pin, false)]
  505. ||
  506. str_p("pin")[assign_a(started, false)] && str_p("1")[assign_a(pin, true)]
  507. ||
  508. str_p("pin")[assign_a(started, false)] && str_p("0")[assign_a(pin, false)]
  509. ||
  510. str_p("pin")[assign_a(started, false)][assign_a(pin, true)]
  511. ||
  512. str_p("order")[assign_a(started, false)] && uint_p[assign_a(orderN)] && uint_p[assign_a(orderD)]
  513. ||
  514. str_p("order")[assign_a(started, false)] && uint_p[assign_a(orderN)]
  515. ||
  516. str_p("target-precision") && uint_p[assign_a(target_precision)]
  517. ||
  518. str_p("working-precision")[assign_a(started, false)] && uint_p[assign_a(working_precision)]
  519. ||
  520. str_p("variant")[assign_a(started, false)] && int_p[assign_a(variant)]
  521. ||
  522. str_p("skew")[assign_a(started, false)] && int_p[assign_a(skew)]
  523. ||
  524. str_p("brake") && int_p[assign_a(brake)]
  525. ||
  526. str_p("step") && int_p[&step_some]
  527. ||
  528. str_p("step")[&step]
  529. ||
  530. str_p("poly")[&graph_poly]
  531. ||
  532. str_p("info")[&show]
  533. ||
  534. str_p("graph") && uint_p[&do_graph]
  535. ||
  536. str_p("graph")[&graph]
  537. ||
  538. str_p("x-offset") && real_p[assign_a(x_offset)]
  539. ||
  540. str_p("x-scale") && real_p[assign_a(x_scale)]
  541. ||
  542. str_p("y-offset") && str_p("auto")[assign_a(auto_offset_y, true)]
  543. ||
  544. str_p("y-offset") && real_p[assign_a(y_offset)][assign_a(auto_offset_y, false)]
  545. ||
  546. str_p("test") && str_p("float80") && uint_p[&test_float80_n]
  547. ||
  548. str_p("test") && str_p("float80")[&test_float80]
  549. ||
  550. str_p("test") && str_p("float128") && uint_p[&test_float128_n]
  551. ||
  552. str_p("test") && str_p("float128")[&test_float128]
  553. ||
  554. str_p("test") && str_p("float") && uint_p[&test_float_n]
  555. ||
  556. str_p("test") && str_p("float")[&test_float]
  557. ||
  558. str_p("test") && str_p("double") && uint_p[&test_double_n]
  559. ||
  560. str_p("test") && str_p("double")[&test_double]
  561. ||
  562. str_p("test") && str_p("long") && uint_p[&test_long_n]
  563. ||
  564. str_p("test") && str_p("long")[&test_long]
  565. ||
  566. str_p("test") && str_p("all")[&test_all]
  567. ||
  568. str_p("test") && uint_p[&test_n]
  569. ||
  570. str_p("rotate")[&rotate]
  571. ||
  572. str_p("rescale") && real_p[assign_a(a)] && real_p[assign_a(b)] && epsilon_p[&rescale]
  573. ), space_p).full)
  574. {
  575. std::cout << "Unable to parse directive: \"" << line << "\"" << std::endl;
  576. }
  577. else
  578. {
  579. std::cout << "Variant = " << variant << std::endl;
  580. std::cout << "range = [" << a << "," << b << "]" << std::endl;
  581. std::cout << "Relative Error = " << rel_error << std::endl;
  582. std::cout << "Pin to Origin = " << pin << std::endl;
  583. std::cout << "Order (Num/Denom) = " << orderN << "/" << orderD << std::endl;
  584. std::cout << "Target Precision = " << target_precision << std::endl;
  585. std::cout << "Working Precision = " << working_precision << std::endl;
  586. std::cout << "Skew = " << skew << std::endl;
  587. std::cout << "Brake = " << brake << std::endl;
  588. std::cout << "X Offset = " << x_offset << std::endl;
  589. std::cout << "X scale = " << x_scale << std::endl;
  590. std::cout << "Y Offset = ";
  591. if(auto_offset_y)
  592. std::cout << "Auto (";
  593. std::cout << y_offset;
  594. if(auto_offset_y)
  595. std::cout << ")";
  596. std::cout << std::endl;
  597. }
  598. }
  599. }