SIMD (AVX): how to 'blend' floats via runtime-computed mask? - sse

How to conditionally keep `equal floats using AVX intrinsics?
I have
__m256 valA = .....;
__m256 valB = .....;
__m256 aIsB = _mm256_cmp_ps( valA, valB, _CMP_EQ_OS );
After getting such a mask I intended to use
__m256 zeros = _mm256_set1_ps(0.0f)
__m256 same = _mm256_blend_ps(valA, zeros, aIsB);//<--aIsB must actually be imm8
however _mm256_blend_ps requires mask to be a runtime compile constant.
Otherwise I would somehow need to cast __m256 into imm8
Should I use some other function?
Documentation:
_mm256_blend_ps
_mm256_cpm_ps
"AVX compare" predicate variants

The instruction you were looking for is blendvps, but if you want to have zero at every entry which does not fulfill the comparison, you can simply use andps.
__m256 aIsB = _mm256_cmp_ps( valA, valB, _CMP_EQ_OS );
__m256 same = _mm256_and_ps( valA, aIsB);

Related

Adding a scalar to a Mat object

So I'm trying to add a scalar value to all elements of a Mat object in openCV, however for raw_t_ubit8 and raw_t_ubit16 types I get wrong results. Here's the code.
Mat A;
//Initialize Mat A;
A = A + 0.1;
The Matrix is initially
The result of the addition is exactly the same matrix. This problem does not occur when I try to add scalars to raw_t_real types of matrices. By raw_t_ubit8 I mean the depth is CV_8UC1
If, as you mentioned in the comments, the contained values are scaled in the matrix to fit the integer domain 0..255, then you should also scale the scalar value you sum. Namely:
A = A + cv::Scalar(round(0.1 * 255) );
Or even better:
A += cv::Scalar(round(0.1 * 255) );
Note that cv::Scalar, as pointed out in the comments by Miki, is in any case made from a double (it's a cv::Scalar_<double>).
The rounding could be omitted, but then you leave the choice on how to convert your double into integer to the function implementation.
You should also check what happens when the values saturate.
Documentation for Opencv matrix expressions.
As stated in the comments and in #Antonio's answer, you can't add 0.1 to an integer.
If you are using CV_8UC1 matrices, but you want to work with floating points values, you should multiply by 255.
Mat1b A; // <-- type CV_8UC1
...
A += 0.1 * 255;
If the result of the operation need to be casted, as in this case, then ultimately saturated_cast is called.
This is equivalent to #Antonio's answer, but it results in cleaner code (at least for me).
The same code will be used, either if you sum a double or a Scalar. A Scalar object will be created in both ways using:
template<typename _Tp> inline
Scalar_<_Tp>::Scalar_(_Tp v0)
{
this->val[0] = v0;
this->val[1] = this->val[2] = this->val[3] = 0;
}
However if you need to sum exactly 0.1 to your matrix (and not to scale it by 255), you need to convert your matrix to CV_32FC1:
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int, char** argv)
{
Mat1b A = (Mat1b(3,3) << 1,2,3,4,5,6,7,8,9);
Mat1f F;
A.convertTo(F, CV_32FC1);
F += 0.1;
return 0;
}

How to convert a tuple of numbers to float in F#?

Suppose I have a tuple of numbers:
let mynum = (3, 5, 8.9, 45, 127.3)
It's mixed int with float. In order to do calculations like average, I have to convert them to float. How to do the conversion?
I don't know how did you end up with that tuple, I would advise to review your design. I personally consider tuples of more than 4 elements a smell, may be a record with named elements would be a best fit.
Anyway you can convert it easily to a list of float and then calculate the average:
let mynum = (3, 5, 8.9, 45, 127.3)
let inline cnv (x1, x2, x3, x4, x5) = [float x1; float x2; float x3; float x4; float x5]
let lst = cnv mynum // float list = [3.0; 5.0; 8.9; 45.0; 127.3]
List.average lst // float = 37.84
How did the input turn out in this format? Tuples aren't supposed to be used in this way; they are intended for combinations of a few objects, which are strongly and independently typed.
The type of a tuple changes with its length, so there is no straightforward way to perform sequence operations on them. They are not compatible with seq<'T> anyway, since they the types of their components are unrelated. There is no average function for tuples, and if there were, it would have to be overloaded for all possible arities (number of components).
You might want to import the data into another collection, such as a list, a set, an array, or another type of sequence, and have the importer handle conversions where necessary. For example, if the input were a list of strings (as taken from a text file or such), System.Double.Parse or, as pointed out by ildjarn in the comments, the float operator, can be used to turn them into floats:
let input = ["3"; "5"; "8.9"; "45"; "127.3"]
List.map float input
This returns [3.0; 5.0; 8.9; 45.0; 127.3], which is of type float list: an immutable, singly-linked list of double-precision floats.

Mat and Vec_ types multiplication

Is there any easy way to multiplicate Mat and Vec_? (Provided, that they have proper sizes, e.g.:
Mat_<double> M = Mat(3,3,CV_32F);
Vec3f V=(1,2,3);
result = M*V //?
Maybe there is some easy method of creating row (or col) Mat based on Vec3?
You can't just multiply Mat and Vec (or, more generally, Matx_) elements. Cast the Vec object to Mat:
Mat_<float> M = Mat::eye(3,3,CV_32F);
Vec3f V=(1,2,3);
Mat result = M*Mat(V);
Also, I noticed an error in your code: when constructing M, the type CV_32F corresponds to float elements, not double. This is also corrected in my code example.
Hope that it helps.

How do I use "i" as an imaginary number in an equation in Objective-C [duplicate]

This question already has answers here:
Are "Complex Numbers" already defined in Objective-C?
(4 answers)
Closed 9 years ago.
Lets say I want to calculate Vout where Vout = (Vin/((I*w*R*C)+1));
where "i" should be defined as the sqrt(-1) . How do I do that in Objective-C?
You can #include <complex.h> then use either _Complex_I or I macros (note the uppercase). The type of variables that contains complex values are denoted with the _Complex attribute, which can also be written simply complex.
double complex c1 = 1.0 + 2.0 * I; // 1+2i
double complex c2 = 2.0 + 3.0 * I; // 2+3i
double complex sum = c1 + c2;
double complex mul = c1 * c2;
You can then use the creal and cimag functions to get real and imaginary parts of a complex.
So in your case:
double Vin = 20; // in Volts
double w = 60; // frequency of your sinusoidal source (60Hz)
double R = 50; // 50 ohms
double C = 20e-6; // 20 µF
double complex invertZc = I*w*C; // Zc = 1/jwC, invertZc = jwC
double complex Vout = Vin / (1. + R*invertZc); // Vout = Vin * 1.0 / (1+Zr/Zc)
Note that all this is provided by the GNU C language (see here), and are not specifically part of Objective-C itself but come from GNU C (Objective-C being a superset of C) and its extensions (which are supported by the GCC and LLVM compilers used by Xcode)
Objective C does not have any built-in facility for handling complex numbers. You have to do the calculations yourself. Create a typedef of a struct imaginaryNumber that contains a real and imaginary part. Write functions that add and multiply those structures and return another one as a result. (To multiply 2 complex numbers (a1+b1i)•(a2+b2i) you treat the numbers as polynomials and use the FOIL method to calculate the result. The product of the 2 imaginary terms becomes a real number because i • i = -1.

how do I do boolean operation on mat, such as mat3 = mat1 & mat2?

I would like to do boolean operation on mat structure.
such as
"and/or/xor" ing two binary images
is it possible to do that ?
just do it !
Mat a,b;
Mat c = a & b;
For the AND and OR operation, here is the syntax :
A | B /* OR operator */
A & B /* AND operator */
The XOR operator doesn't exists, but still, you can do it like this :
(A | B) & (A != B) /* Pseudo-XOR operator */
You may want to check the Compare function to do what you want
All logical operations you have to base on the following functions.
First group of them, consists of three, four parameters functions: bitwise_and(), bitwise_or(), bitwise_xor().
For example:
C++: void bitwise_and(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray())
Python: cv2.bitwise_and(src1, src2[, dst[, mask]]) → dst
There is also bitwise_not(), which takes three parameters.
C++: void bitwise_not(InputArray src, OutputArray dst, InputArray mask=noArray())
Python: cv2.bitwise_not(src[, dst[, mask]]) → dst
Documentation: https://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html

Resources