I'd like to get the number of used inodes for specified volume using function API rather then using the output of df shell command.
I've looked at the man page of getattrlist and found the following attribute, but it may also refer to hard links, but they point to existing inodes, and I don't want to count them more than once.
ATTR_VOL_FILECOUNT A u_int32_t containing the number of files on the volume.
I also tried to run dtruss df and search for the exact sys call which retrieves this value, but I couldn't put my finger on it :
csops(0x872, 0x7, 0x7FFEEE4C8E80) = 0 0
sysctl([CTL_KERN, 14, 1, 2162, 0, 0] (4), 0x7FFEEE4C8FC8, 0x7FFEEE4C8FC0, 0x0, 0x0) = 0 0
csops(0x872, 0x7, 0x7FFEEE4C8770) = 0 0
getfsstat64(0x0, 0x0, 0x2) = 6 0
getfsstat64(0x7FFD41001600, 0x3B48, 0x2) = 6 0
getfsstat64(0x7FFD41001600, 0x3B48, 0x1) = 6 0
getrlimit(0x1008, 0x7FFEEE4C9EC0, 0x0) = 0 0
fstat64(0x1, 0x7FFEEE4C9ED8, 0x0) = 0 0
ioctl(0x1, 0x4004667A, 0x7FFEEE4C9F24) = 0 0
Here's df output (notice the iused field)
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk1s1 976695384 757288824 211770792 79% 2000778 9223372036852775029 0% /
Any ideas where can I find the source code of df or to other API for this task.
thanks
I think I found the source and it does this:
if (iflag) {
inodes = sfsp->f_files;
used = inodes - sfsp->f_ffree;
(void)printf(" %*llu %*llu %4.0f%% ", mwp->iused, used,
mwp->ifree, sfsp->f_ffree, inodes == 0 ? 100.0 :
(double)used / (double)inodes * 100.0);
where sfsp is a pointer to a struct statfs instance, from statfs() like you'd expect.
Related
The expression for completeness relation in quantum mechanics is -
Σ |ψ_n><ψ_n| = 1
where the expression for density matrix in statistical mechanics is -
ρ = Σ p_n |ψ_n><ψ_n|
Both of the equation looks the same. So what are the differences between the density matrix and completeness relation?
What is the basic difference between them?
Formally the difference is that for the density matrix there are pre-factors p_n which sum up to 1 rather than all being 1 as in the completeness relation.
The meaning is also quite different.
Here is a rough illustration what they mean:
This object is a projection operator:
|ψ_n><ψ_n|
It projects on the n-th basis vector.
For simplicity lets take a simple example. Say our Hilbert space is 3 dimensional. Then the sum runs from 1 to 3. Each so-called pure state can be represented by a vector of length 1 in a 3 dimensional space like these examples:
|ψ_1> = (1, 0, 0)T
|ψ_2> = (0, 1, 0)T
|ψ_3> = (0, 0, 1)T
|φ> := (0, 1/2^0.5, 1/2^0.5)T
(The "T" stands for transposed)
These projection operators can be written as a matrix like for example:
/ 0 0 0 \
|ψ_2><ψ_2| = | 0 1 0 |
\ 0 0 0 /
Now what these projection operators do is projecting a vector on one of the coordinate axes. E.g. for n=2 we project to the y-axis.
|ψ_2><ψ_2|φ> = (0, 1/2^0.5, 0)
Now what the completeness relation says is that the sum of those 3 vectors you get when projection on each coordinate axis is once again the original vector (see Basis Decomposition).
As this is true for any vector, this means the operation is the identity matrix:
/ 1 0 0 \ + / 0 0 0 \ + / 0 0 0 \ / 1 0 0 \
|ψ_1><ψ_1| + |ψ_2><ψ_2| + |ψ_3><ψ_3| = | 0 0 0 | + | 0 1 0 | + | 0 0 0 | = | 0 1 0 | = 1
\ 0 0 0 / + \ 0 0 0 / + \ 0 0 1 / \ 0 0 1 /
Now the density matrix is a completely different matter. The weights p_n describe how one state is a mixture of several "pure" states. See e.g. https://en.wikipedia.org/wiki/Density_matrix
I wish to extract GPS Location data from the EXIF properties of image files. I am using the System.Drawing.Bitmap class to get raw the values. I am able to extract the values I am looking for but they are coming back as bytes, or possibly arrays of bytes and I need help converting the bytes into sensible numbers. Here is what I have so far:
$imagePath = 'C:\temp\picTest\WP_20150918_003.jpg'
$imageProperties = New-Object -TypeName System.Drawing.Bitmap -ArgumentList $imagePath
From the EXIF GPS Tag Reference I know that the property tags I am looking for are:
0x0001 - GPSLatitudeRef - Indicates whether the latitude is north or south latitude.
0x0002 - GPSLatitude - Indicates the latitude.
0x0003 - GPSLongitudeRef - Indicates whether the longitude is east or west longitude.
0x0004 - GPSLongitude - Indicates the longitude.
0x0005 - GPSAltitudeRef - Indicates the altitude used as the reference altitude.
0x0006 - GPSAltitude - Indicates the altitude based on the reference in GPSAltitudeRef.
First I get the GPSLatitudeRef:
$imageProperies.PropertyItems | ? ID -eq 0x0001
and I get:
Id Len Type Value
-- --- ---- -----
1 2 2 {78, 0}
According to the MSDN documentation for System.Drawing library, PropertyItem.Type of "2" is ASCII.
I load the value into a variable:
$GPSLatRef = $imageProperties.PropertyItems| Where ID -eq 0x0001
$GPSLatRef = $GPSLatRef.Value
$GPSLatRef
78
0
Get-Member on the variable returns type System.Byte. I know how to convert byte back into ASCII:
$GPSLatRef = [System.Text.Encoding]::ASCII.GetString($GPSLatRef.Value)
$GPSLatRef
returns:
N
But things get tricky for me with the GPSLatitude value (0x0002):
$imageProperies.PropertyItems | ? ID -eq 0x0002
returns:
Id Len Type Value
-- --- ---- -----
2 24 5 {37, 0, 0, 0...}
Load the value up into a variable:
$GPSLatitiude = $imageProperties.PropertyItems| Where ID -eq 0x0002
$GPSLatitiude.Value
The value returned is:
37
0
0
0
1
0
0
0
40
0
0
0
1
0
0
0
220
182
0
0
232
3
0
0
According to the MSDN documentation referenced above, PropertyItem.Type of "5"
"Specifies that Value data member is an array of pairs of unsigned long integers. Each pair represents a fraction; the first integer is the numerator and the second integer is the denominator.
Looking at the properties of the file itself in Windows Explorer I see the GPS Location values in decimal form.
"37;40;46.812000000005156"
From the value data above, and the description of the data type from the documentation, and comparing to the decimal values from Windows Explorer I can surmise that $GPSLatitude.Value actually shows me three different sets of two integers apiece. For example,
37
0
0
0
= 37
1
0
0
0
= 1
and 37/1 = 37, which matches the decimal value from Windows Explorer so I know I am on the right track.
How can I split the three sets of values from the (array of?) bytes found in the GPSLatitude property? Even though the data in the bytes is described as long integers, the decimal value displayed in the Windows Explorer shows that the outcome could be a number with fifteen digits to the right of the decimal point makes me think that the product of the division of the two long integers in the bytes from the property value might need to be stored in a [double] or perhaps [decimal]?
This snippet will give you Latitude and longitude details, I am using BitConverter for extracting the data from Byte array:
[double]$LatDegrees = (([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 0)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 4)));
[double]$LatMinutes = ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 8)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 12));
[double]$LatSeconds = ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 16)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(2).Value, 20));
[double]$LonDegrees = (([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 0)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 4)));
[double]$LonMinutes = ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 8)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 12));
[double]$LonSeconds = ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 16)) / ([System.BitConverter]::ToInt32( $imageProperties.GetPropertyItem(4).Value, 20));
"Latitude: $LatDegrees;$LatMinutes;$LatSeconds"
"Longitude: $LonDegrees;$LonMinutes;$LonSeconds"
I want to load gray scale images in C, pre process it and then display the modified image. My question is:
What is the right way to import gray scale images(jpeg,png formats)in C language ?
My own search before asking this question.
1- fread or with file management, we can read image but data will be encrypted(compressed), I want gray scale values(0-255) of each pixel.
2- There is one API ImageMagick which can be helpful but it is having installation problem with Mac OS X.
I have done image processing in python and matlab but have no idea about C language.
Thanks
You have a number of options, but I will go through them starting with the easiest and least integrated with OSX, and getting progressively more integrated with OSX.
Easiest Option
Personally, if I was intent on processing greyscale images, I would write my software to use NetPBM's Portable Greymap (PGM) format as that is the very simplest to read and write and readily interchangeable with other formats. There is no compression, DCT, quantisation, colorspaces, EXIF data - just your data with a simple header. The documentation is here.
Basically a PGM file looks like this:
P2
# Shows the word "FEEP" (example from Netpbm man page on PGM)
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
You can see the P2 says it is in ASCII (easy to read) and a greymap. Then the next line says it is 24 pixels wide by 7 tall and that the brightest pixel is 15. Very simple to read and write. You can change the P2 to P5 and write everything after the MAXVAL in binary to save space.
Now you can just use ImageMagick outside your program to convert JPEG, PNG, GIF, TIFF files to PGM like this - without needing any linking or libraries or compiler switches:
convert input.png output.pgm
convert input.jpg output.pgm
Likewise, when you have finished processing and created your resulting output file in PGM format you can convert it to JPEG or TIFF by simply reversing the parameters:
convert result.pgm result.jpg
Personally, I would install ImageMagick using homebrew. You go to the homebrew website and copy the one-liner and paste it into a terminal to install homebrew. Then you can install ImageMagick with:
brew install imagemagick
and, by the way, if you want to try out the other suggestion here, using OpenCV, then that is as easy as
brew search opencv
brew install homebrew/science/opencv
If you want a small, self-contained example of a little OpenCV project, have a look at my answer to another question here - you can also see how a project like that is possible from the command line with ImageMagick in my other answer to the same question.
Magick++
If you choose to install ImageMagick using homebrew you will get Magick++ which will allow you to write your algorithms in C and C++. It is pretty easy to use and can run on any platforms, including OSX and Windows and Linux so it is attractive from that point of view. It also has many, many image-processing functions built right in. There is a good tutorial here, and documentation here.
Your code will look something like this:
// Read an image from URL
Image url_image("http://www.serverName.com/image.gif");
// Read image from local filesystem
Image local_file_image("my_image.gif");
// Modify image
Pixels my_pixel_cache(my_image);
PixelPacket* pixels;
// define the view area that will be accessed via the image pixel cache
int start_x = 10, start_y = 20, size_x = 200, size_y = 100;
// return a pointer to the pixels of the defined pixel cache
pixels = my_pixel_cache.get(start_x, start_y, size_x, size_y);
// set the color of the first pixel from the pixel cache to black (x=10, y=20 on my_image)
*pixels = Color("black");
// set to green the pixel 200 from the pixel cache:
// this pixel is located at x=0, y=1 in the pixel cache (x=10, y=21 on my_image)
*(pixels+200) = Color("green");
// now that the operations on my_pixel_cache have been finalized
// ensure that the pixel cache is transferred back to my_image
my_pixel_cache.sync();
// Save results as BMP file
image.write(“result.bmp”);
Apple OSX Option
The other ENTIRELY SEPARATE option would be to use the tools that Apple provides for manipulating images - they are fast and easy to use, but are not going to work on Linux or Windows. So, for example, if you want to
a) load a PNG file (or a TIFF or JPEG, just change the extension)
b) save it as a JPEG file
c) process the individual pixels
// Load a PNG file
NSImage * strImage = [[NSImage alloc]initWithContentsOfFile:#"/Users/mark/Desktop/input.png"];
// Save NSImage as JPG
NSData *imageData = [strImage TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
imageData = [imageRep representationUsingType:NSJPEGFileType properties:imageProps];
[imageData writeToFile:#"/Users/Mark/Desktop/result.jpg" atomically:YES];
// Access individual pixels
int w=imageRep.pixelsWide;
int h=imageRep.pixelsHigh;
int bps=imageRep.bitsPerSample;
printf("Dimensions: %dx%d\n",w,h);
printf("bps: %d\n",bps);
// Get a pointer to the uncompressed, unencoded pixel data
unsigned char *pixelData = [imageRep bitmapData];
for(int j=0;j<10;j++){
printf("Pixel %d: %d\n",j,pixelData[j]);
}
Of course, you could take the code above and easily make a little utility that converts any file format to PGM and then you could go with my first suggestion of using PGM format and wouldn't need to install ImageMagick - although it is actually dead simple with homebrew.
Bear in mind that you can mix Objective-C (as in the last example) with C++ and C in a single project using clang (Apple's compiler), so you can go ahead in C as you indicate in your question with any of the examples I have given above.
If you are new to developing on OSX, you need to go to the AppStore and download, for free, Apple's Xcode to get the compiler and libraries. Then you must do
xcode-select --install
to install the command-line tools if you wish to do traditional development using Makefiles and command-line compilation/linking.
This answer is an attempt to demonstrate how to develop with ImageMagick's MagickWand API with Xcode, and is based on the comments from the OP.
After installing ImageMagick, start a new Xcode command-line C project. Before writing any code, you need to tell llvm about the ImageMagick resources/libraries/etc.
There are many, many, ways to achieve this, but here's the quickest I can think of.
Navigate to top-level project's "Build Settings"
Under "All" (not "Basic") search for "Other Linker Flags"
Outside of Xcode, open up Terminal.app and enter the following
MagickWand-config --ldflags
Enter the output from Terminal.app as the value for "Other Linker Flags"
Back in the settings search; enter "Other C Flags"
Back in Terminal.app run the following
MagickWand-config --cflags
Enter the resulting output as the value for "Other C Flags"
Over in file main.c, you should notice Xcode picking-up MagickWand commands right away.
Try the following (needs X11 installed) ...
#include <stdio.h>
#include <wand/MagickWand.h>
int main(int argc, const char * argv[]) {
MagickWandGenesis();
MagickWand * wand;
wand = NewMagickWand();
MagickReadImage(wand, "wizard:");
MagickQuantizeImage(wand, 255, GRAYColorspace, 0, MagickFalse, MagickTrue);
MagickDisplayImage(wand, ":0");
wand = DestroyMagickWand(wand);
MagickWandTerminus();
return 0;
}
... and build + run to verify.
edit
To get the gray scale (0-255) value for each pixel, you can invoke a pixel iterator (see second example here), or export the values. Here is an example of dynamically populating a list of gray values by exporting...
// Get image size from wand instance
size_t width = MagickGetImageWidth(wand);
size_t height = MagickGetImageHeight(wand);
size_t total_gray_pixels = width * height;
// Allocate memory to hold values (total pixels * size of data type)
unsigned char * blob = malloc(total_gray_pixels);
MagickExportImagePixels(wand, // Image instance
0, // Start X
0, // Start Y
width, // End X
height, // End Y
"I", // Value where "I" = intensity = gray value
CharPixel, // Storage type where "unsigned char == (0 ~ 255)
blob); // Destination pointer
// Dump to stdout
for (int i = 0; i < total_gray_pixels; i++ ) {
printf("Gray value # %lux%lu = %d\n", i % width, i / height, (int)blob[i]);
}
/** Example output...
* Gray value # 0x0 = 226
* Gray value # 1x0 = 189
* Gray value # 2x0 = 153
* Gray value # 3x0 = 116
* Gray value # 4x0 = 80
* ... etc
*/
You can install ImageMagick on OS/X with this command:
sudo port install ImageMagick
You can get the macports package from https://www.macports.org
Don't have much experience with Mac's but I have quite a lot with OpenCV. Now granted a lot of OpenCV is in C++ (which may or may not be a problem) however it definitely supports everything you want to do and more. It's very easy to work with has lot's of helpful wiki's and a very good community.
Link to installing on Mac: http://blogs.wcode.org/2014/10/howto-install-build-and-use-opencv-macosx-10-10/
Link to some OpenCV wikis: http://opencv.org/documentation.html
EDIT:
I should also mention that older versions of OpenCV are in C and a lot of the functions are still supported if you chose to go the C route.
I'm trying to determine address values and sizes using ARM .elf output in GDB.
With the usual p& and print functions I can determine most of the addresses and and variable sizes, but I can't figure out if the variable is a bitValue or not.
To give an example:
typedef struct
{
bool_t start;
bool_t running :1;
bool_t objectpoolUsable :1;
bool_t ready :1;
bool_t test :1;
bool_t stop :1;
uint8_t defaultMachine;
}bitFieldTest;
bitFieldTest bitValues;
When asking GDB for the address of "bitValues.ready" or "bitValues.running" it will return the same address (since it uses the same address), but doesn't give me the bit position. Neither do I know if it really is a bitvalue or just a boolean taking the space of a uint8_t.
To clarify what I need to do: Give GDB only a single name, what might be a bitValue, and return me the right address and type. If this type is a bitValue, I need to find the bit position. For non-bitValues this works fine, bitValues are causing trouble for now.
Is GDB able to give some kind of output to solve this problem?
There's no way to get this information directly using the gdb expression API. There's no really deep reason for this -- certainly gdb knows the bit position -- but it is a consequence of the fact that gdb expressions mimic the language being debugged, plus just that nobody ever bothered to expose it. Since I've never heard of anyone wanting this before, I think it's safe to say that it is a rare request.
The information is available via gdb's Python API. In particular, if you iterate over the fields of a type, the Field object will have a bitpos member that has the bit offset of the data. Note that the offset is from the start of the enclosing struct.
It would be a relatively simple matter to write a new command in Python that prints this information.
I've solved this problem myself already.
Since I don't know how, and there doesn't seem to be a direct way to return the bit position it can be calculated by asking multiple addresses of GDB.
Using the p& command can determine the address of the variable, but not of its a bitField or the bit-position of it.
By using the print command of GDB on a struct, the location of the bitValue I need, it will return all the available values in this struct, example:
I am looking for the bitField: MachineToUi.tramlining.sensorBoutAdvance
MachineToUi will return the following:
$1 = {speedPls = {present = 0 '\000', time = 0, count = 0, noPulseCount = 0,
value = 0, calDist = 0, calPulses = 0,END DATA ALL DATA: sampleTime = 0}, output = {
trackMarkerL = 0 '\000', trackMarkerR = 0 '\000',
workingLights = 0 '\000', foldingFrame = 0 '\000',
tramlineShutoffL1 = 0 '\000', tramlineShutoffR1 = 0 '\000'}, input = {
fanPpm = 0, workswitch1 = 0 '\000', workswitch2 = 0 '\000',
speedSensor = 0 '\000', fanSensor = 0 '\000', meteringEncL = 0 '\000',
motorEncL = 0 '\000', trackMarkerL = 0 '\000', trackMarkerR = 0 '\000',
lowLvlHopperL = 0 '\000', venturiFlapL = 0 '\000',
calButtonL = 0 '\000'}, hssoOutput = HSSO_IDLE, tramlining = {
active = 0 '\000', restoreCfg = 0 '\000', updateCfg = 0 '\000',
boutAdvance = 0 '\000', boutDecrement = 0 '\000',
noTramlineIncDec = 0 '\000', displaySfks = 0 '\000',
sensorBoutAdvance = 0 '\000', bout = 0 '\000'}, tramlineLeft = 0 '\000',
tramlineRight = 0 '\000', diagOutputs = '\000' <repeats 11 times>,
markerAutoDown = 0 '\000', fanRpm = 0, fanOffTime = 0, speed = 0,
fsAlarmSensorNr = 0 '\000', fsAlarmDisconnectedSensorNr = 0 '\000',
fsAlarmType = 0 '\000', seeding = 0 '\000', actMinSpeed = 0,
actMaxSpeed = 0, lastSensorBout = 0 '\000', ctrMLeftUpFlash = 0 '\000',
ctrMRightUpFlash = 0 '\000', folding = 0 '\000', startLeftOff = 0 '\000',
startRightOff = 0 '\000', halfSideShutOff = 0 '\000',
oldMarkerPosL = 0 '\000', oldMarkerPosR = 0 '\000',
timeDateActive = 0 '\000', licVtCheck = 0 '\000', trialVtCheck = 0 '\000',
trialAlarmActive = 0 '\000', workBeep = 0 '\000', warningBeep = 0 '\000',
errorBeep = 0 '\000', runLed = 0 '\000', tcLicenseOk = 0 '\000',
WDI_start = 0 '\000', newViewSeedCalRecRead = 0 '\000',
MotorStopMarkerDelay = 0}
I'm interested in variable: sensorBoutAdvance.
By listing all the variables around sensorBoutAdvance within a range of at least 8 before the value you want to read and 1 behind the value you want to read, and make GDB return their addresses:
* calButtonL 0x2000435A
* hssoOutput 0x2000435B
* tramlining 0x2000435C
* restoreCfg 0x2000435D
* updateCfg 0x2000435E
* boutAdvance 0x2000435F (Same address! Stop search!)
* boutDecrement
* noTramlineIncDec
* displaySfks
* sensorBoutAdvance (Known address by &p = 0x2000435F)
* bout
* tramlineLeft
* tramlineRight
* diagOutputs
* markerAutoDown
* fanRpm
* fanOffTime
* speed
* fsAlarmSensorNr
* fsAlarmDisconnectedSensorNr
As soon as the same address is found, a bitField is detected. And in this case sensorBoutAdvance can be found on bit 5. If no double address is found, it might not be a bitField, but at least the bit-position won't matter. If the same Address is found right after your the variable you want to read (and not before), your bit position is on the first bit.
It sure requires some parsing, but works for me without having to add external programs or different languages.
Note: This method will only work when all bit-field are only 1-bit long.
import gdb
class Offsets(gdb.Command):
outfile = None
def __init__(self):
super (Offsets, self).__init__ ('offsets-of', gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
argv = gdb.string_to_argv(arg)
if len(argv) != 2:
raise gdb.GdbError('offsets-of takes exactly 2 arguments.')
self.outfile = open (argv[1], "w")
self.traverse(gdb.lookup_type(argv[0] + '_t').fields(), argv[0], 0)
self.outfile.close()
def traverse(self, branch, fqn, address):
for field in branch:
if field.type.code == gdb.TYPE_CODE_STRUCT:
self.traverse(field.type.fields(), fqn + '.' + field.name, address + field.bitpos//8)
else:
self.outfile.write (('fqn=' + fqn + '.%s offset=%d, size=%d\n' % (field.name, address + field.bitpos//8, field.type.sizeof)))
Offsets()
Is there a way to pick a value based on the bit position. The problem statement is:-
for a 16 bits position, I can set any bits, say I set 1,4,6,7,11,13 bit
so the mask would be:-
Bit Positons 0 0 1 0 1 0 0 0 1 1 0 1 0 0 1 0
Now I need to randomly pick a value based on this bit mask, where only 1 bit is set, so my possible values could be:-
For selecting 4 :0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
For Selecting 7: 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
But I need to select this value randomly, so I though of doing it like this
1)Create an Array based on the bit mask, so for 16 bit , the array would have 16 unique values.
2) Now do the rand operation on the array position to get the array index.
3) Use the value at that array index.
Is there a better way of doing it?
If I understand correctly you want a number with exactly one bit set that is also set in the mask.
To do this I'd make a while loop that selects a random value between 0 and 16 until it has found one that is also set in the mask:
uint16_t mask = 0x28d2; /* == 0 0 1 0 1 0 0 0 1 1 0 1 0 0 1 0 */
int bit = 0;
do{
bit = 1 << (rand() % 16); /* sets one random bit between 1 and 16 */
}while(!(mask & bit));
/* bit has now exactly one bit set that is also set in mask */
If the goal is to have a value with at most one bit set at the end, you don't need the array. You can simply randomly generate a value between 0-15, then bitshift 1 left by that value to get the mask that you will use to select the bit, like this:
uint16_t myValue = 0xA5;
int shiftValue = rand() % 16;
uint16_t randomMask = 1u << shiftValue;
uint16_t randomValue = myValue & randomMask;
If you instead need a value with exactly one of the bits set at the end, it gets a little trickier. At that point, you could do more or less what you said and use an array to store the positions of the bits that are set (e.g. [1, 4, 6, 7, 11, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], using zeroes to indicate when there are no more bits set), then generate a random index into the portion of the array containing valid indices. There are certainly other ways to do it too, but this way seems like one that will be fairly clear to future readers of the code (though I would still comment this somewhat carefully, since bit operations can get confusing fast).
(BTW, there are much better ways of generating random numbers than rand(), and you should probably use one of those if you need anything approaching real randomness - I just used it here as a convenient shorthand, since the actual RNG doesn't matter.)
You can do that in this way:
bitMask = 0x28d2;
randomNum = rand() % 16;
randomBit = (1<<randomNum) & bitMask;
If you want exactly one bit set, you could use a re-try loop, or something like this: (add the appropriate definitions and maybe add a special case for mask == 0)
while (mask)
{
array[i++] = mask & -mask;
mask &= mask - 1;
}
return array[rand_in_range(0, i)];
Where rand_in_range(a, b) is a function that returns a random number in the range [a, b> (be careful with that, 99% of the implementations of rand_in_range are incorrect while seeming correct in most tests, the worst kind of bug).