NSDecimal equal to NSDecimalNumber value? - ios

I am looking for an effective way to save NSDecimalNumber with other data in NSData buffer.
I have not found a method to do it directly from NSDecimalNumber.
However, it is easy to convert it with :
NSDecimal value = [theDecimalNumber decimalValue];
And it is not difficult to transfer NSDecimal in memory (20 bytes).
But, my question: The NSDecimalNumber and NSDecimal values are they exactly the same?
Because their declarations have some differences (ExternalRefCount ?):
#interface NSDecimalNumber : NSNumber {
#private
signed int _exponent:8;
unsigned int _length:4;
unsigned int _isNegative:1;
unsigned int _isCompact:1;
unsigned int _reserved:1;
unsigned int _hasExternalRefCount:1;
unsigned int _refs:16;
unsigned short _mantissa[0]; /* GCC */
}
typedef struct {
signed int _exponent:8;
unsigned int _length:4; // length == 0 && isNegative -> NaN
unsigned int _isNegative:1;
unsigned int _isCompact:1;
unsigned int _reserved:18;
unsigned short _mantissa[NSDecimalMaxSize];
} NSDecimal;
Is it possible to perform many transfers between the two type, without any loss of precision ?

Did you try to use NSArchiver class methods?
NSData *data=[NSArchiver archivedDataWithRootObject:yourNumber];

I made numerous calculations with the transfer from one to the other without any problems.
So I think we can say that they are suitable as identical.
I extend NSDecimalNumber with :
#define DecNum_SizeOf 20
+ (NSDecimalNumber *) fromPtr:(void *)ptr
{
NSDecimal valueRead;
memcpy (&valueRead, ptr, DecNum_SizeOf);
return [NSDecimalNumber decimalNumberWithDecimal:valueRead];
}
- (void) toPtr:(void *)ptr
{
NSDecimal valueWrite = [self decimalValue];
memcpy (ptr, &valueWrite, DecNum_SizeOf);
}
While awaiting a method more "standard" to perform the job as well

Related

iOS a Very Amazing(malloc_error_break)

first this my code
#pragma pack (4)
typedef struct _Login{
char user[32];
char pwd[32];
int userID;
}Login,*PLogin;
const unsigned long MSG_TAG_HEADER_YXHY = 0x59485859;
#pragma pack (2)
typedef struct tagTcpPacketHeader
{
int ulHtag;
char ucVersion;
char ucCmd;
int ulUserId;
short usPacketNum;
int ulDataLen;
}TcpPacketHeader,*LPTcpPacketHeader;
#pragma pack ()
const unsigned int TCP_HEADER_PACKET_LEN = sizeof(TcpPacketHeader);
- (NSData*)sendDataFileWithUserId:(const int)nUserId nCmd:(const int)nCmd pData:(NSData*)data{
NSData* sendData;
void* sendObj = malloc(data.length);
[data getBytes:sendObj length:data.length];
static int nPacketNum = 0;
int nLen = (int)data.length + TCP_HEADER_PACKET_LEN;
char *pTmpBuf = malloc(nLen);
LPTcpPacketHeader tcpHeader = (LPTcpPacketHeader)pTmpBuf;
tcpHeader->ulHtag = MSG_TAG_HEADER_YXHY;
tcpHeader->ucVersion = 1;
tcpHeader->ucCmd = nCmd;
tcpHeader->ulUserId = nUserId;
tcpHeader->usPacketNum = nPacketNum;
tcpHeader->ulDataLen = nLen;
memcpy(tcpHeader + TCP_HEADER_PACKET_LEN,sendObj, data.length);
sendData = [NSData dataWithBytes:pTmpBuf length:nLen];
nPacketNum++;
free(pTmpBuf);
free(sendObj);
return sendData;
}
- (NSData*)get_File_Login:(NSString*)userID{
int length = sizeof(Login);
Login log_in = {"123","456",userID.intValue};
NSData* login_data = [NSData dataWithBytes:&log_in length:length];
NSData* ret = [self sendDataFileWithUserId:log_in.userID nCmd:5 pData:login_data];
return ret;
}
Use
NSData* ms = [self get_File_Login:#"123"];
NSLog(#"%#",ms);
After frequent use can be a problem
question
This question makes me very headache why appear “ set a breakpoint in malloc_error_break to debug ”
I have added the "malloc_error_break" the breakpoint,But it doesn't work......
Who can tell me the answer???
When you use the pointer in memcpy this way
memcpy(tcpHeader + TCP_HEADER_PACKET_LEN,sendObj, data.length);
this means that you want to copy into memory location pointed by tcpHeader plus TCP_HEADER_PACKET_LEN times the size of the data the pointer points to. It is the same as doing &tcpHeader[TCP_HEADER_PACKET_LEN].
Assuming you want to write to a location right after the header there are two ways to fix it:
1) use a pointer with a size of 1, meaning a char*. In your code you have a pointer pTmpBuf that is such so just change the code to:
memcpy(pTmpBuf + TCP_HEADER_PACKET_LEN, sendObj, data.length);
2) use the size 1 for this calculation. Since the size of the data it points to is the same as TCP_HEADER_PACKET_LEN then multiplying it by one gives the correct location:
memcpy(tcpHeader + 1, sendObj, data.length);
I would recommend the first since it's clear what you are calculating. In the second it is unclear why you would add one, as well as using a pointer to one type when copying data that isn't that type.

Parse BLE Manufacturer data - Objective-C

I'm working on a custom bluetooth product, the manufacturer has embeded data in the advertisement packet. How do I effectively parse this data so it's usable within an iOS app?
I'm currently grabbing the data from the NSDictionary as follows:
NSData *rawData = [advertisement objectForKey:#"kCBAdvDataManufacturerData"];
The data in the packet is structured like so:
uint8_t compId[2];
uint8_t empty[6];
uint8_t temperature[2];
uint8_t rampRate[2];
uint8_t dutyFactor[2];
uint8_t alarms[2];
uint8_t statusFlag;
uint8_t speedRpm[2];
uint8_t vib[2];
uint8_t deviceTypeId;
uint8_t radioStatus;
uint8_t cycleTimer[2];
uint8_t batteryLevel;
My first thought was to convert it to a string and parse out the data that I need, but this seems slow and really inefficient. There has to be a standard way developers deal with this. I'm still pretty green when it comes to bitwise operators. All the data is formatted in little endian.
Certainly don't convert it to a string, as it isn't one, and you'll have issues with encoding.
Start by checking that the length of the data matches what you're expecting (26 bytes)
Use the bytes method to get a pointer to the data
Add a function or method to combine two bytes into a 16-bit integer. You'll have to find out if those 2-byte fields are signed or unsigned.
Something along these lines:
- (int)getWordFromBuffer:(const unsigned char *)bytes atOffset:(int) offset
{
return (int)bytes[offset] | (bytes[offset+1] << 8);
}
- (NSDictionary *)decodeData:(NSData *)data
{
if (data.length != 26)
{
NSLog(#"wrong length %d instead of 26", data.length);
return nil;
}
const unsigned char *bytes = (unsigned char *)data.bytes;
return
#{
#"compId": #([self getWordFromBuffer:bytes atOffset:0]),
#"temperature": #([self getWordFromBuffer:bytes atOffset:8]),
#"rampRate": #([self getWordFromBuffer:bytes atOffset:10]),
....
};
}

Any good idea for OpenCL atom_inc separation?

I want to count the total non-zero points number in an image using OpenCL.
Since it is an adding work, I used the atom_inc.
And the kernel code is shown here.
__kernel void points_count(__global unsigned char* image_data, __global int* total_number, __global int image_width)
{
size_t gidx = get_global_id(0);
size_t gidy = get_global_id(1);
if(0!=*(image_data+gidy*image_width+gidx))
{
atom_inc(total_number);
}
}
My question is, by using atom_inc it will be much redundant right?
Whenever we meet a non-zero point, we should wait for the atom_inc.
I have a idea like this, we can separate the whole row into hundreds groups, we find the number in different groups and add them at last.
If we can do something like this:
__kernel void points_count(__global unsigned char* image_data, __global int* total_number_array, __global int image_width)
{
size_t gidx = get_global_id(0);
size_t gidy = get_global_id(1);
if(0!=*(image_data+gidy*image_width+gidx))
{
int stepy=gidy%10;
atom_inc(total_number_array+stepy);
}
}
We will separate the whole problem into more groups.
In that case, we can add the numbers in the total_number_array one by one.
Theoretically speaking, it will have a great performance improvement right?
So, does anyone have some advice about the summing issue here?
Thanks!
Like mentioned in the comments this is a reduction problem.
The idea is to keep separate counts and then put them back together at the end.
Consider using local memory to store the values.
Declare a local buffer to be used by each work group.
Keep track of the number of occurrences in this buffer by using the local_id as the index.
Sum these values at the end of execution.
A very good introduction to the reduction problem using Opencl is shown here:
http://developer.amd.com/resources/documentation-articles/articles-whitepapers/opencl-optimization-case-study-simple-reductions/
The reduction kernel could look like this (taken from the link above):
__kernel
void reduce(
__global float* buffer,
__local float* scratch,
__const int length,
__global float* result) {
int global_index = get_global_id(0);
int local_index = get_local_id(0);
// Load data into local memory
if (global_index < length) {
scratch[local_index] = buffer[global_index];
} else {
// Infinity is the identity element for the min operation
scratch[local_index] = INFINITY;
}
barrier(CLK_LOCAL_MEM_FENCE);
for(int offset = get_local_size(0) / 2;
offset > 0;
offset >>= 1) {
if (local_index < offset) {
float other = scratch[local_index + offset];
float mine = scratch[local_index];
scratch[local_index] = (mine < other) ? mine : other;
}
barrier(CLK_LOCAL_MEM_FENCE);
}
if (local_index == 0) {
result[get_group_id(0)] = scratch[0];
}
}
For further explanation see the proposed link.

Suspicious pointer conversion

I got a suspicious pointer conversion error here. What might be the reason of this error?
I also initialized the code[] array globally as int *code[128]={0};
void encode(const char *s, int *out)
{
while(*s)
{
out=code[*s];
out+=strlen(code[*s++]); //this is where i got the error.
}
}
When you will assign a particular type pointer variable with address of different type, such type of automatic type conversion is known as suspicious type conversion.
strlen requires const char *, while int *code[128] means code is an array of int *, so code[*s++] is a int *.
When int * is supplied to const char *, you get this error.
Generally supply int * pointer to strlen isn't a good idea because strlen will end when a byte is '\0'. You have a good chance to have 0 in a 4 bytes int. E.g., an integer 3 will have 3 bytes of 0, and 1 byte of 3.

How to convert long long to 8 byte array in objective C

In my application i have to convert long long number into 8 byte array. Then i have to convert 8 byte array into hexadecimel string. Can you please help me in this. i'm struck up.
One way to do integer/byte array conversion is to use a union:
union {
long long l;
uint8_t b[sizeof(long long)];
} u;
u.l = mylonglong;
Then u.b[] contains the bytes, which can be accessed individually.
EDIT: Please note as pointed out by #NikolaiRuhe this use of union can lead to undefined behaviour, so it might be best to use memcpy() instead:
uint8_t b[sizeof(long long)];
memcpy(b, &mylonglong, sizeof(b));
If you want the hex string of the long long in native-endian order, then:
void hexChar(uint8_t b, char *out)
{
static const char *chars = "0123456789abcdef";
out[0] = chars[(b >> 4) & 0xf];
out[1] = chars[b & 0xf];
}
// Make sure outbuf is big enough
void hexChars(const uint8_t *buffer, size_t len, char *outbuf)
{
for (size_t i = 0; i < len; i++)
{
hexChar(buffer[i], outbuf);
outbuf += 2;
}
*outbuf = '\0';
}
and call it with:
char hex[32];
hexChars(u.b, sizeof(u.b), hex);
However if instead you want the hex value of the long long:
char hex[32];
sprintf(hex, "%llx", mylonglong);
would that do the trick ?
#include <stdio.h>
int main() {
long long int val = 0x424242;
char str_val[32];
snprintf(str_val, sizeof(str_val), "%#llx", val);
printf("Value : %s\n", str_val);
}

Resources