Eigen: how can I substitute matrix positive values with 1 and 0 otherwise? - matlab

I want to write the following matlab code in Eigen (where K is pxp and W is pxb):
H = (K*W)>0;
However the only thing that I came up so far is:
H = ((K*W.array() > 0).select(1,0));
This code doesn't work as explained here, but replacing 0 with VectorXd::Constant(p,0) (as suggested in the link question) generates a runtime error:
Eigen::internal::variable_if_dynamic<T, Value>::variable_if_dynamic(T) [with T = long int; int Value = 1]: Assertion `v == T(Value)' failed.
How can I solve this?

You don't need .select(). You just need to cast an array of bool to an array of H's component type.
H = ((K * W).array() > 0.0).cast<double>();
Your original attempt failed because the size of your constant 1/0 array is not match with the size of H. Using VectorXd::Constant is not a good choice when H is MatrixXd. You also have a problem with parentheses. I think you want * rather than .* in matlab notation.
#include <iostream>
#include <Eigen/Eigen>
using namespace Eigen;
int main() {
const int p = 5;
const int b = 10;
MatrixXd H(p, b), K(p, p), W(p, b);
K.setRandom();
W.setRandom();
H = ((K * W).array() > 0.0).cast<double>();
std::cout << H << std::endl << std::endl;
H = ((K * W).array() > 0).select(MatrixXd::Constant(p, b, 1),
MatrixXd::Constant(p, b, 0));
std::cout << H << std::endl;
return 0;
}
When calling a template member function in a template, you need to use the template keyword.
#include <iostream>
#include <Eigen/Eigen>
using namespace Eigen;
template<typename Mat, typename Vec>
void createHashTable(const Mat &K, Eigen::MatrixXi &H, Mat &W, int b) {
Mat CK = K;
H = ((CK * W).array() > 0.0).template cast<int>();
}
int main() {
const int p = 5;
const int b = 10;
Eigen::MatrixXi H(p, b);
Eigen::MatrixXf W(p, b), K(p, p);
K.setRandom();
W.setRandom();
createHashTable<Eigen::MatrixXf, Eigen::VectorXf>(K, H, W, b);
std::cout << H << std::endl;
return 0;
}
See this for some explanation.
Issue casting C++ Eigen::Matrix types via templates

Related

Is there a space efficient way to compute the gcd of high exponents?

Basically, I am writing a program that works with large integer values that overflow the cpp integer. I am trying to compute something like: gdc(pow(a, b), c) where a ^ b is the value overflowing the integer limit. Is there a way to do this where I don't have to rely on big integer libraries? If not, are there any recommended big integer libraries?
We can use a property of greatest common divisor that gcd(a, b) = gcd(a % b, b). Hence gcd(pow(a, b), c) = gcd(pow(a, b) % c, c) = gcd(powmod(a, b, c), c), where powmod() is modular exponentiation.
In my C++ code below PowMod() is implemented using exponentiation by squaring approach.
Try it online!
#include <cstdint>
#include <iostream>
using Word = uint32_t;
using DWord = uint64_t;
Word GCD(Word a, Word b) {
Word t = 0;
while (b != 0) {
t = b;
b = a % b;
a = t;
}
return a;
}
Word PowMod(Word a, Word b, Word c) {
Word r = 1;
while (b != 0) {
if (b & 1)
r = (DWord(r) * a) % c;
a = (DWord(a) * a) % c;
b >>= 1;
}
return r;
}
int main() {
Word const
a = 2645680092U, b = 3562429202U, c = 3045001828U,
powmod = PowMod(a, b, c), gcd = GCD(powmod, c);
std::cout << "a = " << a << ", b = " << b
<< ", c = " << c << std::endl;
std::cout << "PowMod(a, b, c) = "
<< powmod << std::endl; // 592284924
std::cout << "GCD(PowMod(a, b, c), c) = "
<< gcd << std::endl; // 1892
}
Output:
a = 2645680092, b = 3562429202, c = 3045001828
PowMod(a, b, c) = 592284924
GCD(PowMod(a, b, c), c) = 1892
which gives correct results, that can be verified through following simple Python program giving same result:
Try it online!
import random, math
random.seed(0)
bits = 32
while True:
c = random.randrange(1 << (bits - 1), 1 << bits)
a = random.randrange(1 << (bits - 1), 1 << bits) % c
b = random.randrange(1 << (bits - 1), 1 << bits)
pm = pow(a, b, c)
gcd = math.gcd(pm, c)
if gcd >= 1000:
print('a =', a, ', b =', b, ', c =', c,
', powmod =', pm, ', gcd =', gcd)
break
Output:
a = 2645680092 , b = 3562429202 , c = 3045001828 ,
powmod = 592284924 , gcd = 1892
If you have GCC/CLang compiler, you can make Word to be 64-bit and DWord to be 128-bit, by changing following lines of code:
using Word = uint64_t;
using DWord = unsigned __int128;
my code supports 32-bit inputs, but after this change you can have 64-bit inputs.
Part 2. Using large integer arithmetics library GMP.
If for some reason you have large input integers then you can use great library GMP for large arithmetics (it supports integer, rational, floating point numbers).
This library has all mathematical operations, including modular exponentiation (PowMod) and some number theoretical functions (including GCD). Also this library is very popular and highly optimized.
In following code I do same things like in me code above, but using only GMP's functions. As an example I use 512-bit integers to show that it can accept large inputs (it can accept even millions of digits):
Try it online!
#include <iostream>
#include <cstdlib>
#include <gmpxx.h>
int main() {
mpz_class const
a("1953143455988359840868749111326065201169739169335107410565117106311318704164104986194255770982854472823807334163384557922525376038346976291413843761504166", 10),
b("5126002245539530470958611905297854592859344951467500786493685495603638740444446597426402800257519403404965463713689509774040138494219032682986554069941558", 10),
c("4396071968291195248321035664209400217968667450140674696924686844534284953565382985421958604880273584922294910355449271193696338132720472184903935323837626", 10);
mpz_class powmod, gcd;
// PowMod
mpz_powm(powmod.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t(), c.get_mpz_t()); // 1632164707041502536171492944083090257113212090861915134477312917063125646194834706890409016008321666479437224930114914370387958138698748075752168351835856
// GCD
mpz_gcd(gcd.get_mpz_t(), powmod.get_mpz_t(), c.get_mpz_t()); // 51842
// Output
std::cout << "PowMod = " << powmod.get_str() << std::endl
<< "GCD = " << gcd.get_str() << std::endl;
}
Output:
PowMod = 1632164707041502536171492944083090257113212090861915134477312917063125646194834706890409016008321666479437224930114914370387958138698748075752168351835856
GCD = 51842
To use GMP library under Linux just install sudo apt install libgmp-dev and compile clang++ -std=c++11 -O2 -lgmp -o main main.cpp.
Using GMP under Windows is a bit more tricky. One way is to build yourself MPIR library which is a Windows friendly clone of GMP. Another way is to install MSYS and use prebuilt GMP from there following these instructions that I wrote in my other answer.

How to emulate *really simple* variable bit shifts with SSE?

I have two variable bit-shifting code fragments that I want to SSE-vectorize by some means:
1) a = 1 << b (where b = 0..7 exactly), i.e. 0/1/2/3/4/5/6/7 -> 1/2/4/8/16/32/64/128/256
2) a = 1 << (8 * b) (where b = 0..7 exactly), i.e. 0/1/2/3/4/5/6/7 -> 1/0x100/0x10000/etc
OK, I know that AMD's XOP VPSHLQ would do this, as would AVX2's VPSHLQ. But my challenge here is whether this can be achieved on 'normal' (i.e. up to SSE4.2) SSE.
So, is there some funky SSE-family opcode sequence that will achieve the effect of either of these code fragments? These only need yield the listed output values for the specific input values (0-7).
Update: here's my attempt at 1), based on Peter Cordes' suggestion of using the floating point exponent to do simple variable bitshifting:
#include <stdint.h>
typedef union
{
int32_t i;
float f;
} uSpec;
void do_pow2(uint64_t *in_array, uint64_t *out_array, int num_loops)
{
uSpec u;
for (int i=0; i<num_loops; i++)
{
int32_t x = *(int32_t *)&in_array[i];
u.i = (127 + x) << 23;
int32_t r = (int32_t) u.f;
out_array[i] = r;
}
}

How can I convert the input operator (+,-) to math in C

Assume that the given input are 5,+,5 in C.
ex)
5
+
5
And I would like to get the answer 10.
I thought code like the below.
#include
using namespace std;
int main(){
char a,b,symbol;
cin >> a >> symbol >> b;
printf("%d", (a-'0') symbol (b-'0'));
return 0;
}
Expected value is 10. However, I got an error in symbol
How would I get the solution?
There are multiple things that I noticed:
First, you are printing integer, but a and b are both chars.
Knowing that there are only a few symbols that you can use, maybe a switch case would be more appropriate?
int main(){
int a, b;
char symbol;
switch(symbol){
case('-'): print("%d", a - b);
case('+'): print("%d", a + b);
case('*'): print("%d", a * b);
case('/'): print("%d", a / b);
case('%'): print("%d", a % b);
default : print("Not a known symbol");
}
Second: Why are you substracting a from the character 0?

Incorrect output of quadratic equation

I have a problem, and I don't know how to deal with it. I made a simple calculator with few functions. Every option is working fine, but I have problem when it comes to quadratic equation. When I put any numbers the response that I get is "The roots of the equations are : x=1.79599e-307. I don't know to deal with it - can you help me ? I will post parts of my code that includes the problem. Thanks You for any feedback and help!
main:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "kalkulator.cpp"
...
using namespace std;
case 10:
cout<<"\nQuadratic Equation \n";
cout<<"\nSelect number \n";
cin>>a;
cout<<"\nSelect number \n";
cin>>b;
cout<<"\nSelect bumber \n";
cin>>c;
int r;
r=equation(a, b, c, x1, x2);
if (r==0) cout << "\n No roots\n" << endl;
else if (r==1) cout << "\n 1 root x = " << x1 << endl;
else if (r==2) cout << "\n 2 roots x1 = " << x1 << " and x2 = " << x2 << endl;
break;
kalkulator.cpp
#include "kalkulator.h"
using namespace std;
...
double equation(double a, double b, double c, double x1, double
x2)
{
double delta=b*b-4*a*c;
if (delta<0.0)
{
return 0;}
if (delta==0.0)
{
x1=-b/(2*a);
return 1;}
else
{
delta=sqrt(delta);
x1==(-b-delta)/(2*a);
x2==(-b+delta)/(2*a);
return 2;}}
kalkulator.h
#ifndef kalkulator_H
#define kalkulator_H
class kalkulator
{
private:
double a;
double b;
double c;
double x1;
double x2;
public:
double equation(double, double, double, double, double);
};
#endif
If you want to set x1 and x2 through the supplied parameters, you need to pass them by reference:
double equation(double, double, double, double&, double&);
and
double equation(double a, double b, double c, double & x1, double & x2)
Also, in the last lines of your code, "x1==" and "x2==" should be "x1=" and "x2=".

how to convert variable type integer to double

I want to convert integers to double in the following piece of code:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int a , b;
double c;
cout<<"Enter two integers: ";
cin>>a>>b;
try
{
if (b == 0)
throw 0;
}
catch (int a)
{
cout<<"You made a division by zero?"<<endl<<a;
}
c = static_cast<double>(a/b);
cout<<"The division is: "<<fixed<<setprecision(2)<<c;
}
How to change the code to output the double value?
As mentioned you should cast not a result of division but variables itself, to get double value. All three options works.
int a, b;
double c;
std::cout << "Enter two integers: ";
std::cin >> a >> b;
try
{
if (b == 0)
throw 0;
}
catch (int a)
{
std::cout << "You made a division by zero?" << std::endl << a;
}
c = static_cast<double>(a) / b;
c = a / static_cast<double>(b);
c = static_cast<double>(a) / static_cast<double>(b);
std::cout << "The division is: " << std::fixed << std::setprecision(2) << c;
std::cin >> a >> b;
You are casting the result of the division, you should cast the operands instead.
Don't use an exception to catch a condition that you already catch using a simple if. Just use the if, and use an else to skip the division if the second operand is zero.
int a , b;
double c;
cout<<"Enter two integers: ";
cin>>a>>b;
if (b == 0) {
cout<<"You made a division by zero?"<<endl;
} else {
c = static_cast<double>(a) / static_cast<double>(b);
cout<<"The division is: "<<fixed<<setprecision(2)<<c;
}