本文整理汇总了C++中SpProxy::end方法的典型用法代码示例。如果您正苦于以下问题:C++ SpProxy::end方法的具体用法?C++ SpProxy::end怎么用?C++ SpProxy::end使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SpProxy
的用法示例。
在下文中一共展示了SpProxy::end方法的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: while
arma_hot
inline
uword
n_unique
(
const SpProxy<T1>& pa,
const SpProxy<T2>& pb,
const op_n_unique_type junk
)
{
arma_extra_debug_sigprint();
arma_ignore(junk);
typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
typename SpProxy<T1>::const_iterator_type x_it_end = pa.end();
typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
typename SpProxy<T2>::const_iterator_type y_it_end = pb.end();
uword total_n_nonzero = 0;
while( (x_it != x_it_end) || (y_it != y_it_end) )
{
if(x_it == y_it)
{
if(op_n_unique_type::eval((*x_it), (*y_it)) != typename T1::elem_type(0))
{
++total_n_nonzero;
}
++x_it;
++y_it;
}
else
{
if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_it.row() < y_it.row()))) // if y is closer to the end
{
if(op_n_unique_type::eval((*x_it), typename T1::elem_type(0)) != typename T1::elem_type(0))
{
++total_n_nonzero;
}
++x_it;
}
else // x is closer to the end
{
if(op_n_unique_type::eval(typename T1::elem_type(0), (*y_it)) != typename T1::elem_type(0))
{
++total_n_nonzero;
}
++y_it;
}
}
}
return total_n_nonzero;
}
示例2: result
inline
typename
enable_if2
<
(is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
Mat<typename T1::elem_type>
>::result
operator-
(
const T1& x,
const T2& y
)
{
arma_extra_debug_sigprint();
Mat<typename T1::elem_type> result(x);
const SpProxy<T2> pb(y.get_ref());
arma_debug_assert_same_size( result.n_rows, result.n_cols, pb.get_n_rows(), pb.get_n_cols(), "subtraction" );
typename SpProxy<T2>::const_iterator_type it = pb.begin();
typename SpProxy<T2>::const_iterator_type it_end = pb.end();
while(it != it_end)
{
result.at(it.row(), it.col()) -= (*it);
++it;
}
return result;
}
示例3: P
inline
arma_warn_unused
bool
is_finite(const SpBase<typename T1::elem_type,T1>& X)
{
arma_extra_debug_sigprint();
const SpProxy<T1> P(X.get_ref());
if(is_SpMat<typename SpProxy<T1>::stored_type>::value)
{
const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q);
return tmp.M.is_finite();
}
else
{
typename SpProxy<T1>::const_iterator_type it = P.begin();
typename SpProxy<T1>::const_iterator_type it_end = P.end();
while(it != it_end)
{
if(arma_isfinite(*it) == false) { return false; }
++it;
}
}
return true;
}
示例4: if
arma_hot
inline
typename T1::elem_type
dot_helper(const SpProxy<T1>& pa, const SpProxy<T2>& pb)
{
typedef typename T1::elem_type eT;
// Iterate over both objects and see when they are the same
eT result = eT(0);
typename SpProxy<T1>::const_iterator_type a_it = pa.begin();
typename SpProxy<T1>::const_iterator_type a_end = pa.end();
typename SpProxy<T2>::const_iterator_type b_it = pb.begin();
typename SpProxy<T2>::const_iterator_type b_end = pb.end();
while((a_it != a_end) && (b_it != b_end))
{
if(a_it == b_it)
{
result += (*a_it) * (*b_it);
++a_it;
++b_it;
}
else if((a_it.col() < b_it.col()) || ((a_it.col() == b_it.col()) && (a_it.row() < b_it.row())))
{
// a_it is "behind"
++a_it;
}
else
{
// b_it is "behind"
++b_it;
}
}
return result;
}
示例5: proxy
inline
void
op_sp_plus::apply(Mat<typename T1::elem_type>& out, const SpToDOp<T1,op_sp_plus>& in)
{
arma_extra_debug_sigprint();
// Note that T1 will be a sparse type, so we use SpProxy.
const SpProxy<T1> proxy(in.m);
out.set_size(proxy.get_n_rows(), proxy.get_n_cols());
out.fill(in.aux);
typename SpProxy<T1>::const_iterator_type it = proxy.begin();
typename SpProxy<T1>::const_iterator_type it_end = proxy.end();
for(; it != it_end; ++it)
{
out.at(it.row(), it.col()) += (*it);
}
}
示例6: while
arma_hot
inline
void
spglue_plus::apply_noalias(SpMat<eT>& out, const SpProxy<T1>& pa, const SpProxy<T2>& pb)
{
arma_extra_debug_sigprint();
arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "addition");
if( (pa.get_n_nonzero() != 0) && (pb.get_n_nonzero() != 0) )
{
out.set_size(pa.get_n_rows(), pa.get_n_cols());
// Resize memory to correct size.
out.mem_resize(n_unique(pa, pb, op_n_unique_add()));
// Now iterate across both matrices.
typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
typename SpProxy<T1>::const_iterator_type x_end = pa.end();
typename SpProxy<T2>::const_iterator_type y_end = pb.end();
uword cur_val = 0;
while( (x_it != x_end) || (y_it != y_end) )
{
if(x_it == y_it)
{
const eT val = (*x_it) + (*y_it);
if (val != eT(0))
{
access::rw(out.values[cur_val]) = val;
access::rw(out.row_indices[cur_val]) = x_it.row();
++access::rw(out.col_ptrs[x_it.col() + 1]);
++cur_val;
}
++x_it;
++y_it;
}
else
{
const uword x_it_row = x_it.row();
const uword x_it_col = x_it.col();
const uword y_it_row = y_it.row();
const uword y_it_col = y_it.col();
if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end
{
access::rw(out.values[cur_val]) = (*x_it);
access::rw(out.row_indices[cur_val]) = x_it_row;
++access::rw(out.col_ptrs[x_it_col + 1]);
++cur_val;
++x_it;
}
else
{
access::rw(out.values[cur_val]) = (*y_it);
access::rw(out.row_indices[cur_val]) = y_it_row;
++access::rw(out.col_ptrs[y_it_col + 1]);
++cur_val;
++y_it;
}
}
}
const uword out_n_cols = out.n_cols;
uword* col_ptrs = access::rwp(out.col_ptrs);
// Fix column pointers to be cumulative.
for(uword c = 1; c <= out_n_cols; ++c)
{
col_ptrs[c] += col_ptrs[c - 1];
}
}
else
{
if(pa.get_n_nonzero() == 0)
{
out = pb.Q;
return;
}
if(pb.get_n_nonzero() == 0)
{
out = pa.Q;
return;
}
}
}
示例7: p
arma_hot
inline
void
spop_sum::apply(SpMat<typename T1::elem_type>& out, const SpOp<T1,spop_sum>& in)
{
arma_extra_debug_sigprint();
typedef typename T1::elem_type eT;
const uword dim = in.aux_uword_a;
arma_debug_check( (dim > 1), "sum(): parameter 'dim' must be 0 or 1" );
const SpProxy<T1> p(in.m);
const uword p_n_rows = p.get_n_rows();
const uword p_n_cols = p.get_n_cols();
if(p.get_n_nonzero() == 0)
{
if(dim == 0) { out.zeros(1,p_n_cols); }
if(dim == 1) { out.zeros(p_n_rows,1); }
return;
}
if(dim == 0) // find the sum in each column
{
Row<eT> acc(p_n_cols, fill::zeros);
if(SpProxy<T1>::must_use_iterator)
{
typename SpProxy<T1>::const_iterator_type it = p.begin();
typename SpProxy<T1>::const_iterator_type it_end = p.end();
while(it != it_end) { acc[it.col()] += (*it); ++it; }
}
else
{
for(uword col = 0; col < p_n_cols; ++col)
{
acc[col] = arrayops::accumulate
(
&p.get_values()[p.get_col_ptrs()[col]],
p.get_col_ptrs()[col + 1] - p.get_col_ptrs()[col]
);
}
}
out = acc;
}
else
if(dim == 1) // find the sum in each row
{
Col<eT> acc(p_n_rows, fill::zeros);
typename SpProxy<T1>::const_iterator_type it = p.begin();
typename SpProxy<T1>::const_iterator_type it_end = p.end();
while(it != it_end) { acc[it.row()] += (*it); ++it; }
out = acc;
}
}
示例8: acc
inline
void
spop_mean::apply_noalias_fast
(
SpMat<typename T1::elem_type>& out,
const SpProxy<T1>& p,
const uword dim
)
{
arma_extra_debug_sigprint();
typedef typename T1::elem_type eT;
typedef typename T1::pod_type T;
const uword p_n_rows = p.get_n_rows();
const uword p_n_cols = p.get_n_cols();
if( (p_n_rows == 0) || (p_n_cols == 0) || (p.get_n_nonzero() == 0) )
{
if(dim == 0) { out.zeros((p_n_rows > 0) ? 1 : 0, p_n_cols); }
if(dim == 1) { out.zeros(p_n_rows, (p_n_cols > 0) ? 1 : 0); }
return;
}
if(dim == 0) // find the mean in each column
{
Row<eT> acc(p_n_cols, fill::zeros);
if(SpProxy<T1>::must_use_iterator)
{
typename SpProxy<T1>::const_iterator_type it = p.begin();
typename SpProxy<T1>::const_iterator_type it_end = p.end();
while(it != it_end) { acc[it.col()] += (*it); ++it; }
acc /= T(p_n_rows);
}
else
{
for(uword col = 0; col < p_n_cols; ++col)
{
acc[col] = arrayops::accumulate
(
&p.get_values()[p.get_col_ptrs()[col]],
p.get_col_ptrs()[col + 1] - p.get_col_ptrs()[col]
) / T(p_n_rows);
}
}
out = acc;
}
else
if(dim == 1) // find the mean in each row
{
Col<eT> acc(p_n_rows, fill::zeros);
typename SpProxy<T1>::const_iterator_type it = p.begin();
typename SpProxy<T1>::const_iterator_type it_end = p.end();
while(it != it_end) { acc[it.row()] += (*it); ++it; }
acc /= T(p_n_cols);
out = acc;
}
if(out.is_finite() == false)
{
spop_mean::apply_noalias_slow(out, p, dim);
}
}
示例9: pa
inline
typename
enable_if2
<
(is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_type<typename T1::elem_type, typename T2::elem_type>::value),
SpMat<typename T1::elem_type>
>::result
operator%
(
const SpBase<typename T1::elem_type, T1>& x,
const SpBase<typename T2::elem_type, T2>& y
)
{
arma_extra_debug_sigprint();
typedef typename T1::elem_type eT;
const SpProxy<T1> pa(x.get_ref());
const SpProxy<T2> pb(y.get_ref());
arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "element-wise multiplication");
SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols());
if( (pa.get_n_nonzero() != 0) && (pb.get_n_nonzero() != 0) )
{
// Resize memory to correct size.
result.mem_resize(n_unique(x, y, op_n_unique_mul()));
// Now iterate across both matrices.
typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
typename SpProxy<T1>::const_iterator_type x_end = pa.end();
typename SpProxy<T2>::const_iterator_type y_end = pb.end();
uword cur_val = 0;
while((x_it != x_end) || (y_it != y_end))
{
if(x_it == y_it)
{
const eT val = (*x_it) * (*y_it);
if (val != eT(0))
{
access::rw(result.values[cur_val]) = val;
access::rw(result.row_indices[cur_val]) = x_it.row();
++access::rw(result.col_ptrs[x_it.col() + 1]);
++cur_val;
}
++x_it;
++y_it;
}
else
{
const uword x_it_row = x_it.row();
const uword x_it_col = x_it.col();
const uword y_it_row = y_it.row();
const uword y_it_col = y_it.col();
if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end
{
++x_it;
}
else
{
++y_it;
}
}
}
// Fix column pointers to be cumulative.
for(uword c = 1; c <= result.n_cols; ++c)
{
access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1];
}
}
return result;
}
示例10: while
inline
void
spop_diagmat::apply_noalias(SpMat<typename T1::elem_type>& out, const SpProxy<T1>& p)
{
arma_extra_debug_sigprint();
const uword n_rows = p.get_n_rows();
const uword n_cols = p.get_n_cols();
const bool p_is_vec = (n_rows == 1) || (n_cols == 1);
if(p_is_vec) // generate a diagonal matrix out of a vector
{
const uword N = (n_rows == 1) ? n_cols : n_rows;
out.zeros(N, N);
if(p.get_n_nonzero() == 0) { return; }
typename SpProxy<T1>::const_iterator_type it = p.begin();
typename SpProxy<T1>::const_iterator_type it_end = p.end();
if(n_cols == 1)
{
while(it != it_end)
{
const uword row = it.row();
out.at(row,row) = (*it);
++it;
}
}
else
if(n_rows == 1)
{
while(it != it_end)
{
const uword col = it.col();
out.at(col,col) = (*it);
++it;
}
}
}
else // generate a diagonal matrix out of a matrix
{
arma_debug_check( (n_rows != n_cols), "diagmat(): given matrix is not square" );
out.zeros(n_rows, n_rows);
if(p.get_n_nonzero() == 0) { return; }
typename SpProxy<T1>::const_iterator_type it = p.begin();
typename SpProxy<T1>::const_iterator_type it_end = p.end();
while(it != it_end)
{
const uword row = it.row();
const uword col = it.col();
if(row == col)
{
out.at(row,row) = (*it);
}
++it;
}
}
}
示例11: pa
inline
const SpSubview<eT>&
SpSubview<eT>::operator_equ_common(const SpBase<eT, T1>& in)
{
arma_extra_debug_sigprint();
// algorithm:
// instead of directly inserting values into the matrix underlying the subview,
// create a new matrix by merging the underlying matrix with the input object,
// and then replacing the underlying matrix with the created matrix.
//
// the merging process requires pretending that the input object
// has the same size as the underlying matrix.
// while iterating through the elements of the input object,
// this requires adjusting the row and column locations of each element,
// as well as providing fake zero elements.
// in effect there is a proxy for a proxy.
const SpProxy< SpMat<eT> > pa((*this).m );
const SpProxy< T1 > pb(in.get_ref());
arma_debug_assert_same_size(n_rows, n_cols, pb.get_n_rows(), pb.get_n_cols(), "insertion into sparse submatrix");
const uword pa_start_row = (*this).aux_row1;
const uword pa_start_col = (*this).aux_col1;
const uword pa_end_row = pa_start_row + (*this).n_rows - 1;
const uword pa_end_col = pa_start_col + (*this).n_cols - 1;
const uword pa_n_rows = pa.get_n_rows();
SpMat<eT> out(pa.get_n_rows(), pa.get_n_cols());
const uword alt_count = pa.get_n_nonzero() - (*this).n_nonzero + pb.get_n_nonzero();
// Resize memory to correct size.
out.mem_resize(alt_count);
typename SpProxy< SpMat<eT> >::const_iterator_type x_it = pa.begin();
typename SpProxy< SpMat<eT> >::const_iterator_type x_end = pa.end();
typename SpProxy<T1>::const_iterator_type y_it = pb.begin();
typename SpProxy<T1>::const_iterator_type y_end = pb.end();
bool x_it_ok = (x_it != x_end);
bool y_it_ok = (y_it != y_end);
uword x_it_row = (x_it_ok) ? x_it.row() : 0;
uword x_it_col = (x_it_ok) ? x_it.col() : 0;
uword y_it_row = (y_it_ok) ? y_it.row() + pa_start_row : 0;
uword y_it_col = (y_it_ok) ? y_it.col() + pa_start_col : 0;
uword cur_val = 0;
while(x_it_ok || y_it_ok)
{
const bool x_inside_box = (x_it_row >= pa_start_row) && (x_it_row <= pa_end_row) && (x_it_col >= pa_start_col) && (x_it_col <= pa_end_col);
const bool y_inside_box = (y_it_row >= pa_start_row) && (y_it_row <= pa_end_row) && (y_it_col >= pa_start_col) && (y_it_col <= pa_end_col);
const eT x_val = x_inside_box ? eT(0) : ( x_it_ok ? (*x_it) : eT(0) );
const eT y_val = y_inside_box ? ( y_it_ok ? (*y_it) : eT(0) ) : eT(0);
if( (x_it_row == y_it_row) && (x_it_col == y_it_col) )
{
if( (x_val != eT(0)) || (y_val != eT(0)) )
{
access::rw(out.values[cur_val]) = (x_val != eT(0)) ? x_val : y_val;
access::rw(out.row_indices[cur_val]) = x_it_row;
++access::rw(out.col_ptrs[x_it_col + 1]);
++cur_val;
}
if(x_it_ok)
{
++x_it;
if(x_it == x_end) { x_it_ok = false; }
}
if(x_it_ok)
{
x_it_row = x_it.row();
x_it_col = x_it.col();
}
else
{
x_it_row++;
if(x_it_row >= pa_n_rows) { x_it_row = 0; x_it_col++; }
}
if(y_it_ok)
{
++y_it;
if(y_it == y_end) { y_it_ok = false; }
}
//.........这里部分代码省略.........
示例12: while
arma_hot
inline
void
spglue_minus::apply_noalias(SpMat<eT>& out, const SpProxy<T1>& pa, const SpProxy<T2>& pb)
{
arma_extra_debug_sigprint();
arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_rows(), pb.get_n_cols(), "subtraction");
if(pa.get_n_nonzero() == 0) { out = pb.Q; out *= eT(-1); return; }
if(pb.get_n_nonzero() == 0) { out = pa.Q; return; }
const uword max_n_nonzero = spglue_elem_helper::max_n_nonzero_plus(pa, pb);
// Resize memory to upper bound
out.reserve(pa.get_n_rows(), pa.get_n_cols(), max_n_nonzero);
// Now iterate across both matrices.
typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
typename SpProxy<T1>::const_iterator_type x_end = pa.end();
typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
typename SpProxy<T2>::const_iterator_type y_end = pb.end();
uword count = 0;
while( (x_it != x_end) || (y_it != y_end) )
{
eT out_val;
const uword x_it_row = x_it.row();
const uword x_it_col = x_it.col();
const uword y_it_row = y_it.row();
const uword y_it_col = y_it.col();
bool use_y_loc = false;
if(x_it == y_it)
{
out_val = (*x_it) - (*y_it);
++x_it;
++y_it;
}
else
{
if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end
{
out_val = (*x_it);
++x_it;
}
else
{
out_val = -(*y_it); // take the negative
++y_it;
use_y_loc = true;
}
}
if(out_val != eT(0))
{
access::rw(out.values[count]) = out_val;
const uword out_row = (use_y_loc == false) ? x_it_row : y_it_row;
const uword out_col = (use_y_loc == false) ? x_it_col : y_it_col;
access::rw(out.row_indices[count]) = out_row;
access::rw(out.col_ptrs[out_col + 1])++;
++count;
}
}
const uword out_n_cols = out.n_cols;
uword* col_ptrs = access::rwp(out.col_ptrs);
// Fix column pointers to be cumulative.
for(uword c = 1; c <= out_n_cols; ++c)
{
col_ptrs[c] += col_ptrs[c - 1];
}
if(count < max_n_nonzero)
{
if(count <= (max_n_nonzero/2))
{
out.mem_resize(count);
}
else
{
// quick resize without reallocating memory and copying data
access::rw( out.n_nonzero) = count;
access::rw( out.values[count]) = eT(0);
access::rw(out.row_indices[count]) = uword(0);
}
}
//.........这里部分代码省略.........
示例13: index
arma_hot
inline
void
spglue_times::apply_noalias(SpMat<eT>& c, const SpProxy<T1>& pa, const SpProxy<T2>& pb)
{
arma_extra_debug_sigprint();
const uword x_n_rows = pa.get_n_rows();
const uword x_n_cols = pa.get_n_cols();
const uword y_n_rows = pb.get_n_rows();
const uword y_n_cols = pb.get_n_cols();
arma_debug_assert_mul_size(x_n_rows, x_n_cols, y_n_rows, y_n_cols, "matrix multiplication");
// First we must determine the structure of the new matrix (column pointers).
// This follows the algorithm described in 'Sparse Matrix Multiplication
// Package (SMMP)' (R.E. Bank and C.C. Douglas, 2001). Their description of
// "SYMBMM" does not include anything about memory allocation. In addition it
// does not consider that there may be elements which space may be allocated
// for but which evaluate to zero anyway. So we have to modify the algorithm
// to work that way. For the "SYMBMM" implementation we will not determine
// the row indices but instead just the column pointers.
//SpMat<typename T1::elem_type> c(x_n_rows, y_n_cols); // Initializes col_ptrs to 0.
c.zeros(x_n_rows, y_n_cols);
//if( (pa.get_n_elem() == 0) || (pb.get_n_elem() == 0) )
if( (pa.get_n_nonzero() == 0) || (pb.get_n_nonzero() == 0) )
{
return;
}
// Auxiliary storage which denotes when items have been found.
podarray<uword> index(x_n_rows);
index.fill(x_n_rows); // Fill with invalid links.
typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
typename SpProxy<T2>::const_iterator_type y_end = pb.end();
// SYMBMM: calculate column pointers for resultant matrix to obtain a good
// upper bound on the number of nonzero elements.
uword cur_col_length = 0;
uword last_ind = x_n_rows + 1;
do
{
const uword y_it_row = y_it.row();
// Look through the column that this point (*y_it) could affect.
typename SpProxy<T1>::const_iterator_type x_it = pa.begin_col(y_it_row);
while(x_it.col() == y_it_row)
{
// A point at x(i, j) and y(j, k) implies a point at c(i, k).
if(index[x_it.row()] == x_n_rows)
{
index[x_it.row()] = last_ind;
last_ind = x_it.row();
++cur_col_length;
}
++x_it;
}
const uword old_col = y_it.col();
++y_it;
// See if column incremented.
if(old_col != y_it.col())
{
// Set column pointer (this is not a cumulative count; that is done later).
access::rw(c.col_ptrs[old_col + 1]) = cur_col_length;
cur_col_length = 0;
// Return index markers to zero. Use last_ind for traversal.
while(last_ind != x_n_rows + 1)
{
const uword tmp = index[last_ind];
index[last_ind] = x_n_rows;
last_ind = tmp;
}
}
}
while(y_it != y_end);
// Accumulate column pointers.
for(uword i = 0; i < c.n_cols; ++i)
{
access::rw(c.col_ptrs[i + 1]) += c.col_ptrs[i];
}
// Now that we know a decent bound on the number of nonzero elements, allocate
// the memory and fill it.
c.mem_resize(c.col_ptrs[c.n_cols]);
// Now the implementation of the NUMBMM algorithm.
uword cur_pos = 0; // Current position in c matrix.
podarray<eT> sums(x_n_rows); // Partial sums.
sums.zeros();
// setting the size of 'sorted_indices' to x_n_rows is a better-than-nothing guess;
//.........这里部分代码省略.........