可以将算术表达式作为参数传递给函数来描述其中的逻辑吗?
Can an arithmetic expression be passed as argument to a function to describe the logic therein?
我正在研究 Mandelbrot 集以及其他一些分形的可视化,其中有很多重复代码,但没有代码重用。
我正在使用的功能之一如下:
/**
* determines whether a pixel lies in the set
* @params x, y - x and y coordinates on R/I axes
* @param c - a complex number
*/
void calculateSet(int x, int y, Complex c) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = z^2 + c;
}
// some code using n to color the set
}
这遵循 Mandelbrot 集:
z_(n+1) = z_n^2 + c
但是看看燃烧之船套装的相关代码:
void calculateSet(int x, int y, Complex c) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = abs(z)^2 + c; // ***
}
// follows z_(n+1) = abs(z_1)^2 + c
}
除加星标行外的所有代码都是相同的。现在我有单独的 classes 用于 Mandelbrot
、BurningShip
和其他一些,唯一的区别是那一行。
有没有办法定义这个表达式并传递给通用的 Set
class?
一些伪代码:
class Set {
// ...
Set(Type expression) {
// ...
// x, y, c initialized
// ...
calculateSet(x, y, c, expression);
}
void calculateSet(int x, int y, Complex c, Type e) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = e;
}
}
};
我可以用 Set
来描述我想要的任何类型的集合吗?
Set mandelbrot = Set(Type("z^2 + c"));
Set burningship = Set(Type("abs(z)^2 + c"));
// etc
我可以使用 if/else
语句来得到一个 class,但它不是通用的。
我想这就是 lambda 的用途。
template<typename Lam>
class Set
{
private:
Lam lam;
public:
Set (Lam&& lam) : lam(lam) {}
void calculateSet(int x, int y, Complex c)
{
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = lam(z, c);
}
}
};
您可以这样使用 class:
auto mandelbrot = Set([](Complex z, Complex c) -> Complex {
return (z*z) + c;
});
auto burningShip = Set([](Complex z, Complex c) -> Complex {
return abs((z*z)) + c;
});
mandelbrot.calculateSet(...);
burningShip .calculateSet(...);
由于您仅限于 C++03,因此您可以相对轻松地使用函数指针。
Complex mandlebrotCompute(Complex z, Complex c) {
return z*z + c;
}
void calculateSet(int x, int y, Complex c, Complex (*func)(Complex, Complex)) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = func(z, c);
}
}
用法如下:
Complex foo;
calculateSet(1, 2, foo, mandlebrotCompute);
它可能有助于使代码更清晰 use a typedef for the function pointer。
你可以制作一个模板,将函数作为模板参数。
我相信这是提供最多内联机会的方法。
typedef Complex (*Function)(const Complex&, const Complex&);
template<Function fn>
class Set
{
// ...
void calculateSet(int x, int y, Complex c) {
Complex z = c;
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = fn(z, c)
}
// some code...
}
}
Complex mandelbrot_fn(const Complex& z, const Complex& c)
{
return z^2 + c;
}
Complex burning_fn(const Complex& z, const Complex& c)
{
return abs(z)^2 + c;
}
Set<mandelbrot_fn> mandelbrot;
Set<burning_fn> burning_ship;
我正在研究 Mandelbrot 集以及其他一些分形的可视化,其中有很多重复代码,但没有代码重用。
我正在使用的功能之一如下:
/**
* determines whether a pixel lies in the set
* @params x, y - x and y coordinates on R/I axes
* @param c - a complex number
*/
void calculateSet(int x, int y, Complex c) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = z^2 + c;
}
// some code using n to color the set
}
这遵循 Mandelbrot 集:
z_(n+1) = z_n^2 + c
但是看看燃烧之船套装的相关代码:
void calculateSet(int x, int y, Complex c) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = abs(z)^2 + c; // ***
}
// follows z_(n+1) = abs(z_1)^2 + c
}
除加星标行外的所有代码都是相同的。现在我有单独的 classes 用于 Mandelbrot
、BurningShip
和其他一些,唯一的区别是那一行。
有没有办法定义这个表达式并传递给通用的 Set
class?
一些伪代码:
class Set {
// ...
Set(Type expression) {
// ...
// x, y, c initialized
// ...
calculateSet(x, y, c, expression);
}
void calculateSet(int x, int y, Complex c, Type e) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = e;
}
}
};
我可以用 Set
来描述我想要的任何类型的集合吗?
Set mandelbrot = Set(Type("z^2 + c"));
Set burningship = Set(Type("abs(z)^2 + c"));
// etc
我可以使用 if/else
语句来得到一个 class,但它不是通用的。
我想这就是 lambda 的用途。
template<typename Lam>
class Set
{
private:
Lam lam;
public:
Set (Lam&& lam) : lam(lam) {}
void calculateSet(int x, int y, Complex c)
{
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = lam(z, c);
}
}
};
您可以这样使用 class:
auto mandelbrot = Set([](Complex z, Complex c) -> Complex {
return (z*z) + c;
});
auto burningShip = Set([](Complex z, Complex c) -> Complex {
return abs((z*z)) + c;
});
mandelbrot.calculateSet(...);
burningShip .calculateSet(...);
由于您仅限于 C++03,因此您可以相对轻松地使用函数指针。
Complex mandlebrotCompute(Complex z, Complex c) {
return z*z + c;
}
void calculateSet(int x, int y, Complex c, Complex (*func)(Complex, Complex)) {
Complex z = c.clone();
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = func(z, c);
}
}
用法如下:
Complex foo;
calculateSet(1, 2, foo, mandlebrotCompute);
它可能有助于使代码更清晰 use a typedef for the function pointer。
你可以制作一个模板,将函数作为模板参数。
我相信这是提供最多内联机会的方法。
typedef Complex (*Function)(const Complex&, const Complex&);
template<Function fn>
class Set
{
// ...
void calculateSet(int x, int y, Complex c) {
Complex z = c;
int n = 0;
for (; n < maxDepth; n++) {
if (z.dis() > 4) { break; }
z = fn(z, c)
}
// some code...
}
}
Complex mandelbrot_fn(const Complex& z, const Complex& c)
{
return z^2 + c;
}
Complex burning_fn(const Complex& z, const Complex& c)
{
return abs(z)^2 + c;
}
Set<mandelbrot_fn> mandelbrot;
Set<burning_fn> burning_ship;