- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
现在我正在尝试教授 g++ 编译器线性代数,以便 g++ 可以重写像 (matrix * vector)(index)
这样的表达式作为计算表达式的循环。基本上这就是我对 the last article 的下一篇文章的期望在“Expressive C++”系列中。最后一篇文章解释了如何制作用于添加 vector 的 EDSL,因此我编写了另一个 EDSL 用于将矩阵乘以 vector 。
但是当我自己的矩阵和 vector 类的 Proto 域的名称作为第一个宏参数传递时,BOOST_PROTO_DEFINE_OPERATORS 宏无法编译。
所以我想知道 Proto 转换是否有可能评估矩阵和 vector 对象的混合表达式。好像没有这样的示例代码可以编译,示例代码在"Adapting Existing Types to Proto"在 Proto 用户指南 1.57.0 中是不完整的,尽管它是关于如何使现有的矩阵和 vector 类型适应 Proto。
我不知所措..你能给我一些建议或提示吗?
这是我的源代码。如果您能就如何修复它向我提供建议,我将不胜感激:
#include <iostream>
#include <boost/proto/proto.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;
namespace LinAlg {
class Vector;
class Matrix;
// Functor for lazy evaluation
struct ElmOfMatVecMult;
// The grammar for an expression like ( matrix * vector )(index)
struct MatVecMultElmGrammar : proto::or_<
proto::when< proto::multiplies< Matrix, Vector>,
proto::_make_function( ElmOfMatVecMult,
proto::_left, proto::_right,
proto::_state) >
> {};
// The grammar for a vector expression
// ( Now I consider just one form : matrix * vector . )
struct VecExprGrammar : proto::or_<
proto::when< proto::function< MatVecMultElmGrammar, proto::_>,
MatVecMultElmGrammar( proto::_left, proto::_right) >,
proto::multiplies< Matrix, Vector>
> {};
template<typename E> struct Expr;
// The above grammar is associated with this domain.
struct Domain
: proto::domain<proto::generator<Expr>, VecExprGrammar>
{};
// A wrapper template for linear algebraic expressions
// including matrices and vectors
template<typename ExprType>
struct Expr
: proto::extends<ExprType, Expr<ExprType>, Domain>
{
explicit Expr(const ExprType& e)
: proto::extends<ExprType, Expr<ExprType>, Domain>(e)
{}
};
// Testing if data in an heap array can be a vector object
class Vector {
private:
int sz;
double* data;
public:
template <typename Sig> struct result;
template <typename This, typename T>
struct result< This(T) > { typedef double type; };
typedef double result_type;
explicit Vector(int sz_ = 1, double iniVal = 0.0) :
sz( sz_), data( new double[sz] ) {
for (int i = 0; i < sz; i++) data[i] = iniVal;
std::cout << "Created" << std::endl;
}
Vector(const Vector& vec) :
sz( vec.sz), data( new double[sz] ) {
for (int i = 0; i < sz; i++) data[i] = vec.data[i];
std::cout << "Copied! " << std::endl;
}
~Vector() {
delete [] data;
std::cout << "Deleted" << std::endl;
}
// accessing to an element of this vector
double& operator()(int i) { return data[i]; }
const double& operator()(int i) const { return data[i]; }
};
// Testing if data in an heap array can be a matrix object
class Matrix
{
private:
int rowSz, colSz;
double* data;
double** m;
public:
template <typename Signature> struct result;
template <typename This, typename T>
struct result< This(T,T) > { typedef double type; };
explicit Matrix(int rowSize = 1, int columnSize =1,
double iniVal = 0.0) :
rowSz( rowSize), colSz(columnSize),
data( new double[rowSz*colSz] ), m( new double*[rowSz])
{
for (int i = 0; i < rowSz; i++) m[i] = data + i*colSz;
for (int ri = 0; ri < rowSz; ri++)
for (int ci = 0; ci < colSz; ci++) m[ri][ci] = iniVal;
std::cout << "Created" << std::endl;
}
Matrix(const Matrix& mat) :
rowSz( mat.rowSz), colSz( mat.colSz),
data( new double[rowSz*colSz] ), m( new double*[rowSz])
{
for (int i = 0; i < rowSz; i++) m[i] = data + i*colSz;
for (int ri = 0; ri < rowSz; ri++)
for (int ci = 0; ci < colSz; ci++)
m[ri][ci] = mat.m[ri][ci];
std::cout << "Copied! " << std::endl;
}
~Matrix()
{
delete [] m;
delete [] data;
std::cout << "Deleted" << std::endl;
}
int rowSize() const { return rowSz; }
int columnSize() const { return colSz; }
// accesing to a vector element
double& operator()(int ri, int ci) { return m[ri][ci]; }
const double& operator()(int ri, int ci) const { return m[ri][ci]; }
};
// An expression like ( matrix * vector )(index) is transformed
// into the loop for calculating the dot product between
// the vector and matrix.
struct ElmOfMatVecMult
{
double operator()( Matrix const& mat, Vector const& vec,
int index) const
{
double elm = 0.0;
for (int ci =0; ci < mat.columnSize(); ci++)
elm += mat(index, ci) * vec(ci);
return elm;
}
};
// Define a trait for detecting linear algebraic terminals, to be used
// by the BOOST_PROTO_DEFINE_OPERATORS macro below.
template<typename> struct IsExpr : mpl::false_ {};
template<> struct IsExpr< Vector> : mpl::true_ {};
template<> struct IsExpr< Matrix> : mpl::true_ {};
// This defines all the overloads to make expressions involving
// Vector and Matrix objects to build Proto's expression templates.
BOOST_PROTO_DEFINE_OPERATORS(IsExpr, Domain)
}
int main()
{
using namespace LinAlg;
proto::_default<> trans;
Matrix mat( 3, 3);
Vector vec1(3);
mat(0,0) = 1.00; mat(0,1) = 1.01; mat(0,2) = 1.02;
mat(1,0) = 1.10; mat(1,1) = 1.11; mat(1,2) = 1.12;
mat(2,0) = 1.20; mat(2,1) = 1.21; mat(2,2) = 1.22;
vec1(0) = 1.0;
vec1(1) = 2.0;
vec1(2) = 3.0;
proto::display_expr( ( mat * vec1)(2) );
proto::display_expr( VecExprGrammar()( ( mat * vec1)(2) );
double vecElm = trans( VecExprGrammar()( ( mat * vec1)(2) );
return 0;
}
最佳答案
我以某种方式确认我的问题的答案是"is"。让我的源代码工作的技巧是定义一个事件语法,用 MatVecMult
对象替换 matrix * vector 并将 MatVecMult
定义为 proto::callable
对象,用于制作惰性求值仿函数 LazyMatVecMult
。当使用 operator()(int index)
调用此 LazyMatVecMult
实例时,它会计算矩阵的第 index 行与 vector 的点积。
(很抱歉自己回答我的问题。但我认为,关于如何为 vector 和矩阵表达式制作基于 Proto 的 EDSL,我并不是唯一一个偶然发现这 block 石头的人。)
此源代码已确认可与 g++ 4.8.4 一起使用:
#include <iostream>
#include <boost/proto/proto.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;
namespace LinAlg {
class Vector;
class Matrix;
// Callable transform object to make a proto exression
// for lazily evaluationg a. multiplication
struct MatVecMult;
// The grammar for the multiplication of a matrix and a vector
struct MatVecMultGrammar : proto::or_<
proto::when<
proto::multiplies< proto::terminal< Matrix> ,
proto::terminal< Vector> >,
MatVecMult( proto::_value( proto::_left),
proto::_value( proto::_right) )
>
> {};
// The grammar for a vector expression
// ( Now I consider just one form : matrix * vector . )
struct VecExprGrammar : proto::or_<
proto::function< MatVecMultGrammar, proto::_>,
MatVecMultGrammar
> {};
// A wrapper for a linear algebraic expression
template<typename E> struct Expr;
// The above grammar is associated with this domain.
struct Domain
: proto::domain<proto::generator<Expr>, VecExprGrammar>
{};
// A wrapper template for linear algebraic expressions
// including matrices and vectors
template<typename ExprType>
struct Expr
: proto::extends<ExprType, Expr<ExprType>, Domain>
{
/* typedef double result_type; */
explicit Expr(const ExprType& e)
: proto::extends<ExprType, Expr<ExprType>, Domain>(e)
{}
};
// Testing if data in an heap array can be a vector object
class Vector {
private:
int sz;
double* data;
public:
explicit Vector(int sz_ = 1, double iniVal = 0.0) :
sz( sz_), data( new double[sz] ) {
for (int i = 0; i < sz; i++) data[i] = iniVal;
std::cout << "Created" << std::endl;
}
Vector(const Vector& vec) :
sz( vec.sz), data( new double[sz] ) {
for (int i = 0; i < sz; i++) data[i] = vec.data[i];
std::cout << "Copied! " << std::endl;
}
~Vector() {
delete [] data;
std::cout << "Deleted" << std::endl;
}
// accessing to an element of this vector
double& operator()(int i) { return data[i]; }
const double& operator()(int i) const { return data[i]; }
};
// Testing if data in an heap array can be a matrix object
class Matrix
{
private:
int rowSz, colSz;
double* data;
double** m;
public:
explicit Matrix(int rowSize = 1, int columnSize =1,
double iniVal = 0.0) :
rowSz( rowSize), colSz(columnSize),
data( new double[rowSz*colSz] ), m( new double*[rowSz])
{
for (int i = 0; i < rowSz; i++) m[i] = data + i*colSz;
for (int ri = 0; ri < rowSz; ri++)
for (int ci = 0; ci < colSz; ci++) m[ri][ci] = iniVal;
std::cout << "Created" << std::endl;
}
Matrix(const Matrix& mat) :
rowSz( mat.rowSz), colSz( mat.colSz),
data( new double[rowSz*colSz] ), m( new double*[rowSz])
{
for (int i = 0; i < rowSz; i++) m[i] = data + i*colSz;
for (int ri = 0; ri < rowSz; ri++)
for (int ci = 0; ci < colSz; ci++)
m[ri][ci] = mat.m[ri][ci];
std::cout << "Copied! " << std::endl;
}
~Matrix()
{
delete [] m;
delete [] data;
std::cout << "Deleted" << std::endl;
}
int rowSize() const { return rowSz; }
int columnSize() const { return colSz; }
// accesing to a vector element
double& operator()(int ri, int ci) { return m[ri][ci]; }
const double& operator()(int ri, int ci) const { return m[ri][ci]; }
};
// Lazy function object for evaluating an element of
// the resultant vector from the multiplication of
// a matrix and vector objects.
//
// An expression like ( matrix * vector )(index) is transformed
// into the loop for calculating the dot product between
// the index'th row of the matrix and the vector.
struct LazyMatVecMult
{
Matrix const& m;
Vector const& v;
int mColSz;
typedef double result_type;
// typedef mpl::int_<1> proto_arity;
explicit LazyMatVecMult(Matrix const& mat, Vector const& vec) :
m( mat), v( vec), mColSz(mat.rowSize()) {}
LazyMatVecMult(LazyMatVecMult const& lazy) :
m(lazy.m), v(lazy.v), mColSz(lazy.mColSz) {}
result_type operator()(int index) const
{
result_type elm = 0.0;
for (int ci =0; ci < mColSz; ci++)
elm += m(index, ci) * v(ci);
return elm;
}
};
// Callable transform object to make the lazy functor
// a proto exression for lazily evaluationg the multiplication
// of a matrix and a vector .
struct MatVecMult : proto::callable
{
typedef proto::terminal< LazyMatVecMult >::type result_type;
result_type
operator()( Matrix const& mat, Vector const& vec) const
{
return proto::as_expr( LazyMatVecMult(mat, vec) );
}
};
// Define a trait for detecting linear algebraic terminals, to be used
// by the BOOST_PROTO_DEFINE_OPERATORS macro below.
template<typename> struct IsExpr : mpl::false_ {};
template<> struct IsExpr< Vector> : mpl::true_ {};
template<> struct IsExpr< Matrix> : mpl::true_ {};
// template<> struct IsExpr< MatVecMult> : mpl::true_ {};
template<> struct IsExpr< LazyMatVecMult> : mpl::true_ {};
// This defines all the overloads to make expressions involving
// Vector and Matrix objects to build Proto's expression templates.
BOOST_PROTO_DEFINE_OPERATORS(IsExpr, Domain)
// BOOST_PROTO_DEFINE_OPERATORS(IsExpr, proto::default_domain)
}
int main()
{
using namespace LinAlg;
proto::_default<> trans;
Matrix mat( 3, 3);
Vector vec1(3), vec2(3);
mat(0,0) = 1.00; mat(0,1) = 1.01; mat(0,2) = 1.02;
mat(1,0) = 1.10; mat(1,1) = 1.11; mat(1,2) = 1.12;
mat(2,0) = 1.20; mat(2,1) = 1.21; mat(2,2) = 1.22;
vec1(0) = 1.0;
vec1(1) = 2.0;
vec1(2) = 3.0;
std::cout << " mat * vec1" << std::endl;
proto::display_expr( mat * vec1 );
std::cout << " MatVecMultGrammar()( mat * vec1) " << std::endl;
proto::display_expr( MatVecMultGrammar()( mat * vec1) );
std::cout << "( mat * vec1)(2)" << std::endl;
proto::display_expr( ( mat * vec1)(2) );
std::cout << "VecExprGrammar()( ( mat * vec1)(2) )" << std::endl;
proto::display_expr( VecExprGrammar()( ( mat * vec1)(2) ) );
double elm2 = trans( VecExprGrammar()( ( mat * vec1)(2) ) );
std::cout << "( mat * vec1)(2) = " << elm2 << std::endl;
return 0;
}
关于c++ - Boost.原型(prototype) : Is it possible for Proto transforms to evaluate a mixture expression of matrix & vector?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32901317/
我有一个包含需要排序的不同项目的列表。但还有一个额外的问题:某些元素只允许出现在列表中的特定位置。 示例(请查看 http://jsfiddle.net/pYL32/2/ ):有一个包含元素 foo、
关于https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained据解释,guava(以及后来的 java 8
我有一个名为 say CalculationOutcome 的类(class)和 FileHashOutcome .他们的构造函数有 (ActualResult, Throwable)参数,并在 Co
我正在使用pycharm,我的代码在分屏上。当我运行调试时,会弹出调试/运行窗口,它非常分散注意力并且限制了我在调试时可以查看的代码量......但我想保持它,因为我来回走动;另外,我想要调试变量的完
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: javascript object, access variable property name? 我确信这是可以完
if (typeof Object.create !== 'function') { Object.create = function (o) { function F() {
在将实体存储在 redis 中作为序列化二进制 blob 的应用程序中工作。我有多个客户端处理同一个数据集,我希望使用乐观并发。 我的要求是: 在一次往返中读取特定键的序列化实体 将修改后的实体写回r
这个问题是指 C/x86 上使用的 IEEE 标准浮点数。 是否可以将任何数字(即不包括 NaN 之类的特殊值)浮点数或 double 数表示为十进制字符串,以便将该字符串转换回浮点数/ double
我的团队目前正在与 Lua 合作,创建一个 android 游戏。我们遇到的一件事是表面上无法创建重载构造函数。 我习惯于使用默认值设置一个对象,然后在需要时使其过载。 前任: apples() {
如何在 Scene Kit 中使用 SCNCamera 获得像鱼眼镜头那样的失真? 类似于这种图像的“鞠躬”: //正如 Rickster 指出的那样,这种失真被称为“桶形失真”。 从文档中,这是让我
我想问是否有一种方法可以多次评估 javascript 术语,而不需要一遍又一遍地解析一个术语。 说,您想要评估 var1/var2+Math.sqrt(var3) 每秒 20 次。 使用时这可能会出
我想知道在技术上是否可以在 java applet 中创建代理。 那么是否可以通过这个 java applet 代理路由所有进一步的浏览器请求? 例如,如果用户要浏览 google.com,默认行为是
我有以下代码,我想返回一个 bool 值或一个元组。 (函数 isvariable 和 dont_care 都返回 bool 值,仅供引用) let match_element (a, b) = if
这个问题困扰我很久了。我想要一个二叉树(或类似的嵌套结构)上的迭代器,它高效、简单且Pythonic。例如,对于这样的用法: for value in values(root): do_som
目前我有以下 MySQL 查询: SELECT COUNT(*) AS `count`, `v`.`value` FROM `client_entity_int` AS `v` INN
我正在使用 Angular 开发应用程序,客户端是 100% JS。我即将替换使用 ExtJS 制作的旧应用程序,但我不会更改服务器端。只有客户端从头开始重新编码。 我想在任何地方和任何机器上处理这个
有没有办法在运行时检索实例的声明类?例如: public class Caller { private JFrame frame = new JFrame("Test"); priva
我目前正在请求 MySQL 数据库使用 PDO 计算一些计数和总和。这个过程可能需要一段时间,如果用户突然想浏览另一个页面,他可能会停留在浏览器前面。 我试图弄清楚是否可以使用 PDO 启动 MySQ
想知道它是不是这样工作的: $result .= mysqli_query($query1); $result .= mysqli_query($query2); $result 会是查询 1 和 2
所以我有这样的挑战: body 背景上的图像,背景大小,覆盖以适合整个屏幕。在背景图像上是一些元素(建筑物)。所以我想将鼠标悬停在建筑物上,他们会更改颜色或添加阴影等。问题在于屏幕调整大小,当我调整屏
我是一名优秀的程序员,十分优秀!