Regarding the code shown below:
#include <cmath>
int main()
{
const int n = 10000;
const int K = 10;
double* matrix = new double[n * n];
for(int k = 0; k < K; ++k) {
for(int j = 0; j < n; ++j) {
for(int i = 0; i < n; ++i) {
double ai = (double)i/double(n);
double aj = (double)i/double(n);
matrix[i * n + j] += pow(n, (double)k / K) / exp((double)k / K) * pow(sin(ai),2) * pow(sin(aj),2);
}
}
}
}
Is the way that lines
double ai = (double)i/double(n);
double aj = (double)i/double(n);
are defined is because we want floating-point division as opposed to integer division?
In addition, why are the operands cast in the way they are, i.e (double)i/double(n) instead of double(i)/double(n)?
Yes because if i and n are two integers as follow:
int i = ...;
int n = ...;
double ai = i/n
This will be an integer division. Say i=5 and n=9, even ai being a double it will end up with 0 as result.
You can either cast i or n to tell the compiler that you want a float division.
Yes. Actually, it would be enough to cast just one of the operands, but some programmers prefer to cast all the operands for consistency and more clarity.
Related
double CountSum(double **mat, int R, int C)
{
double sum = 0.0;
for(int i = 0; i < R / 2; i++)
{
for(int j = 0; j < C / 2; j++)
{
sum += mat[i][j];
}
}
return sum;
}
Am I correct do this, or where I have mistakes? Or if you have some piece of advice on how to pass parameters to function, please tell me about that
Assuming R and C are number of rows and number of columns respectively, this code won't work.
If R = 2 then (R - 1) / 2 = 0 so the outer loop won't be executed, because i < 0 is always false.
Don't subtract one, R / 2 would be enough. There are corner cases though, when R and C aren't even.
About parameters: you can add R and C to parameter list instead of i and j. (double **mat, int R, int C) and pass them respectively. From this current code, it looks like they are just global variables. i and j can be declared inside the function.
Code:
double CountSum(double **mat, int R, int C)
{
double sum = 0.0;
for(int i = 0; i < R / 2; i++)
{
for(int j = 0; j < C / 2; j++)
{
sum += mat[i][j];
}
}
return sum;
}
This is the working code, I hope you understand how to use it - pass it an appropriate arguments. R and C being height and width of the matrix or dimensions can be called as well. Note that if R or C or both are odd, then you only get the sum of the smaller part always, if you want the bigger part, you should ceil it, thus use (R + 1) / 2 instead of R / 2 and similar for C.
I am trying the following:
Eigen::SparseMatrix<double> bijection(2 * face_count, 2 * vert_count);
/* initialization */
Eigen::VectorXd toggles(2 * vert_count);
toggles.setOnes();
Eigen::SparseMatrix<double> deformed;
deformed = bijection * toggles;
Eigen is returning an error claiming:
error: static assertion failed: THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS
586 | EIGEN_STATIC_ASSERT((internal::is_same<Dest,void>::value),THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS);
According to the eigen documentaion
Sparse matrix and vector products are allowed. What am I doing wrong?
The problem is you have the wrong output type for the product.
The Eigen documentation states that the following type of multiplication is defined:
dv2 = sm1 * dv1;
Sparse matrix times dense vector equals dense vector.
If you actually do need a sparse representation, I think there is no better way of getting one than performing the multiplication as above and then converting the product to a sparse matrix with the sparseView member function. e.g.
Eigen::SparseMatrix<double> bijection(2 * face_count, 2 * vert_count);
/* initialization */
Eigen::VectorXd toggles(2 * vert_count);
toggles.setOnes();
Eigen::VectorXd deformedDense = bijection * toggles;
Eigen::SparseMatrix<double> deformedSparse = deformedDense.sparseView();
This can be faster than outputting to a dense vector if it is very sparse. Otherwise, 99/100 times the conventional product is faster.
void sparsem_densev_sparsev(const SparseMatrix<double>& A, const VectorX<double>& x, SparseVector<double>& Ax)
{
Ax.resize(x.size());
for (int j = 0; j < A.outerSize(); ++j)
{
if (A.outerIndexPtr()[j + 1] - A.outerIndexPtr()[j] > 0)
{
Ax.insertBack(j) = 0;
}
}
for (int j_idx = 0; j_idx < Ax.nonZeros(); j_idx++)
{
int j = Ax.innerIndexPtr()[j_idx];
for (int k = A.outerIndexPtr()[j]; k < A.outerIndexPtr()[j + 1]; ++k)
{
int i = A.innerIndexPtr()[k];
Ax.valuePtr()[j_idx] += A.valuePtr()[k] * x.coeff(i);
}
}
}
For a (probably not optimal) self-adjoint version (lower triangle), change the j_idx loop to:
for (int j_idx = 0; j_idx < Ax.nonZeros(); j_idx++)
{
int j = Ax.innerIndexPtr()[j_idx];
int i_idx = j_idx;//i>= j, trick to improve binary search
for (int k = A.outerIndexPtr()[j]; k < A.outerIndexPtr()[j + 1]; ++k)
{
int i = A.innerIndexPtr()[k];
Ax.valuePtr()[j_idx] += A.valuePtr()[k] * x.coeff(i);
if (i != j)
{
i_idx = std::distance(Ax.innerIndexPtr(), std::lower_bound(Ax.innerIndexPtr() + i_idx, Ax.innerIndexPtr() + Ax.nonZeros(), i));
Ax.valuePtr()[i_idx] += A.valuePtr()[k] * x.coeff(j);
}
}
}
I have a 3007 x 1644 dimensional matrix of terms and documents. I am trying to assign weights to frequency of terms in each document so I'm using this log entropy formula http://en.wikipedia.org/wiki/Latent_semantic_indexing#Term_Document_Matrix (See entropy formula in the last row).
I'm successfully doing this but my code is running for >7 minutes.
Here's the code:
int N = mat.cols();
for(int i=1;i<=mat.rows();i++){
double gfi = sum(mat(i,colon()))(1,1); //sum of occurrence of terms
double g =0;
if(gfi != 0){// to avoid divide by zero error
for(int j = 1;j<=N;j++){
double tfij = mat(i,j);
double pij = gfi==0?0.0:tfij/gfi;
pij = pij + 1; //avoid log0
double G = (pij * log(pij))/log(N);
g = g + G;
}
}
double gi = 1 - g;
for(int j=1;j<=N;j++){
double tfij = mat(i,j) + 1;//avoid log0
double aij = gi * log(tfij);
mat(i,j) = aij;
}
}
Anyone have ideas how I can optimize this to make it faster? Oh and mat is a RealSparseMatrix from amlpp matrix library.
UPDATE
Code runs on Linux mint with 4gb RAM and AMD Athlon II dual core
Running time before change: > 7mins
After #Kereks answer: 4.1sec
Here's a very naive rewrite that removes some redundancies:
int const N = mat.cols();
double const logN = log(N);
for (int i = 1; i <= mat.rows(); ++i)
{
double const gfi = sum(mat(i, colon()))(1, 1); // sum of occurrence of terms
double g = 0;
if (gfi != 0)
{
for (int j = 1; j <= N; ++j)
{
double const pij = mat(i, j) / gfi + 1;
g += pij * log(pij);
}
g /= logN;
}
for (int j = 1; j <= N; ++j)
{
mat(i,j) = (1 - g) * log(mat(i, j) + 1);
}
}
Also make sure that the matrix data structure is sane (e.g. a flat array accessed in strides; not a bunch of dynamically allocated rows).
Also, I think the first + 1 is a bit silly. You know that x -> x * log(x) is continuous at zero with limit zero, so you should write:
double const pij = mat(i, j) / gfi;
if (pij != 0) { g += pij + log(pij); }
In fact, you might even write the first inner for loop like this, avoiding a division when it isn't needed:
for (int j = 1; j <= N; ++j)
{
if (double pij = mat(i, j))
{
pij /= gfi;
g += pij * log(pij);
}
}
I'm trying to multiply two matrices stored inside 1d arrays.
I'm using this function, but my program crashes, I assume due to an out of bounds error.
However, I have no (easy) ability to debug, so I have to decide if my code is correct, and to me it seems it is...
void SampleUtils::multiplyMatrices(float* matA, int rA, int cA, float* matB,
int rB, int cB, float* matC, int rC, int cC) {
for (int i = 0; i <= rA; i++) {
for (int j = 0; j <= cB; j++) {
float sum = 0.0;
for (int k = 0; k <= rB; k++)
sum = sum + matA[i * cA + k] * matB[k * cB + j];
matC[i * cC + j] = sum;
}
}
So, can anyone find out what I did wrong?
Thanks...
Chances are you mean < instead of <= in your for loops.
Try to use i < rA , j < cB, k < rB in your for
I can't figure out why I keep getting the result 1.#INF from my_exp() when I give it 1 as input. Here is the code:
double factorial(const int k)
{
int prod = 1;
for(int i=1; i<=k; i++)
prod = i * prod;
return prod;
}
double power(const double base, const int exponent)
{
double result = 1;
for(int i=1; i<=exponent; i++)
result = result * base;
return result;
}
double my_exp(double x)
{
double sum = 1 + x;
for(int k=2; k<50; k++)
sum = sum + power(x,k) / factorial(k);
return sum;
}
You have an integer overflow in your factorial function. This causes it to output zero. 49! is divisible by 2^32, so your factorial function will return zero.
Then you divide by it causing it to go infinity. So the solution is to change prod to double:
double prod = 1;
Instead of completely evaluating the power and the factorial terms for each term in your expansion, you should consider how the k'th term is related to the k-1'th term and just update each term based on this relationship. That will avoid the nasty overflows in your power and factorial functions (which you will no longer need). E.g.
double my_exp(double x)
{
double sum = 1.0 + x;
double term = x; // term for k = 1 is just x
for (int k = 2; k < 50; k++)
{
term = term * x / (double)k; // term[k] = term[k-1] * x / k
sum = sum + term;
}
return sum;
}
you should just reduce max of k form 50 to like 30 it will work;
and one question your code work just near 0 ?