Object-oriented API for equations - c++

Let's take the Quadratic equation as an example:
a x^2 + b x + c = 0
This equation can be viewed as describing a relation between the values a, b, c, and x. Given three of those, you can calculate the fourth. The four possibilities are:
a = - (b x + c) / x^2
b = - (a x^2 + c) / x
c = - x (a x + b)
x = [-b +- sqrt(b^2 - 4 a c)] / (2 a)
Here's one approach to representing this equation. Given the following class:
class Quadratic
{
public:
double a; bool HasA = false; void A(double a_) { a = a_; HasA = true; }
double b; bool HasB = false; void B(double b_) { b = b_; HasB = true; }
double c; bool HasC = false; void C(double c_) { c = c_; HasC = true; }
double x; bool HasX = false; void X(double x_) { x = x_; HasX = true; }
// a = - (b x + c) / x^2
double A()
{
if (HasB == false) throw domain_error("B not set");
if (HasC == false) throw domain_error("C not set");
if (HasX == false) throw domain_error("X not set");
if (x == 0.0) throw domain_error("X cannot be 0.0");
return - (b*x + c) / (x*x);
}
// x = [-b +- sqrt(b^2 - 4 a c)] / (2 a)
vector<double> X()
{
if (HasA == false) throw domain_error("A not set");
if (HasB == false) throw domain_error("B not set");
if (HasC == false) throw domain_error("C not set");
if (a == 0.0) throw domain_error("A cannot be 0.0");
return
{
(-b + sqrt(b*b - 4 * a*c)) / (2 * a),
(-b - sqrt(b*b - 4 * a*c)) / (2 * a)
};
}
// b = - (a x^2 + c) / x
// ...
// c = - x (a x + b)
// ...
};
We can find x as follows. Set A, B, and C:
obj.A(2.3);
obj.B(3.4);
obj.C(1.2);
There might be two values for X so iterate through the result:
for each (auto elt in obj.X()) cout << elt << endl;
If any of the dependent values are not set, a domain_error exception is thrown.
Similarly, to find A, we set B, C, and X:
obj.B(1.2);
obj.C(2.3);
obj.X(3.4);
and display the result:
cout << obj.A() << endl;
My question is, are there other approaches to representing and working with equations in an object-oriented language? Is there a more idiomatic approach than the above?

The title of your question says:
Object-oriented API for equations
However, there is nothing object-oriented about your code example, at least not with the established definitions of "object-oriented programming" I know. You have no virtual functions, so it's not object-oriented.
Bjarne Stroustrup's FAQ "What is "OOP" and what's so great about it?" says (emphasis added by me):
In the context of C++ [...] it means programming using class hierarchies and virtual
functions to allow manipulation of objects of a variety of types
through well-defined interfaces and to allow a program to be extended
incrementally through derivation.
The Standard C++ FAQ (which also quotes from the first source), answers "Are virtual functions (dynamic binding) central to OO/C++?" like this:
Without virtual functions, C++ wouldn’t be object-oriented.
Therefore,
My question is, are there other approaches to representing and working
with equations in an object-oriented language?
The answer to that should be that mathematical computations and object-orientation programming usually do not mix well. Object orientation is all about choosing the concrete implementation of an abstract operation at run-time. You may, for example, choose a different algorithm with the same input and output based on the user's choice at run-time. This could be done with virtual functions. Still, the object-orientation would happen at a higher level of your application, and the computation itself would not be object-oriented.
Is there a more idiomatic approach than the above?
Yes, generic programming, i.e. templates.
All the code you presented works with double values. What if I want to use it with float, std::complex<double> or a even a custom BigNumber class?
With templates, you can write generic code with concrete implementations chosen at compile-time.
First of all, let's make your original code compilable:
#include <vector>
#include <stdexcept>
#include <math.h>
class Equation
{
public:
bool HasA;
bool HasB;
bool HasC;
bool HasX;
double a;
double b;
double c;
double x;
double A()
{
if (!HasB) throw std::domain_error("B not set");
if (!HasC) throw std::domain_error("C not set");
if (!HasX) throw std::domain_error("X not set");
if (x == 0.0) throw std::domain_error("X cannot be 0.0");
return - (b*x + c) / (x*x);
}
// x = [-b +- sqrt(b^2 - 4 a c)] / (2 a)
std::vector<double> X()
{
if (!HasA) throw std::domain_error("A not set");
if (!HasB) throw std::domain_error("B not set");
if (!HasC) throw std::domain_error("C not set");
if (a == 0.0) throw std::domain_error("A cannot be 0.0");
return
{
(-b + sqrt(b*b - 4 * a*c)) / (2 * a),
(-b - sqrt(b*b - 4 * a*c)) / (2 * a)
};
}
// b = - (a x^2 + c) / x
// ...
// c = - x (a x + b)
// ...
};
int main()
{
Equation e;
std::vector<double> v = e.X();
}
(I've fixed the == false comparisons, which are almost always bad style, but there is more work to do from a C++ coding quality POV, e.g. making the member variables private.)
The problem is that this whole thing only works for doubles. If you try to use it with ints, here's what happens:
int main()
{
Equation e;
std::vector<int> v = e.X();
}
Result:
error C2440: 'initializing' : cannot convert from
'std::vector<double,std::allocator<_Ty>>' to 'std::vector<int,std::allocator<_Ty>>'
Here's how you can turn your class into a template: add template <class T> on top and replace every double with T (and add two static_casts to tell the compiler that you agree with a narrowing conversion which may happen due to sqrt's return type):
#include <vector>
#include <stdexcept>
#include <math.h>
template <class T>
class Equation
{
public:
bool HasA;
bool HasB;
bool HasC;
bool HasX;
T a;
T b;
T c;
T x;
T A()
{
if (!HasB) throw std::domain_error("B not set");
if (!HasC) throw std::domain_error("C not set");
if (!HasX) throw std::domain_error("X not set");
if (x == 0.0) throw std::domain_error("X cannot be 0.0");
return - (b*x + c) / (x*x);
}
// x = [-b +- sqrt(b^2 - 4 a c)] / (2 a)
std::vector<T> X()
{
if (!HasA) throw std::domain_error("A not set");
if (!HasB) throw std::domain_error("B not set");
if (!HasC) throw std::domain_error("C not set");
if (a == 0.0) throw std::domain_error("A cannot be 0.0");
return
{
static_cast<T>((-b + sqrt(b*b - 4 * a*c)) / (2 * a)),
static_cast<T>((-b - sqrt(b*b - 4 * a*c)) / (2 * a))
};
}
// b = - (a x^2 + c) / x
// ...
// c = - x (a x + b)
// ...
};
int main()
{
Equation<int> e;
std::vector<int> v = e.X();
}
Of course, this is only half of the story, because chances are very high that you do not want to allow integral types anyway, only floating-point types like double or float (or custom floating-point types). The result of sqrt(2) truncated to 1 is rarely desirable.
To keep your code generic but prevent such problems, read up on static assertions for compile-time checks, restricting your template to particular types. std::is_floating_point may be useful, too. See also the following recent question on SO:
Getting std::complex<double> to pass std::is_floating_point test
And remember, nothing of this has anything to do with object-oriented programming.

Related

Efficiently preventing duplicate accesses

I have a statement computing a multiply-accumulate operation that looks something like this:
return A->set(A->get() + B->get() * C->get());
Now, A, B, and C may not be unique, and I want to minimize redundant get()s. The only way I can think of optimizing this is with
if (A == B && B == C) {
double a = A->get();
return A->set(a + a * a);
} else if (A == B) {
double a = A->get();
return A->set(a + a * C->get());
} else if (A == C) {
double a = A->get();
return A->set(a + B->get() * a);
} else if (B == C) {
double b = B->get();
return A->set(A->get() + b * b);
} else {
return A->set(A->get() + B->get() * C->get());
}
Is there a more efficient way? What about generalizing this to more than three arguments??
You can store them in a map. The solution can be extended easily to arbitrarily many pointers, but I've used three here for concreteness.
std::unordered_map<MyType *, double> computed_values;
for (MyType *p: {A, B, C}) {
if (computed_values.find(p) == computed_values.end()) {
computed_values[p] = p->get();
}
}
double result = computed_values[A] + computed_values[B] * computed_values[C];
A->set(result);
As others have pointed out, make sure you profile to make sure this is actually worth the overhead of std::unordered_map lookups.
Assuming get() methods are really costly to the extent of producing measurable performance difference,
double a,b,c;
a = A->get();
b = (B==A?a:B->get());
c = (C==B?b:(C==A?a:c->get()));
return A->set(a+b*c);
Assuming the get() methods are reasonably cheap, you'd be better off just doing:
return A->set(A->get() + B->get() * C->get());
The other approach simply inserts a bunch of conditional jumps into your code, which could easily end up being more expensive than the original code.

use typedef for more type safe in c++

I would like to revisit the post. Currently, I am trying to avoid bug created by mixing Rad and Degree types for angles in my program.
For example:
typedef float Degree;
typedef float Radian;
Degree a = 15.;
Radian b = 3.14/4.;
float c = a + b; // no compile error
is there new update solution for this?
EDIT 01:
I resort to write my own class with hope for its small size and no dependency. Here's the working code
#include <stdio.h>
#include <iostream>
template<typename numT>
class RadAngle {
public:
RadAngle() {
AngVal = 0.0;
}
RadAngle(const numT& angV) {
AngVal = angV;
}
void operator = (const RadAngle<numT>& ang1) {
AngVal = ang1.getVal();
}
RadAngle operator+(const RadAngle<numT>& ang1) const { return RadAngle<numT>(AngVal+ang1.getVal()); }
RadAngle operator-(const RadAngle<numT>& ang1) const { return RadAngle<numT>(AngVal-ang1.getVal()); }
RadAngle operator*(const RadAngle<numT>& ang1) const { return RadAngle<numT>(AngVal*ang1.getVal()); }
RadAngle operator/(const RadAngle<numT>& ang1) const { return RadAngle<numT>(AngVal/ang1.getVal()); }
numT getVal() const { return AngVal;};
private:
numT AngVal;
};
int main() {
RadAngle<float> a(1.5);
RadAngle<float> b(3.14);
RadAngle<float> c = a+b;
//std::cout << c << std::endl;
// printf("%.2f",c.getVal());
return 0;
}
What you have doesn't help type safety at all, except perhaps as weak documentation. As far as the compiler is concerned, float, Degree, and Radian are complete synonyms; this is called a weak type alias. Strong type aliases are not a part of C++, but you can work around that. Two good articles on that are here and here. The basic idea is to create a generic class template for a strong typedef, and use that to create each individual alias.
If you don't want to write all the boilerplate yourself even once, I recommend using a third-party library to handle this. Both the authors of the posts I linked above wrote libraries for it, NamedType and type_safe. If you need something heavier-duty, you should check out Boost.Units. Note that I haven't used any of these myself; they're just where I'd check if I needed those features.
You didn't ask about this, but none of this should have any runtime performance costs over just using float everywhere and keeping track of units manually, but might make compilation slower.
Your best bet is to create a class for each kind of measurement and implement ways to convert one to another. The classes could/should have a common superclass.
I would pick one as internal representation (e.g. Radian) and write other as wrapper classes
typedef double Radian;
class Degree {
public:
Degree() {
m_radian = 0.0;
}
Degree(double degree) {
m_radian = degree / 180.0 * 3.1415926;
}
void operator = (double degree) {
m_radian = degree / 180.0 * 3.1415926;
}
operator Radian() const { return m_radian; }
private:
Radian m_radian;
};
void print_rad(Radian rad) {
printf("rad: %lf\n", rad);
}
int main() {
Radian rad = 123.0;
Degree degree = 456.0;
print_rad(rad);
print_rad(degree);
print_rad(rad + degree);
return 0;
}
Output:
rad: 123.000000
rad: 7.958701
rad: 130.958701
Well, you probably want to go the whole way with calculating with units.
Do something like this, with all relevant (SI?) base-units:
template <class T, int meter, int second, int pow_10, int pow_deginrad>
class unit {
T num = 0;
};
// add convenience typedefs. Also look into `operator ""` for denoting literals.
Now you only have to define arithmetic between the types and magnitudes in one place.
Happy coding.
Your approach is a bit flawed, I think.
What you trying to model are physical quantities - types that have a value and a unit.
There is no quantity called a radian. There is a quantity called angle whose units may be radians or degrees.
What you need to is a bit of infrastructure to deal with converting units of quantities and performing operations on units as well as the values.
For example,
L1 = 10 "m" (length)
L2 = 20 "m" (length)
L1 * L2 = 200 "m^2" (area)
F1 = 10 "N" (force)
A1 = 2 "m^2" (area)
F1/A1 = 5 "Pa" (pressure)
A2 = 10 "deg"
convert(A2, "rad") = 0.174533 "rad"
If you are able to add the code for dealing with units, rest of the functionality will be easy.
We have had to do that at my work and the amount of code is non-trivial. It does not make sense for me delver further into that subject here.
Potential C++ code:
struct Quantity
{
double value;
std::string unit;
};
// Defines operations on Quantity.
Quantity operator+(Quantity const& q1, Quantity const& q2) { ... }
Quantity operator-(Quantity const& q1, Quantity const& q2) { ... }
Quantity operator*(Quantity const& q1, Quantity const& q2) { ... }
Quantity operator*(Quantity const& q1, double f) { ... }
Quantity operator/(Quantity const& q1, Quantity const& q2) { ... }
Quantity operator/(Quantity const& q1, double f) { ... }
Quantity convert(Quantity const& q, std::string const& unit) { ... }
auto L1 = Quantity(10, "m");
auto L2 = Quantity(10, "m");
auto a = L1*L2; // Resulting in Quantity(100, "m^2")
auto F1 = Quantity(10, "N");
auto A1 = Quantity(2, "m^2");
auto p = F1/A1; // Resulting in Quantity(5, "Pa")
auto A2 = Quantity(10, "deg");
auto A3 = Convert(A2, "rad"); // Resulting in Quantity(0.174533, "rad")

Generating public key from private key issues

I am using the BigIntegerLibrary and this is applying secp256k1.
Here is my function to generate the public key.
std::string genPublicKey(BigInteger privateKey){
std::vector<bool> sequence = reducePointOps(privateKey);
BigInteger s;
BigInteger x3 = basePoint_X;
BigInteger y3 = basePoint_Y;
BigInteger rx, ry;
BigInteger three(3);
BigInteger two(2);
for(std::vector<bool>::reverse_iterator it = sequence.rbegin(); it != sequence.rend(); ++it){
//meaning point doubling
if(*it == true){
s = (((three * ((x3 * x3)%primeModulo))+a) * inverse(two*y3)) % primeModule;
rx = (((s*s)%primeModulo)-(two * x3))% primeModulo;
ry = (s * (x3 - rx) - y3)%primeModulo;
//cout<<"Doubling: s="<<s<<", x="<<rx<<", y="<<ry<<endl;
}
//meaning point addition
else{
//(x2,y2) -> base point (x1,y1)->(x3, y3) aka previously calculated point
s = ((basePoint_Y - y3) * inverse(basePoint_X - x3))%primeModulo;
rx = (((s*s) % primeModulo) - x3 - basePoint_X) % primeModulo;
ry = ((s * (x3 - rx)) - y3)%primeModulo;
//cout<<"Addition: s="<<s<<", x="<<rx<<", y="<<ry<<endl;
}
//cout<<endl;
x3=rx;
y3=ry;
}
std::string x3_str = bigIntegerToString(x3);
std::string y3_str = bigIntegerToString(y3);
return (x3_str + y3_str);
}
Here is my inverse function but I took this from somewhere so I am almost positive it is correct. Plus I have tested it and is working.
BigInteger inverse(BigInteger a){
BigInteger s;
BigInteger t;
eea(primeModulo, a, &s, &t);
if(t<0)
return (t%primeModulo);
else
return t;
}
BigInteger eea(BigInteger a, BigInteger b, BigInteger *s, BigInteger *t){
if(a==0){
*s=0;
*t=1;
return b;
}
BigInteger s1;
BigInteger t1;
BigInteger gcd = eea(b%a, a, &s1, &t1);
*s = t1 - (b/a) * s1;
*t = s1;
return gcd;
}
Other than that there is only my function to reduce the amount of operations to point doublings and additions. I have worked out many examples by hand so I know the data coming out of this function is correct.
The weird thing is that I have tried this on an example in my cryptography class with values m=17 x=5 y=1 a=2 and I am getting all the values I should be getting. I didn't code a way for the values to 'wrap around' once the inverse of the base point is reached but since with bitcoin the private key space is much much smaller than the modulo value so we shouldn't even reach that point when values start repeating themselves. I am about to cry with how frustrating this is so any help would be wonderful.
Oh also there is one other weird thing. Here is an example when I run it.
Private Key:
18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
My Public Key:
458ACBDD5DE95281B9ACAB95D0F8DAC011C895EBE95E567BE9E308C12936CCAE3B81CE567B126A604A938D29ED15B5A96779AF27B5DC9ED6F2EE187E9C582BA6
Correct Public Key:
50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B23522CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6
It's not obvious but the last 19 hex digits are the same but the rest is different? They are the same length by the way. Could this be something wrong with the BigInteger Library? This was a way that seemed simple to me but would you recommend I did it a different way?

Are enums the canonical way to implement bit flags?

Currently I'm using enums to represent a state in a little game experiment. I declare them like so:
namespace State {
enum Value {
MoveUp = 1 << 0, // 00001 == 1
MoveDown = 1 << 1, // 00010 == 2
MoveLeft = 1 << 2, // 00100 == 4
MoveRight = 1 << 3, // 01000 == 8
Still = 1 << 4, // 10000 == 16
Jump = 1 << 5
};
}
So that I can use them this way:
State::Value state = State::Value(0);
state = State::Value(state | State::MoveUp);
if (mState & State::MoveUp)
movement.y -= mPlayerSpeed;
But I'm wondering if this is the right way to implement bit flags. Isn't there a special container for bit flags? I heard about std::bitset, is it what I should use? Do you know something more efficient?
Am I doing it right?
I forgot to point out I was overloading the basic operators of my enum:
inline State::Value operator|(State::Value a, State::Value b)
{ return static_cast<State::Value>(static_cast<int>(a) | static_cast<int>(b)); }
inline State::Value operator&(State::Value a, State::Value b)
{ return static_cast<State::Value>(static_cast<int>(a) & static_cast<int>(b)); }
inline State::Value& operator|=(State::Value& a, State::Value b)
{ return (State::Value&)((int&)a |= (int)b); }
I had to use a C-style cast for the |=, it didn't work with a static_cast - any idea why?
The STL contains std::bitset, which you can use for precisely such a case.
Here is just enough code to illustrate the concept:
#include <iostream>
#include <bitset>
class State{
public:
//Observer
std::string ToString() const { return state_.to_string();};
//Getters
bool MoveUp() const{ return state_[0];};
bool MoveDown() const{ return state_[1];};
bool MoveLeft() const{ return state_[2];};
bool MoveRight() const{ return state_[3];};
bool Still() const{ return state_[4];};
bool Jump() const{ return state_[5];};
//Setters
void MoveUp(bool on) {state_[0] = on;}
void MoveDown(bool on) {state_[1] = on;}
void MoveLeft(bool on) {state_[2] = on;}
void MoveRight(bool on) {state_[3] = on;}
void Still(bool on) {state_[4] = on;}
void Jump(bool on) {state_[5] = on;}
private:
std::bitset<6> state_;
};
int main() {
State s;
auto report = [&s](std::string const& msg){
std::cout<<msg<<" "<<s.ToString()<<std::endl;
};
report("initial value");
s.MoveUp(true);
report("move up set");
s.MoveDown(true);
report("move down set");
s.MoveLeft(true);
report("move left set");
s.MoveRight(true);
report("move right set");
s.Still(true);
report("still set");
s.Jump(true);
report("jump set");
return 0;
}
Here's it working: http://ideone.com/XLsj4f
The interesting thing about this is that you get std::hash support for free, which is typically one of the things you would need when using state inside various data structures.
EDIT:
There is one limitation to std::bitset and that is the fact that you need to know the maximum number of bits in your bitset at compile time. However, that is the same case with enums anyway.
However, if you don't know the size of your bitset at compile time, you can use boost::dynamic_bitset, which according to this paper (see page 5) is actually really fast. Finally, according to Herb Sutter, std::bitset was designed to be used in cases you would normally want to use std::vector.
That said, there really is no substitute for real world tests. So if you really want to know, profile. That will give you performance numbers for a context that you care about.
I should also mention that std::bitset has an advantage that enum does not - there is no upper limit on the number of bits you can use. So std::bitset<1000> is perfectly valid.
I believe that your approach is right (except several things):
1. You can explicitly specify underlying type to save memory;
2. You can not use unspecified enum values.
namespace State {
enum Value : char {
None = 0,
MoveUp = 1 << 0, // 00001 == 1
MoveDown = 1 << 1, // 00010 == 2
MoveLeft = 1 << 2, // 00100 == 4
MoveRight = 1 << 3, // 01000 == 8
Still = 1 << 4, // 10000 == 16
Jump = 1 << 5
};
}
and:
State::Value state = State::Value::None;
state = State::Value(state | State::MoveUp);
if (mState & State::MoveUp) {
movement.y -= mPlayerSpeed;
}
about overloading:
inline State::Value& operator|=(State::Value& a, State::Value b) {
return a = static_cast<State::Value> (a | b);
}
and since you use C++11, you should use constexpr every were is possible:
inline constexpr State::Value operator|(State::Value a, State::Value b) {
return a = static_cast<State::Value> (a | b);
}
inline constexpr State::Value operator&(State::Value a, State::Value b) {
return a = static_cast<State::Value> (a & b);
}
To be honest I don't think there is a consistent pattern for them.
Just look at std::ios_base::openmode and std::regex_constants::syntax_option_type as two completely different ways of structuring it in the standard library -- one using a struct, the other using an entire namespace. Both are enums all right, but structured differently.
Check your standard library implementation to see the details of how the above two are implemented.

How to pass an expression as an argument/parameter?

Say I have a polynomial function f(x), and I want to use this expression into either the expression g(x) or h(x), depending on which the user chooses. Is this possible?
for example
int main() {
float fexpression = /* polynomial function f(x) here */;
/* some code where user picks g(x) or h(x) */
if (/* gexpression == true */)
cout << gfunction(fexpression);
else /* h expression == true */
cout << hfunction(fexpression);
return 0;
}
float gfunction(float j){
float var = /* some function representing g(f(x)) == g(j) */;
return var;
}
float hfunction(float j){
float var = /* some function representing h(f(x)) == h(j) */;
return var;
}
it just doesnt seem right to me that I can pass a variable that is an expression, such as
float fexpression = ....
You want a function pointer.
Make the expression a function.
float fexpression( float x )
{
return (5*(pow(x,4))) + (3*(pow(x, 3))) + (10 * x) - 5
}
This code, as you wrote it, will then pass the functionality itself.
if (/* gexpression == true */)
cout << gfunction(fexpression);
else /* h expression == true */
cout << hfunction(fexpression);
I tried to explain details of this in the comment section of Drew's answer, but it got lost in the formatting... so had to start another answer.
#DrewDorman's is right in saying you need to just define your expression as a function:
float fexpression( float x )
{
return (5*(pow(x,4))) + (3*(pow(x, 3))) + (10 * x) - 5
}
What is missing (for you) is the following (which you would get from reading Drew's link...):
define your gfunction as follows (for instance)
float gfunction(float (*funcp)(float)) {
// lots of stuff to determine the value of x
return (*funcp)(x);
}
This is how gfunction can evaluate your polynomial. Do something similar for hfunction
When you call gfunction, you have to reference fexpression as follows:
cout << gfunction(&fexpression);
the & matters... it was also missing from Drew's answer.