@@ -498,6 +498,64 @@ bool plot(const VectorY &y,
498498 return plot (x, y, " " , keywords);
499499}
500500
501+ template <typename VectorX, typename VectorY>
502+ bool loglog (const VectorX &x, const VectorY &y, const std::string &s = " " ,
503+ const std::map<std::string, std::string> &keywords = {}) {
504+ detail::_interpreter::get ();
505+
506+ // argument for xscale/yscale is only the string "log"
507+ PyObject *log_arg = PyTuple_New (1 );
508+ PyObject *pystring = PyString_FromString (" log" );
509+ PyTuple_SetItem (log_arg, 0 , pystring);
510+
511+ // call xscale("log") and yscale("log"), no kwargs needed hence pass NULL,
512+ // as explained in https://docs.python.org/3/c-api/object.html
513+ PyObject *res_x = PyObject_Call (
514+ detail::_interpreter::get ().s_python_function_xscale , log_arg, NULL );
515+ PyObject *res_y = PyObject_Call (
516+ detail::_interpreter::get ().s_python_function_yscale , log_arg, NULL );
517+
518+ // clean up
519+ Py_DECREF (log_arg);
520+
521+ if (!res_x)
522+ throw std::runtime_error (" Call to xscale() failed" );
523+ Py_DECREF (res_x);
524+
525+ if (!res_y)
526+ throw std::runtime_error (" Call to yscale() failed" );
527+ Py_DECREF (res_y);
528+
529+ // call plot, which gets now plotted in doubly logarithmic scale
530+ return plot (x, y, s, keywords);
531+ }
532+
533+ template <typename VectorX, typename VectorY>
534+ bool loglog (const VectorX &x, const VectorY &y,
535+ const std::map<std::string, std::string> &keywords) {
536+ return loglog (x, y, " " , keywords);
537+ }
538+
539+ template <typename VectorY>
540+ bool loglog (const VectorY &y, const std::string &s = " " ,
541+ const std::map<std::string, std::string> &keywords = {}) {
542+ std::vector<std::size_t > x (y.size ());
543+ for (std::size_t i = 0 ; i < x.size (); ++i)
544+ x.at (i) = i + 1 ; // in loglog scale the values shouldn't be zero
545+
546+ return loglog (x, y, s, keywords);
547+ }
548+
549+ template <typename VectorY>
550+ bool loglog (const VectorY &y,
551+ const std::map<std::string, std::string> &keywords) {
552+ std::vector<std::size_t > x (y.size ());
553+ for (std::size_t i = 0 ; i < x.size (); ++i)
554+ x.at (i) = i + 1 ; // in loglog scale the values shouldn't be zero
555+
556+ return loglog (x, y, " " , keywords);
557+ }
558+
501559template <typename Numeric>
502560void plot_surface (const std::vector<::std::vector<Numeric>> &x,
503561 const std::vector<::std::vector<Numeric>> &y,
@@ -952,56 +1010,6 @@ bool semilogy(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
9521010 return res;
9531011}
9541012
955- template <typename ... Args> bool loglog_call (Args... args) {
956- // argument for xscale/yscale is only the string "log"
957- PyObject *log_arg = PyTuple_New (1 );
958- PyObject *pystring = PyString_FromString (" log" );
959- PyTuple_SetItem (log_arg, 0 , pystring);
960-
961- // call xscale("log") and yscale("log"), no kwargs needed hence pass NULL,
962- // as explained in https://docs.python.org/3/c-api/object.html
963- PyObject *res_x = PyObject_Call (
964- detail::_interpreter::get ().s_python_function_xscale , log_arg, NULL );
965- PyObject *res_y = PyObject_Call (
966- detail::_interpreter::get ().s_python_function_yscale , log_arg, NULL );
967-
968- // clean up
969- Py_DECREF (log_arg);
970-
971- if (!res_x)
972- throw std::runtime_error (" Call to xscale() failed" );
973- Py_DECREF (res_x);
974-
975- if (!res_y)
976- throw std::runtime_error (" Call to yscale() failed" );
977- Py_DECREF (res_y);
978-
979- // call plot, which gets now plotted in doubly logarithmic scale
980- return plot (args...);
981- }
982-
983- template <typename VectorY>
984- bool loglog (const VectorY &y, const std::string &s = " " ) {
985- return loglog_call (y, s);
986- }
987-
988- template <typename VectorX, typename VectorY>
989- bool loglog (const VectorX &x, const VectorY &y, const std::string &s = " " ) {
990- return loglog_call (x, y, s);
991- }
992-
993- template <typename VectorY>
994- bool loglog (const VectorY &y,
995- const std::map<std::string, std::string> &kwargs) {
996- return loglog_call (y, kwargs);
997- }
998-
999- template <typename VectorX, typename VectorY>
1000- bool loglog (const VectorX &x, const VectorY &y,
1001- const std::map<std::string, std::string> &kwargs) {
1002- return loglog_call (x, y, kwargs);
1003- }
1004-
10051013template <typename NumericX, typename NumericY>
10061014bool errorbar (const std::vector<NumericX> &x, const std::vector<NumericY> &y,
10071015 const std::vector<NumericX> &yerr,
0 commit comments