How to pass an struct (with no atributes, only methods) to a trigonometrical function? - class

my problem is, I have an class that is supposed to be an X for a function, for example
auto f = x * x + 7.0;
and when called with f.e(3) it would return the function value.
It was resolved with operator overload on the * and +, but when i would try to do with trigonometrical functions, it doesnt work.
Here's what i've been trying to do:
auto f = sin(x);
that would later be invoked with an
f.e(5);
But its unable to do that because sin only accepts numbers as arguments, how would i go about doing that?
Here's class X:
class X {
public:
double e( double v ) {
return v;
}
};
The full code required to simply make it work is quite big, so I'm posting it on pastebin:
pastebin.com/SwKUUbyr
It also calculates the 1st derivative of the function.
This is the error:
error: no matching function for call to 'sin(X&)'
I'd love any input you guys can provide.

#include <cmath>
namespace formula {
template<class Lhs, class Rhs>
struct Times;
template<class Lhs, class Rhs>
struct Plus;
template<class D>
struct Formula {
double ex( double in ) { return static_cast<D&>(*this).ex(in); }
double dx( double in ) { return static_cast<D&>(*this).dx(in); }
template<class Rhs>
friend auto operator*( Formula<D>, Formula<Rhs> ) {
return Formula< Times<D, Rhs> >{};
}
template<class Rhs>
friend auto operator+( Formula<D>, Formula<Rhs> ) {
return Formula< Plus<D, Rhs> >{};
}
};
struct X:Formula<X> {
double ex(double in){ return in; }
double dx(double in){ return 1; }
};
X x;
template<class Lhs, class Rhs>
struct Times:Formula<Times<Lhs, Rhs>> {
double ex( double in ) {
return Lhs{}.ex(in) * Rhs{}.ex(in);
}
double dx( double in ) {
return Lhs{}.ex(in) * Rhs{}.dx(in) + Lhs{}.dx(in) * Rhs{}.ex(in);
}
};
template<class Lhs, class Rhs>
struct Plus:Formula<Plus<Lhs, Rhs>> {
double ex( double in ) {
return Lhs{}.ex(in) + Rhs{}.ex(in);
}
double dx( double in ) {
return Lhs{}.dx(in) + Rhs{}.dx(in);
}
};
That is a bit better machinery that replicates what yours does.
Now to extend it:
template<class X>
struct Sin:Formula<Sin<X>> {
double ex( double in ) {
return ::std::sin(X{}.ex(in));
}
double dx( double in ) {
return X{}.dx(in) * ::std::cos(X{}.ex(in));
}
};
template<class X>
auto sin( Formula<X> ) {
return Sin<X>{};
}
}
Test code:
using namespace formula;
auto x_2 = x*x;
auto sin_x_2 = sin(x_2);
std::cout << sin_x_2.ex(0.) << "\n";
std::cout << sin_x_2.dx(0.) << "\n";
std::cout << sin(x).ex(0.) << "\n";
std::cout << sin(x).dx(0.) << "\n";
std::cout << (x*x).ex(1.) << "\n";
std::cout << (x*x).dx(1.) << "\n";
This can be extended with storing copies of the formula you depend upon to allow equations to contain some state.

Related

When calling a member function of a class, I get Error C3867

In my displayData member function of the car class, the error says I should create a pointer to the member, do I have to create pointers to the member? If I do how so? I completely forget pointers. Do i make the object a pointer then point to the displayData member function? I get no red squiggles just an error message saying "use '&' to create a pointer to the member. I tried but had no luck.
#include<iostream>
#include<string>
using namespace std;
class Car
{
private:
int xVal, yVal, zVal;
protected:
public:
Car() { int xVal = 0; int yVal = 0; int zVal = 0; }
Car(int x,int y,int z) { xVal = x; yVal = y; zVal = z; }
~Car() {};
int getX() { return xVal; }
int getY() { return yVal; }
int getZ() { return zVal; }
void changeX(int n) { xVal = n; }
void changeY(int n) { yVal = n; }
void changez(int n) { zVal = n; }
virtual void getData();
void displayData();
};
class Sensor : public Car
{
private:
string sensorType;
protected:
public:
Sensor() { sensorType = "EMPTY"; }
Sensor(int x, int y, int z, string type) :Car(x,y,z) { sensorType = type; }
};
void Car::displayData()
{
cout << "The x values is: " << getX() << endl;
cout << "The y values is: " << getY() << endl;
cout << "The z values is: " << getZ() << endl;
}
int main()
{
Sensor n1;
Sensor n2(20,30,40, "Accelerometer");
n1.displayData;
n2.displayData;
return 0;
}
There is a syntax error in calling the function.
it should be
n1.displayData();
instead of
n1.displayData;

Robust type caster for STL-vector-like classes

I have a class that is quite similar to an STL-vector (the differences are not important for the pybind11 type caster, so I will ignore them here). I have written a type caster for this class. A minimal working example of my code is given below. An example showing the problem is included below the code.
The problem is that my caster is quite limited (because I have used py::array_t). In principle the interface does accept tuples, lists, and numpy-arrays. However, when I overload based on typename, the interface fails for inputted tuples and lists (simply the first overload is selected even though it is the incorrect type).
My question is: How can I make the type caster more robust? Is there an effective way to re-use as much as possible existing type casters for STL-vector-like classes?
C++ code (including pybind11 interface)
#include <iostream>
#include <vector>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
namespace py = pybind11;
// class definition
// ----------------
template<typename T>
class Vector
{
private:
std::vector<T> mData;
public:
Vector(){};
Vector(size_t N) { mData.resize(N); };
auto data () { return mData.data (); };
auto data () const { return mData.data (); };
auto begin() { return mData.begin(); };
auto begin() const { return mData.begin(); };
auto end () { return mData.end (); };
auto end () const { return mData.end (); };
size_t size () const { return mData.size (); };
std::vector<size_t> shape() const { return std::vector<size_t>(1, mData.size()); }
std::vector<size_t> strides() const { return std::vector<size_t>(1, sizeof(T) ); }
template<typename It> static Vector<T> Copy(It first, It last) {
Vector out(last-first);
std::copy(first, last, out.begin());
return out;
}
};
// C++ functions: overload based on type
// -------------------------------------
Vector<int> foo(const Vector<int> &A){ std::cout << "int" << std::endl; return A; }
Vector<double> foo(const Vector<double> &A){ std::cout << "double" << std::endl; return A; }
// pybind11 type caster
// --------------------
namespace pybind11 {
namespace detail {
template<typename T> struct type_caster<Vector<T>>
{
public:
PYBIND11_TYPE_CASTER(Vector<T>, _("Vector<T>"));
bool load(py::handle src, bool convert)
{
if ( !convert && !py::array_t<T>::check_(src) ) return false;
auto buf = py::array_t<T, py::array::c_style | py::array::forcecast>::ensure(src);
if ( !buf ) return false;
auto rank = buf.ndim();
if ( rank != 1 ) return false;
value = Vector<T>::Copy(buf.data(), buf.data()+buf.size());
return true;
}
static py::handle cast(const Vector<T>& src, py::return_value_policy policy, py::handle parent)
{
py::array a(std::move(src.shape()), std::move(src.strides()), src.data());
return a.release();
}
};
}} // namespace pybind11::detail
// Python interface
// ----------------
PYBIND11_MODULE(example,m)
{
m.doc() = "pybind11 example plugin";
m.def("foo", py::overload_cast<const Vector<int > &>(&foo));
m.def("foo", py::overload_cast<const Vector<double> &>(&foo));
}
Example
import numpy as np
import example
print(example.foo((1,2,3)))
print(example.foo((1.5,2.5,3.5)))
print(example.foo(np.array([1,2,3])))
print(example.foo(np.array([1.5,2.5,3.5])))
Output:
int
[1 2 3]
int
[1 2 3]
int
[1 2 3]
double
[1.5 2.5 3.5]
A very easy solution is to specialise pybind11::detail::list_caster. The type caster now becomes as easy as
namespace pybind11 {
namespace detail {
template <typename Type> struct type_caster<Vector<Type>> : list_caster<Vector<Type>, Type> { };
}} // namespace pybind11::detail
Note that this does require Vector to have the methods:
clear()
push_back(const Type &value)
reserve(size_t n) (seems optional in testing)
Complete example
#include <iostream>
#include <vector>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
namespace py = pybind11;
// class definition
// ----------------
template<typename T>
class Vector
{
private:
std::vector<T> mData;
public:
Vector(){};
Vector(size_t N) { mData.resize(N); };
auto data () { return mData.data (); };
auto data () const { return mData.data (); };
auto begin() { return mData.begin(); };
auto begin() const { return mData.begin(); };
auto end () { return mData.end (); };
auto end () const { return mData.end (); };
size_t size () const { return mData.size (); };
void push_back(const T &value) { mData.push_back(value); }
void clear() { mData.clear(); }
void reserve(size_t n) { mData.reserve(n); }
std::vector<size_t> shape() const { return std::vector<size_t>(1, mData.size()); }
std::vector<size_t> strides() const { return std::vector<size_t>(1, sizeof(T) ); }
template<typename It> static Vector<T> Copy(It first, It last) {
printf("Vector<T>::Copy %s\n", __PRETTY_FUNCTION__);
Vector out(last-first);
std::copy(first, last, out.begin());
return out;
}
};
// C++ functions: overload based on type
// -------------------------------------
Vector<int> foo(const Vector<int> &A){ std::cout << "int" << std::endl; return A; }
Vector<double> foo(const Vector<double> &A){ std::cout << "double" << std::endl; return A; }
// pybind11 type caster
// --------------------
namespace pybind11 {
namespace detail {
template <typename Type> struct type_caster<Vector<Type>> : list_caster<Vector<Type>, Type> { };
}} // namespace pybind11::detail
// Python interface
// ----------------
PYBIND11_MODULE(example,m)
{
m.doc() = "pybind11 example plugin";
m.def("foo", py::overload_cast<const Vector<double> &>(&foo));
m.def("foo", py::overload_cast<const Vector<int > &>(&foo));
}

Function template parameters failing to convert type during compilation

While trying to use a function template that calls a class's specialized static function template it is failing to convert its parameter from the template parameter list.
Here is the function that I'm calling in main:
template<class Engine, typename Type, template<typename = Type> class Distribution, class... DistParams>
Type randomGenerator( RE::SeedType seedType, std::size_t seedValue, std::initializer_list<std::size_t> list, DistParams... params ) {
static Type retVal = 0;
static Engine engine = RE::getEngine<Engine>( seedType, seedValue, list );
static Distribution<Type> dist = RD::getDistribution<Type, Distribution>( params... );
retVal = dist( engine );
return retVal;
}
A little bit about the function above:
The Type represents the return value of the distribution such as int, unsigned, char, etc for Integral Types that work with distributions such as uniform_int_distribution<IntType> or Real Types such as float, double for distributions like uniform_real_distribution<RealType>.
The terms RE & RD are typedefs of two classes.
typedef RandomEngine RE;
typedef RandomDistribution RD;
Both classes follow the same pattern as they have delete constructors and all of their methods are declared a static.
The 2nd line in the function is using the template parameter <class Engine> to represent what kind of engine from the <random> header file we want to use from the static methods in class RandomEngine{...}. Each of the engine types has it's own function to create an engine, seed it by the seeding type and seed values and then returns a reference of the engine. All of the functions in the RandomEngine class are non template functions. So I then went ahead and made generalized function template RE::getEngine<Engine>( parameters ); in this RandomEngine class that you can see in this function template randomGenerator(). Then I specialized this function for each engine type. I had no problems with doing that.
This brings me to the next line with the RandomDistribution class I'm trying to follow a similar pattern as I did with the RandomEngine I made a generalized function template RD::getDistribution<Type, Distribution>( params... );
Before I get to the RD::getDistribution<...>(...) function both of the classes above are non templates. The first class RandomEngine has zero function templates for its engines except the generalized getEngine() The difference with this class as opposed to the RandomDistribution is that every function in this class is a function template, because the <random> library's distribution functions require it. So now I have to not only template this generalized function as I did for getEngine() I have to also use a variadic parameter pack as different distributions takes a different amount of arguments.
Here is my declaration of my generalized function in the RandomDistribution class that is found in the header file:
template<typename Type, template<typename = Type> class Distribution, class... DistParams>
static Distribution<Type>& getDistribution( DistParams... params ) {
return getUniformIntDistribution( params... );
}
Then I have this attempt of a specialization for this function in the cpp file for just one of the other distributions:
template<>
static std::uniform_real_distribution<>& RandomDistribution::getDistribution() {
return RandomDistribution::getUniformRealDistribution();
}
I would like to do this for all the other distributions that I'm supporting.
I am using the stand alone function template randomGenerator() in my main function like this:
{
std::initializer_list<std::size_t> list{};
unsigned val = randomGenerator<std::mt19937, unsigned, std::uniform_int_distribution>
( RE::USE_CHRONO_CLOCK, std::size_t( 12 ), list, 1, 100 );
std::cout << val << std::endl;
}
When I compile RandomGenerator.cpp file it compiles without error;
however, when I compile main.cpp I am getting a compiler error stating that it can not convert from std::uniform_int_distribution<int>& to std::uniform_int_distribution<Type>&
and it is pointing to my class's generalized function template that is declared in RandomGenerator.hfile.
For some reason; Type is not being assigned or casted to the type that is passed into randomGenerator's template parameter list.
I'm stuck at this point. I know what the compiler message is saying; I don't what to do to fix. What can be done to resolve this conversion failure?
Okay scrap that whole idea above: I went and entirely rewritten my classes into a single class. The class itself is now a class template. And it looks like this:
#ifndef GENERATOR_H
#define GENERATOR_H
#include <limits>
#include <chrono>
#include <random>
#include <type_traits>
enum SeedType { USE_CHRONO_CLOCK, USE_RANDOM_DEVICE, USE_SEED_VALUE, USE_SEED_SEQ };
template<class Engine, class Type, template<typename> class Distribution>
class Generator {
public:
using Clock = std::conditional_t<std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock,
std::chrono::steady_clock>;
private:
Engine _engine;
Distribution<Type> _distribution;
Type _value;
public:
template<class... Params>
explicit Generator( Engine engine, Params... params ) : _engine( engine ) {
_distribution = Distribution<Type>( params... );
}
void seed( SeedType type = USE_RANDOM_DEVICE, std::size_t seedValue = 0, std::initializer_list<std::size_t> list = {} ) {
switch( type ) {
case USE_CHRONO_CLOCK: { _engine.seed( getTimeNow() ); break; }
case USE_RANDOM_DEVICE: { std::random_device device{};
_engine.seed( device() ); break; }
case USE_SEED_VALUE: { _engine.seed( seedValue ); break; }
case USE_SEED_SEQ: { std::seed_seq seq( list );
_engine.seed( seq ); break; }
}
}
void generate() {
_value = _distribution( _engine );
}
Type getGeneratedValue() const {
return _value;
}
Distribution<Type> getDistribution() const {
return _distribution;
}
std::size_t getTimeNow() {
std::size_t now = static_cast<std::size_t>(Clock::now().time_since_epoch().count());
return now;
}
};
#endif // !GENERATOR_H
And to use it is as simple as:
#include <iostream>
#include <iomanip>
#include <vector>
#include "generator.h"
int main() {
// Engine, Seeding Type, & Distribution Combo 1
std::mt19937 engine1;
Generator<std::mt19937, short, std::uniform_int_distribution> g1( engine1, 1, 100 );
g1.seed( USE_RANDOM_DEVICE );
std::vector<short> vals1;
for( unsigned int i = 0; i < 200; i++ ) {
g1.generate();
auto v = g1.getGeneratedValue();
vals1.push_back( v );
}
int i = 0;
for( auto& v : vals1 ) {
if( (i % 10) != 0 ) {
std::cout << std::setw( 3 ) << v << " ";
} else {
std::cout << '\n' << std::setw( 3 ) << v << " ";
}
i++;
}
std::cout << "\n\n";
// Engine, Seeding Type, & Distribution Combo 2
std::ranlux48 engine2;
std::initializer_list<std::size_t> list2{ 3, 7, 13, 17, 27, 31, 43 };
Generator<std::ranlux48, unsigned, std::binomial_distribution> g2( engine2, 50, 0.75 );
g2.seed( USE_SEED_SEQ, std::size_t(7), list2 );
std::vector<unsigned> vals2;
for( int i = 0; i < 200; i++ ) {
g2.generate();
auto v = g2.getGeneratedValue();
vals2.push_back( v );
}
for( auto& v : vals2 ) {
if( (i % 10) != 0 ) {
std::cout << std::setw( 3 ) << v << " ";
} else {
std::cout << '\n' << std::setw( 3 ) << v << " ";
}
i++;
}
std::cout << "\n\n";
// Engine, Seeding Type, & Distribution Combo 3
std::minstd_rand engine3;
Generator<std::minstd_rand, float, std::gamma_distribution> g3( engine3, 0.22222f, 0.7959753f );
g3.seed( USE_CHRONO_CLOCK );
std::vector<float> vals3;
for( int i = 0; i < 200; i++ ) {
g3.generate();
auto v = g3.getGeneratedValue();
vals3.push_back( v );
}
for( auto& v : vals3 ) {
if( (i % 5 ) != 0 ) {
std::cout << std::setw( 12 ) << v << " ";
} else {
std::cout << '\n' << std::setw( 12 ) << v << " ";
}
i++;
}
std::cout << "\n\n";
std::cout << "\nPress any key and enter to quit.\n";
std::cin.get();
return 0;
}

Point class. distance formula. logic issue when plugging coordinate from the constructor and getting wrong result

#include <iostream>
#include <cmath>
using namespace std;
class point{ // define point class
private:
float x=0;
float y=0;
public:
point();// default constructor
point(float, float);// constructor
void setX(float);
void setY(float);
double getX()const;
double getY()const;
};
//implement all the member function
point::point(){ }
point::point(float i, float k){
x=i;
y=k;
}
void point::setX(float xc){
x=xc;
}
void point::setY(float yc){
y=yc;
}
double point::getY()const{
return y;
}
double point::getX()const{
return x;
}
double operator + (const point&lhs, const point &rhs) // free function.
{
double dx=lhs.getX()-rhs.getX();
double dy=lhs.getX()-rhs.getY();
return sqrt(dx*dx+dy*dy);
}
int main(){
point p1(2, -1);
point p2(1, 5);
int dist=0;
dist = p1 + p2;
cout << "The distance between p1 " << "and p2" << " is " << dist << endl;
return 0;
}
This should be 5 but I got 3. I do not understand why?
replace
double dy=lhs.getX()-rhs.getY();
by
double dy=lhs.getY()-rhs.getY()

How to call functions in the main function by use class?

#include <iostream>
using namespace std;
class Money
{
public:
Money();
Money(int, int);
void setDollars(int d);
void setCents(int c);
int getDollars() const;
int getCents() const;
double getAmount(int, int);
private:
int dollars;
int cents;
};
Money::Money()
{
dollars = 0;
cents = 0;
}
Money::Money(int d, int c)
{
dollars = d;
cents = c;
}
void Money::setDollars(int d)
{
dollars = d;
}
void Money::setCents(int c)
{
if (c > 100)
{
c = c % 100;
dollars = dollars + (c / 100);
}
//update the dollars member if the cents input argument is 100 or larger.
cents = c;
}
int Money::getDollars() const
{
return dollars;
}
int Money::getCents() const
{
return cents;
}
double Money::getAmount(int d, int c)
{
return dollars + (cents / 100);
}
int main()
{
int dlr;
int cts;
//double amt;
cout << "Please input amount of dollars: ";
cin >> dlr;
cout << "Please input amount of cents: ";
cin >> cts;
Money money0(dlr, cts);
cout << "The money object1 has amount: " << money0.getDollars() << "." << money0.getCents() << endl;
cout << "The money object2 has amount: " << money0.getAmount() << endl;
//I try to call the functions to tell user how much is it
//use both ways to tell user how much is it(1.getDollars+getCents, 2. getAmount)
return 0;
system("pause");
}
When I try to call the get functions in the main, the errors show up. How to call those functions correctly?
Here is my assignment:
Define a class named Money that stores a monetary amount. The class should have two private integer variables, one to store the number of dollars and another to store the number of cents. Include a default constructor that initializes the amount to $0.00 and an overloaded parameterized constructor to initialize any non-zero amount(as demonstrated in the example program below).