Related
I am trying to understand the basics of image/video processing and recently I learned that all the processing should be applied to a linear representation of an image. So, I wrote two functions for sRGB -> RGB and RGB -> sRGB:
void sRGB2lRGB(std::vector<unsigned char>& in, std::vector<unsigned char>& out)
{
std::vector<double> temp(in.begin(), in.end());
for (int i = 0; i < temp.size(); i++)
{
temp[i] /= 255.0;
}
for (int i = 0; i < temp.size(); i++)
{
if (temp[i] <= 0.04045)
{
temp[i] /= 12.92;
}
else
{
temp[i] = std::pow((temp[i] + 0.055) / 1.055, 2.4);
}
}
for (int i = 0; i < temp.size(); i++)
{
out[i] = temp[i] * (int)255 + 0.5;
}
}
void lRGB2sRGB(std::vector<unsigned char>& in, std::vector<unsigned char>& out)
{
std::vector<double> temp(in.begin(), in.end());
for (int i = 0; i < temp.size(); i++)
{
temp[i] /= 255.0;
}
for (int i = 0; i < temp.size(); i++)
{
if (temp[i] <= 0.0031308)
{
temp[i] *= 12.92;
}
else
{
temp[i] = 1.055 * std::pow(temp[i], 1.0 / 2.4) - 0.055;
}
}
for (int i = 0; i < temp.size(); i++)
{
out[i] = temp[i] * (int)255 + 0.5;
}
}
To test it I tried this:
int main()
{
std::vector<unsigned char> in(255);
std::vector<unsigned char> out(255);
std::vector<unsigned char> out2(255);
for (int i = 0; i < 255; i++)
{
in[i] = i;
}
sRGB2lRGB(in, out);
lRGB2sRGB(out, out2);
for (int i = 0; i < 255; i++)
{
if (out2[i] != i)
{
std::cout << "was: " << (int)in[i] << ", now: " << (int)out2[i] << '\n';
}
}
}
But it appeared that the closer the value to 0, the more inaccurate the result would be. The output is:
was: 1, now: 0
was: 2, now: 0
was: 3, now: 0
was: 4, now: 0
was: 5, now: 0
was: 6, now: 0
was: 7, now: 13
was: 8, now: 13
was: 9, now: 13
was: 10, now: 13
was: 11, now: 13
was: 12, now: 13
was: 14, now: 13
was: 15, now: 13
was: 16, now: 13
was: 17, now: 13
was: 18, now: 22
was: 19, now: 22
was: 20, now: 22
was: 21, now: 22
was: 23, now: 22
was: 24, now: 22
was: 25, now: 22
was: 26, now: 28
was: 27, now: 28
was: 29, now: 28
was: 30, now: 28
was: 31, now: 28
was: 32, now: 34
was: 33, now: 34
was: 35, now: 34
was: 36, now: 34
was: 37, now: 38
was: 39, now: 38
was: 40, now: 38
was: 41, now: 42
was: 43, now: 42
was: 44, now: 42
was: 45, now: 46
was: 47, now: 46
was: 48, now: 50
was: 49, now: 50
was: 51, now: 50
was: 52, now: 53
was: 54, now: 53
was: 55, now: 56
was: 57, now: 56
was: 58, now: 59
was: 60, now: 61
was: 62, now: 61
was: 63, now: 64
was: 65, now: 64
was: 67, now: 66
was: 68, now: 69
was: 70, now: 71
was: 72, now: 73
was: 74, now: 73
was: 76, now: 75
was: 78, now: 77
was: 80, now: 79
was: 82, now: 83
was: 84, now: 85
was: 87, now: 86
was: 89, now: 88
was: 91, now: 92
was: 94, now: 95
was: 97, now: 96
was: 100, now: 99
was: 103, now: 104
was: 107, now: 106
was: 111, now: 112
was: 116, now: 117
was: 123, now: 124
Where am I wrong?
Because you are quantizing the linear floating-point values by casting them to integer representation, the conversion will indeed be destructive.
However, there should be no surprise that this occurs: it is actually the intent when encoding data with the sRGB inverse electro-optical transfer function (EOTF). The purpose is to carry data over 8-bit signals while maintaining a good perceptual uniformity with an overall reduced bandwidth.
I would refer to Charles Poynton's Gamma Faq and Poynton, C., & Funt, B. (2014). Perceptual uniformity in digital image representation and display. Color Research and Application, 39(1), 6–15. https://doi.org/10.1002/col.21768
Note that "Conversation" should be "conversion" here.
I have uint16_t color and need to convert it into its RGB equivalent. The hex is set up so the first 5 bits represent red, next 6 for green, and last 5 for blue.
So far I have found something close to a solution but not quite due to truncation.
void hexToRGB(uint16_t hexValue)
{
int r = ((hexValue >> 11) & 0x1F); // Extract the 5 R bits
int g = ((hexValue >> 5) & 0x3F); // Extract the 6 G bits
int b = ((hexValue) & 0x1F); // Extract the 5 B bits
r = ((r * 255) / 31) - 4;
g = ((g * 255) / 63) - 2;
b = ((b * 255) / 31) - 4;
printf("r: %d, g: %d, b: %d\n",r, g, b);
}
int main()
{
//50712=0xC618
hexToRGB(50712);
return 0;
}
The example above yields r: 193, g: 192, b: 193 which should be r: 192, g: 192, b: 192 I have been using this question as reference, but I essentially need a backwards solution to what they are asking.
What about the following:
unsigned r = (hexValue & 0xF800) >> 8; // rrrrr... ........ -> rrrrr000
unsigned g = (hexValue & 0x07E0) >> 3; // .....ggg ggg..... -> gggggg00
unsigned b = (hexValue & 0x1F) << 3; // ............bbbbb -> bbbbb000
printf("r: %d, g: %d, b: %d\n", r, g, b);
That should result in 0xC618 --> 192, 192, 192, but 0xFFFF --> 248, 252, 248, i.e. not pure white.
If you want 0xFFFF to be pure white, you'll have to scale, so
unsigned r = (hexValue & 0xF800) >> 11;
unsigned g = (hexValue & 0x07E0) >> 5;
unsigned b = hexValue & 0x001F;
r = (r * 255) / 31;
g = (g * 255) / 63;
b = (b * 255) / 31;
Then 0xC618 --> 197, 194, 197, instead of the expected 192, 192, 192, but 0xFFFF is pure white and 0x0000 is pure black.
There are no "correct" ways to convert from the RGB565 scale to RGB888. Each colour component needs to be scaled from its 5-bit or 6-bit range to an 8-bit range and there are varying ways to do this each often producing different types of visual artifact in an image.
When scaling a colour in the n-bit range we might decide we want the following to be generally true:
that absolute black (eg 00000 in 5-bit space) must map to absolute black in 8-bit space;
that absolute white (eg 11111 in 5-bit space) must map to absolute white in 8-bit space;
Achieving this means we basically wish to scale the value from (2n - 1) shades in n-bit space into (28 - 1) shades in 8-bit space. That is, we want to effectively do the following in some way:
r_8 = (255 * r / 31)
g_8 = (255 * g / 63)
b_8 = (255 * b / 31)
Different approaches often taken are:
scale using integer division
scale using floating division and then round
bitshift into 8-bit space and add the most significant bits
The latter approach is effectively the following
r_8 = (r << 3) | (r >> 2)
g_8 = (g << 2) | (g >> 4)
b_8 = (b << 3) | (b >> 2)
For your 5-bit value 11000 these would result in 8-bit values of:
197
197
198 (11000000 | 110)
Similarly your six bit value 110000 would result in 8-bit values of:
194
194
195 (11000000 | 11)
I am building a program in objective C/C++ and openCV. I am pretty skilled in Objective C but new to C++.
I am building custom RGB2HSV algorithm. My algorithm is slightly different from the openCV library cvtColor(in, out, CV_RGB2HSV).
The one I try to translate form Matlab to opencV/C++ produces so clear HSV image that no additional filtering is needed before further processing. Code below – Matlab code is self-explanatory.
I try to translate it to C++/openCV function out of it but I hit the wall trying to access pixel values of the image. I am new to C++.
I read a lot on the ways how to access Mat structure but usually I obtain either bunch of letters in a place of zeros or a number typically something like this “\202 k g”. When I try to do any multiplication operations on the say \202 the result has nothing to do with math.
Please help me to properly access the pixel values. Also in current version using uchar won’t work because some values are outside 0-255 range.
The algorithm is not mine. I cannot even point the source but it gives clearly better results than stock RGB2HSV.
Also the algorithm below is for one pixel. It needs to be applied each pixel in the image so in final version it need to wrapped with for { for {}} loops.
I also wish to share this method with community so everyone can benefit from it and saving on pre-filtering.
Please help me translate it to C++ / openCV. If possible with the best practices speed wise. Or at least how to clearly access the pixel value so it is workable with range of mathematical equations. Thanks in advance.
function[H, S, V] = rgb2hsvPixel(R,G,B)
% Algorithm:
% In case of 8-bit and 16-bit images, `R`, `G`, and `B` are converted to the
% floating-point format and scaled to fit the 0 to 1 range.
%
% V = max(R,G,B)
% S = / (V - min(R,G,B)) / V if V != 0
% \ 0 otherwise
% / 60*(G-B) / (V - min(R,G,B)) if V=R
% H = | 120 + 60*(B-R) / (V - min(R,G,B)) if V=G
% \ 240 + 60*(R-G) / (V - min(R,G,B)) if V=B
%
% If `H<0` then `H=H+360`. On output `0<=V<=1`, `0<=S<=1`, `0<=H<=360`.
red = (double(R)-16)*255/224; % \
green = (double(G)-16)*255/224; % }- R,G,B (0 <-> 255) -> (-18.2143 <-> 272.0759)
blue = (min(double(B)*2,240)-16)*255/224; % /
minV = min(red,min(green,blue));
value = max(red,max(green,blue));
delta = value - minV;
if(value~=0)
sat = (delta*255) / value;% s
if (delta ~= 0)
if( red == value )
hue = 60*( green - blue ) / delta; % between yellow & magenta
elseif( green == value )
hue = 120 + 60*( blue - red ) / delta; % between cyan & yellow
else
hue = 240 + 60*( red - green ) / delta; % between magenta & cyan
end
if( hue < 0 )
hue = hue + 360;
end
else
hue = 0;
sat = 0;
end
else
% r = g = b = 0
sat = 0;
hue = 0;
end
H = max(min(floor(((hue*255)/360)),255),0);
S = max(min(floor(sat),255),0);
V = max(min(floor(value),255),0);
end
To access the value of a pixel in a 3-channel, 8-bit precision image (type CV_8UC3) you have to do it like this:
cv::Mat image;
cv::Vec3b BGR = image.at<cv::Vec3b>(i,j);
If, as you say, 8-bit precision and range are not enough, you can declare a cv::Mat of type CV_32F to store floating point 32-bit numbers.
cv::Mat image(height, width, CV_32FC3);
//fill your image with data
for(int i = 0; i < image.rows; i++) {
for(int j = 0; j < image.cols; j++) {
cv::Vec3f BGR = image.at<cv::Vec3f>(i,j)
//process your pixel
cv::Vec3f HSV; //your calculated HSV values
image.at<cv::Vec3f>(i,j) = HSV;
}
}
Be aware that OpenCV stores rgb values in the BGR order and not RGB. Take a look at OpenCV docs to learn more about it.
If you are concerned by performance and fairly comfortable with pixel indexes, you can use directly the Mat ptr.
For example:
cv::Mat img = cv::Mat::zeros(4, 8, CV_8UC3);
uchar *ptr_row_img;
int cpt = 0;
for(int i = 0; i < img.rows; i++) {
ptr_row_img = img.ptr<uchar>(i);
for(int j = 0; j < img.cols; j++) {
for(int c = 0; c < img.channels(); c++, cpt++, ++ptr_row_img) {
*ptr_row_img = cpt;
}
}
}
std::cout << "img=\n" << img << std::endl;
The previous code should print:
img= [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23; 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47; 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
69, 70, 71; 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95]
The at access should be enough for most of the cases and is much more readable / less likely to make a mistake than using the ptr access.
References:
How to scan images, lookup tables and time measurement with OpenCV
C++: OpenCV: fast pixel iteration
Thanks everybody for help.
Thanks to your hints I constructed the custom rgb2hsv function C++/openCV.
From the top left respectively, edges after bgr->gray->edges, bgr->HSV->edges, bgr->customHSV->edges
Below each of them corresponding settings of the filters to achieve approximately the same clear results. The bigger the radius of a filter the more complex and time consuming computations.
It produces clearer edges in next steps of image processing.
It can be tweaked further experimenting with parameters in r g b channels:
red = (red-16)*1.1384; //255/244=1.1384
here 16 – the bigger the number the clearer V becomes
255/244 – also affect the outcome extending it beyond ranges 0-255, later to be clipped.
This numbers here seem to be golden ratio but anyone can adjust for specific needs.
With this function translating BGR to RGB can be avoided by directly connecting colors to proper channels in raw image.
Probably it is a little clumsy performance wise. In my case it serves in first step of color balance and histogram adjustment so speed is not that critical.
To use in constant processing video stream it need speed optimization, I think by using pointers and reducing loop complexity. Optimization is not exactly my cup of tea. So if someone helped to optimize it for the community that would be great.
Here it is ready to use:
Mat bgr2hsvCustom ( Mat& image )
{
//smallParam = 16;
for(int x = 0; x < image.rows; x++)
{
for(int y = 0; y<image.cols; y++)
{
//assigning vector to individual float BGR values
float blue = image.at<cv::Vec3b>(x,y)[0];
float green = image.at<cv::Vec3b>(x,y)[1];
float red = image.at<cv::Vec3b>(x,y)[2];
float sat, hue, minValue, maxValue, delta;
float const ang0 = 0; // func min and max don't accept varaible and number
float const ang240 = 240;
float const ang255 = 255;
red = (red-16)*1.1384; //255/244
green = (green-16)*1.1384;
blue = (min(blue*2,ang240)-16)*1.1384;
minValue = min(red,min(green,blue));
maxValue = max(red,max(green,blue));
delta = maxValue - minValue;
if (maxValue != 0)
{
sat = (delta*255) / maxValue;
if ( delta != 0)
{
if (red == maxValue){
hue = 60*(green - blue)/delta;
}
else if( green == maxValue ) {
hue = 120 + 60*( blue - red )/delta;
}
else{
hue = 240 + 60*( red - green )/delta;
}
if( hue < 0 ){
hue = hue + 360;
}
}
else{
sat = 0;
hue = 0;
}
}
else{
hue = 0;
sat = 0;
}
image.at<cv::Vec3b>(x,y)[0] = max(min(floor(maxValue),ang255),ang0); //V
image.at<cv::Vec3b>(x,y)[1] = max(min(floor(sat),ang255),ang0); //S
image.at<cv::Vec3b>(x,y)[2] = max(min(floor(((hue*255)/360)),ang255),ang0); //H
}
}
return image;
}
I'm trying to encode a relatively complex message into a union structure so that I can generate an array of uint8_t that I can feed into a serial communications protocol.
However, when looking at the array generated when my union is filled with data, an extra uint8_t element appears after my command type element. Please see the Union structure below:
union myint16_t{
uint16_t ui16;
int16_t i16;
uint8_t data[2];
};
union {
struct {
uint8_t commandtype;
myint16_t UpperLimits[4];
myint16_t LowerLimits[4];
myint16_t JointZeros[4];
int8_t JointPolarity[4];
myint16_t P[4];
myint16_t I[4];
myint16_t D[4];
};
uint8_t data[53];
};
as you can see there are the second anonymous union references the union myint16_t.
So if I fill all the values of the anonymous union and then print out the underlying data[53] array, my second value (data[1]) is 0 and not part of the first element of UpperLimits[4]. Please see the code where I fill the union and then print out the elements.
char q = 'c';
hmmv4_configmsg msg;
msg.commandtype =(uint8_t) q;
msg.UpperLimits[0].ui16 = 784;
msg.UpperLimits[1].ui16 = 784;
msg.UpperLimits[2].ui16 = 784;
msg.UpperLimits[3].ui16 = 784;
msg.LowerLimits[0].ui16 = 223;
msg.LowerLimits[1].ui16 = 223;
msg.LowerLimits[2].ui16 = 223;
msg.LowerLimits[3].ui16 = 223;
msg.JointZeros[0].ui16 = 512;
msg.JointZeros[1].ui16 = 512;
msg.JointZeros[2].ui16 = 512;
msg.JointZeros[3].ui16 = 512;
msg.JointPolarity[0] = -1;
msg.JointPolarity[1] =-1;
msg.JointPolarity[2] =-1;
msg.JointPolarity[3] =-1;
msg.P[0].i16=4000;
msg.P[1].i16=4000;
msg.P[2].i16=4000;
msg.P[3].i16=4000;
msg.I[0].i16=1;
msg.I[1].i16=1;
msg.I[2].i16=1;
msg.I[3].i16=1;
msg.D[0].i16=24;
msg.D[1].i16=24;
msg.D[2].i16=24;
msg.D[3].i16=24;
//msg.change_endian();
while(1)
{
for(int i =0; i<54; i++)
{
writebuf[i]=msg.data[i];
printf("D: %d, %d \n", i, msg.data[i]);
}
printf("L0: %d, %d, %d", msg.P[0].i16, msg.P[0].data[0], msg.P[0].data[1]);
int r =jointencoder.xfer1(writebuf, readbuf, 54);
}
the output of the printf is (the offending element is D:1 -- it shouldn't be there):
D: 0, 99
D: 1, 0
D: 2, 16
D: 3, 3
D: 4, 16
D: 5, 3
D: 6, 16
D: 7, 3
D: 8, 16
D: 9, 3
D: 10, 223
D: 11, 0
D: 12, 223
D: 13, 0
D: 14, 223
D: 15, 0
D: 16, 223
D: 17, 0
D: 18, 0
D: 19, 2
D: 20, 0
D: 21, 2
D: 22, 0
D: 23, 2
D: 24, 0
D: 25, 2
D: 26, 255
D: 27, 255
D: 28, 255
D: 29, 255
D: 30, 160
D: 31, 15
D: 32, 160
D: 33, 15
D: 34, 160
D: 35, 15
D: 36, 160
D: 37, 15
D: 38, 1
D: 39, 0
D: 40, 1
D: 41, 0
D: 42, 1
D: 43, 0
D: 44, 1
D: 45, 0
D: 46, 24
D: 47, 0
D: 48, 24
D: 49, 0
D: 50, 24
D: 51, 0
D: 52, 24
D: 53, 0
L0: 4000, 160, 15joint encoder transferred
My question is why is D:1 there? My understanding of unions and structures is that because command type is uint8_t, then it should only occupy one data space, and therefore UpperLimits[0] should start on D:1, but it seems that command_type is acting as a uint16_t and posting another bit. Why is this so?
Note: you may see that the index goes up to count data[53] which should be out of bounds, but I need to read this and send it so as to be able to deconstruct the data at the other end.
There is almost certainly a padding byte between commandtype and UpperLimits; the 2-byte myint16_t data type is aligned on an even byte boundary.
struct {
uint8_t commandtype;
myint16_t UpperLimits[4];
...
If you could print the size of the anonymous structure and union, you're likely to find that it is at least 54 bytes (where you think it should be 53). One of the disadvantages of untagged structure types embedded as anonymous members of a union is that there is no easy way to print the size of the structure. Give the structure a tag (struct tag { uint8_t commandtype; ...) so that you can print its size out.
There isn't an easy fix for that using the current framework.
You need to tell the compiler how to align the elements in your union or struct. Simply add #pragma pack(push,1) before your definitions to instruct the compiler to align adjacent elements on one-byte boundaries, and then use #pragma pack(pop) to revert to the compiler's default alignment. For performance reasons, you would not want to use one-byte alignment for all structs/unions/classes, so it's a good idea to wrap your union definition in the pragma pair.
Example:
#pragma pack(push,1)
union
{
uint_8 first;
uint_8 second;
} two_bytes;
#pragma pack(pop)
assert(sizeof two_bytes == 2);
I have to XOR numbers from 1 to N, does there exist a direct formula for it ?
For example if N = 6 then 1^2^3^4^5^6 = 7 I want to do it without using any loop so I need an O(1) formula (if any)
Your formula is N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) ):
int main()
{
int S = 0;
for (int N = 0; N < 50; ++N) {
S = (S^N);
int check = N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) );
std::cout << "N = " << N << ": " << S << ", " << check << std::endl;
if (check != S) throw;
}
return 0;
}
Output:
N = 0: 0, 0 N = 1: 1, 1 N = 2: 3, 3
N = 3: 0, 0 N = 4: 4, 4 N = 5: 1, 1
N = 6: 7, 7 N = 7: 0, 0 N = 8: 8, 8
N = 9: 1, 1 N = 10: 11, 11 N = 11: 0, 0
N = 12: 12, 12 N = 13: 1, 1 N = 14: 15, 15
N = 15: 0, 0 N = 16: 16, 16 N = 17: 1, 1
N = 18: 19, 19 N = 19: 0, 0 N = 20: 20, 20
N = 21: 1, 1 N = 22: 23, 23 N = 23: 0, 0
N = 24: 24, 24 N = 25: 1, 1 N = 26: 27, 27
N = 27: 0, 0 N = 28: 28, 28 N = 29: 1, 1
N = 30: 31, 31 N = 31: 0, 0 N = 32: 32, 32
N = 33: 1, 1 N = 34: 35, 35 N = 35: 0, 0
N = 36: 36, 36 N = 37: 1, 1 N = 38: 39, 39
N = 39: 0, 0 N = 40: 40, 40 N = 41: 1, 1
N = 42: 43, 43 N = 43: 0, 0 N = 44: 44, 44
N = 45: 1, 1 N = 46: 47, 47 N = 47: 0, 0
N = 48: 48, 48 N = 49: 1, 1 N = 50: 51, 51
Explanation:
Low bit is XOR between low bit and next bit.
For each bit except low bit the following holds:
if N is odd then that bit is 0.
if N is even then that bit is equal to corresponded bit of N.
Thus for the case of odd N the result is always 0 or 1.
edit
GSerg Has posted a formula without loops, but deleted it for some reason (undeleted now). The formula is perfectly valid (apart from a little mistake). Here's the C++-like version.
if n % 2 == 1 {
result = (n % 4 == 1) ? 1 : 0;
} else {
result = (n % 4 == 0) ? n : n + 1;
}
One can prove it by induction, checking all reminders of division by 4. Although, no idea how you can come up with it without generating output and seeing regularity.
Please explain your approach a bit more.
Since each bit is independent in xor operation, you can calculate them separately.
Also, if you look at k-th bit of number 0..n, it'll form a pattern. E.g., numbers from 0 to 7 in binary form.
000
001
010
011
100
101
110
111
You see that for k-th bit (k starts from 0), there're 2^k zeroes, 2^k ones, then 2^k zeroes again, etc.
Therefore, you can for each bit calculate how many ones there are without actually going through all numbers from 1 to n.
E.g., for k = 2, there're repeated blocks of 2^2 == 4 zeroes and ones. Then,
int ones = (n / 8) * 4; // full blocks
if (n % 8 >= 4) { // consider incomplete blocks in the end
ones += n % 8 - 3;
}
For odd N, the result is either 1 or 0 (cyclic, 0 for N=3, 1 for N=5, 0 for N=7 etc.)
For even N, the result is either N or N+1 (cyclic, N+1 for N=2, N for N=4, N+1 for N=6, N for N=8 etc).
Pseudocode:
if (N mod 2) = 0
if (N mod 4) = 0 then r = N else r = N+1
else
if (N mod 4) = 1 then r = 1 else r = 0
Lets say the function that XORs all the values from 1 to N be XOR(N), then
XOR(1) = 000 1 = 0 1 ( The 0 is the dec of bin 000)
XOR(2) = 001 1 = 1 1
XOR(3) = 000 0 = 0 0
XOR(4) = 010 0 = 2 0
XOR(5) = 000 1 = 0 1
XOR(6) = 011 1 = 3 1
XOR(7) = 000 0 = 0 0
XOR(8) = 100 0 = 4 0
XOR(9) = 000 1 = 0 1
XOR(10)= 101 1 = 5 1
XOR(11)= 000 0 = 0 0
XOR(12)= 110 0 = 6 0
I hope you can see the pattern. It should be similar for other numbers too.
Try this:
the LSB gets toggled each time the N is odd, so we can say that
rez & 1 == (N & 1) ^ ((N >> 1) & 1)
The same pattern can be observed for the rest of the bits.
Each time the bits B and B+1 (starting from LSB) in N will be different, bit B in the result should be set.
So, the final result will be (including N): rez = N ^ (N >> 1)
EDIT: sorry, it was wrong. the correct answer:
for odd N: rez = (N ^ (N >> 1)) & 1
for even N: rez = (N & ~1) | ((N ^ (N >> 1)) & 1)
Great answer by Alexey Malistov! A variation of his formula: n & 1 ? (n & 2) >> 1 ^ 1 : n | (n & 2) >> 1 or equivalently n & 1 ? !(n & 2) : n | (n & 2) >> 1.
this method avoids using conditionals F(N)=(N&((N&1)-1))|((N&1)^((N&3)>>1)
F(N)= (N&(b0-1)) | (b0^b1)
If you look at the XOR of the first few numbers you get:
N | F(N)
------+------
0001 | 0001
0010 | 0011
0011 | 0000
0100 | 0100
0101 | 0001
0110 | 0111
0111 | 0000
1000 | 1000
1001 | 0001
Hopefully you notice the pattern:
if N mod 4 = 1 than F(N)=1
if N mod 4 = 3 than F(N)=0
if N mod 4 = 0 than F(N)=N
if N mod 4 = 2 than F(N)=N but with the first bit as 1 so N|1
the tricky part is getting this in one statement without conditionals ill explain the logic I used to do this.
take the first 2 significant bits of N call them:
b0 and b1 and these are obtained with:
b0 = N&1
b1 = N&3>>1
Notice that if b0 == 1 we have to 0 all of the bits, but if it isn't all of the bits except for the first bit stay the same. We can do this behavior by:
N & (b0-1) : this works because of 2's complement, -1 is equal to a number with all bits set to 1 and 1-1=0 so when b0=1 this results in F(N)=0.. so that is the first part of the function:
F(N)= (N&(b0-1))...
now this will work for for N mod 4 == 3 and 0, for the other 2 cases lets look solely at b1, b0 and F(N)0:
b0|b1|F(N)0
--+--+-----
1| 1| 0
0| 0| 0
1| 0| 1
0| 1| 1
Ok hopefully this truth table looks familiar! it is b0 XOR b1 (b1^b0). so now that we know how to get the last bit let put that on our function:
F(N)=(N&(b0-1))|b0^b1
and there you go, a function without using conditionals. also this is useful if you want to compute the XOR from positive numbers a to b. you can do:
F(a) XOR F(b).
With minimum change to the original logic:
int xor = 0;
for (int i = 1; i <= N; i++) {
xor ^= i;
}
We can have:
int xor = 0;
for (int i = N - (N % 4); i <= N; i++) {
xor ^= i;
}
It does have a loop but it would take a constant time to execute. The number of times we iterate through the for-loop would vary between 1 and 4.
How about this?
!(n&1)*n+(n%4&n%4<3)
This works fine without any issues for any n;
unsigned int xorn(unsigned int n)
{
if (n % 4 == 0)
return n;
else if(n % 4 == 1)
return 1;
else if(n % 4 == 2)
return n+1;
else
return 0;
}
Take a look at this. This will solve your problem.
https://stackoverflow.com/a/10670524/4973570
To calculate the XOR sum from 1 to N:
int ans,mod=N%4;
if(mod==0) ans=N;
else if(mod==1) ans=1;
else if(mod==2) ans=N+1;
else if(mod==3) ans=0;
If still someone needs it here simple python solution:
def XorSum(L):
res = 0
if (L-1)%4 == 0:
res = L-1
elif (L-1)%4 == 1:
res = 1
elif (L-1)%4 == 2:
res = (L-1)^1
else: #3
res= 0
return res