This question already has answers here:
C++ SSE Intrinsics: Storing results in variables [closed]
(1 answer)
print a __m128i variable
(4 answers)
SSE: Difference between _mm_load/store vs. using direct pointer access
(3 answers)
How to extract bytes from an SSE2 __m128i structure?
(1 answer)
Is `reinterpret_cast`ing between hardware SIMD vector pointer and the corresponding type an undefined behavior?
(2 answers)
Closed 1 year ago.
I can use _mm_set_epi64 to store two uint64_ts into a __m128 intrinsic. But hunting around, I see various ways to get the values back out: There's reinterpret_cast (and it's evil twin C-style casts), it's sibling union { __m128; uint64[2]; }; and memcpy, there's accessing fields of __m128. There's __m128i _mm_load_si128(__m128i *p);, but I'm not seeing a _mm_get_* function. Am I missing something? If there's a _mm_set_epi64 then there must be a non-cast way to get the uint64_ts back out, right? (Otherwise why would they bother providing _mm_set_epi64?)
I see Get member of __m128 by index? but the "correct answer" has a broken link and implies there's a load function, but all the loads I see map __m128 to __m128. Shouldn't there be a void _mm_get_epi64(__m128, uint64_t* outbuf)?
The following is base on my guess. Someone please point out the parts that I understand incorrectly.
If I have a class, of which an instance occupies 128 bits, called Class128Bits. And my program runs on a 64 bits computer.
First, I call let pointer = UnsafeMutablePointer<Calss128Bits>.allocate(capacity: 2)
the memory layout should look like this:
000-063 064 bits chaos
064-127 064 bits chaos
128-255 128 bits chaos
256-383 128 bits chaos
If I call pointer.pointee = aClass128Bits, it crashes because the pointers in the first two grids have not been initialized yet. Accessing to what they point to leads to unpredictable results.
But if I call pointer.initialize(to: aClass128Bits, count: 2), the pointers could be initialized like this:
000-063 address to offset 128
064-127 address to offset 256
128-255 a copy of aClass128Bits
256-383 a copy of aClass128Bits
Then any accesses will be safe.
However this cannot explain why UnsafeMutablePointer<Int> does not crash.
Original
The case I am facing:
The pointer to Int works fine, but the one to String crashes.
I know that I need to initialize it like this:
But I can't see the reason why I need to pass "42" twice.
In C, I might do something similar like this:
char *pointer = (char *)malloc(3 * sizeof(char));
memcpy(pointer, "42", 3);
free(pointer)
If allocate equals malloc, free equals deallocate, memcpy equals pointee{ set },
then what do initialize and deinitialize actually do?
And why does my code crash?
let pointer0 = UnsafeMutablePointer<String>.allocate(capacity: 1)
let pointer1 = UnsafeMutablePointer<Int>.allocate(capacity: 1)
let check the size of both
MemoryLayout.size(ofValue: pointer0) // 8
MemoryLayout.size(ofValue: pointer1) // 8
let check the value of .pointee
pointer0.pointee // CRASH!!!
while
pointer1.pointee // some random value
Why? The answer is as simple, as it can be. We allocated 8 bytes, independently from "associated" Type. Now is clear, that 8 bytes in memory are not enough to store any String. the underlying memory must be referenced indirectly. But there are some 8 random bytes there ... Loading what is in the memory with address represented by 8 random bytes as a String will most likely crash :-)
Why didn't it crash in the second case? Int value is 8 bytes long and the address can be represented as Int value.
let's try in the Playground
import Foundation
let pointer = UnsafeMutablePointer<CFString>.allocate(capacity: 1)
let us = Unmanaged<CFString>.passRetained("hello" as CFString)
pointer.initialize(to: us.takeRetainedValue())
print(pointer.pointee)
us.release()
// if this playground crash, try to run it again and again ... -)
print(pointer.pointee)
look what it prints to me :-)
hello
(
"<__NSCFOutputStream: 0x7fb0bdebd120>"
)
There is no miracle behind. pointer.pointee is trying to represent what is in the memory, which address is stored in our pointer, as a value of its associated type. It never crashes for Int because every 8 continues bytes somewhere in the memory can be represented as Int.
Swift use ARC, but creating the Unsafe[Mutable]Poiner doesn't allocate any memory for the instance of T, destroying it doesn't deallocate any memory for it.
Typed memory must be initialized before use and deinitialized after use. This is done using initialize and deinitialize methods respectively. Deinitialization is only required for non-trivial types. That said, including deinitialization is a good way to future-proof your code in case you change to something non-trivial
Why doesn't assignment to .pointee with Int value crash?
Initialize store the address of value
Assignment to pointee update the value at stored address
Without initializing It most likely will crash, only the probability is less by modifying only 8 bytes in memory at some random address.
trying this
import Darwin
var k = Int16.max.toIntMax()
typealias MyTupple = (Int32,Int32,Int8, Int16, Int16)
var arr: [MyTupple] = []
repeat {
let p = UnsafeMutablePointer<MyTupple>.allocate(capacity: 1)
if k == 1 {
print(MemoryLayout.size(ofValue: p), MemoryLayout.alignment(ofValue: p),MemoryLayout.stride(ofValue: p))
}
arr.append(p.pointee)
k -= 1
defer {
p.deallocate(capacity: 1)
}
} while k > 0
let s = arr.reduce([:]) { (r, v) -> [String:Int] in
var r = r
let c = r["\(v.0),\(v.1),\(v.2),\(v.3)"] ?? 0
r["\(v.0),\(v.1),\(v.2),\(v.3)"] = c + 1
return r
}
print(s)
I received
8 8 8
["0,0,-95,4104": 6472, "0,0,0,0": 26295]
Program ended with exit code: 0
It doesn't look very random, is it? That explains, why the crash with the typed pointer to Int is very unlikely.
One reason you need initialize(), and the only one as for now maybe, is
for ARC.
You'd better think with local scope variables, when seeing how ARC works:
func test() {
var refVar: RefType = initValue //<-(1)
//...
refVar = newValue //<-(2)
//...
//<-(3) just before exiting the loacl scope
}
For a usual assignment as (2), Swift generates some code like this:
swift_retain(_newValue)
swift_release(_refVar)
_refVar = _newValue
(Assume _refVar and _newValue are unmanaged pseudo vars.)
Retain means incrementing the reference count by 1, and release means decrementing the reference count by 1.
But, think what happens when the initial value assignment as at (1).
If the usual assignment code was generated, the code might crash at this line:
swift_release(_refVar)
because newly allocated region for a var may be filled with garbages, so swift_release(_refVar) cannot be safely executed.
Filling the newly region with zero (null) and release safely ignoring the null could be one solution, but it's sort of redundant and not effective.
So, Swift generates this sort of code for initial value assignment:
(for already retained values, if you know ownership model, owned by you.)
_refVar = _initValue
(for unretained values, meaning you have no ownership yet.)
swift_retain(_initValue)
_refVar = _initValue
This is initialize.
No-releasing the garbage data, and assign an initial value, retaining it if needed.
(The above explanation of "usual assignment" is a little bit simplified, Swift omits swift_retain(_newValue) when not needed.)
When exiting the local scope at (3), Swift just generates this sort of code:
swift_release(_refVar)
So, this is deinitialize.
Of course, you know retaining and releasing are not needed for primitive types like Int, so initialize and deinitialize may be donothing for such types.
And when you define a value type which includes some reference type properties, Swift generates initialize and deinitialize procedures specialized for the type.
The local scope example works for the regions allocated on the stack, and initialize() and deinitialize() of UnsafeMutablePointer works for the regions allocated in the heap.
And Swift is evolving so swift, that you might find another reason for needing initialize() and deinitialize() in the future, you'd better make it a habit to initialize() and deinitialize() all allocated UnsafeMutablePointers of any Pointee types.
From the documentation it is possible to conclude that .initialize() is a method that :
Initializes memory starting at self with the elements of source.
And .deinitialize() is a method that :
De-initializes the count Pointees starting at self, returning their
memory to an uninitialized state.
We should understand that when we are using UnsafeMutablePointer we should manage memory on our own. And methods that are described above help us to do this.
So in your case lets analyze example that you provide:
let pointer = UnsafeMutablePointer<String>.allocate(capacity: 1)
// allocate a memory space
pointer.initialize(to: "42")
// initialise memory
pointer.pointee // "42"
// reveals what is in the pointee location
pointer.pointee = "43"
// change the contents of the memory
pointer.deinitialize()
// return pointer to an unintialized state
pointer.deallocate(1)
// deallocate memory
So your code crashes because you do not initialize memory and try to set value.
Previously in objective-c when we are working with objects we always use [[MyClass alloc] init]].
In this case :
alloc:
allocates a part of memory to hold the object, and returns the
pointer.
init:
sets up the initial parameters of the object and returns it.
So basically .initialize() sets the value to the allocated memory part. When you create an object only with alloc you only set reference to empty memory part in the heap. When you call .initialize() you set value to this memory allocation in the heap.
Nice article about the pointers.
This question already has answers here:
Creating a vector of zeros for a specific size
(4 answers)
Closed 7 years ago.
What is the most efficient way to get access to &mut [u8]? Right now I'm borrowing from a Vec but it would be easier to just allocate the buffer more directly.
The best I can do right now is to preallocate a vector then push out its length but there is no way this is idiomatic.
let mut points_buf : Vec<u8> = Vec::with_capacity(points.len() * point::POINT_SIZE);
for _ in (0..points_buf.capacity()) {
points_buf.push(0);
}
file.read(&mut points_buf[..]).unwrap();
You could just create the vec with a given size directly:
vec![0; num_points]
Or use iterators:
repeat(0).take(num_points).collect::<Vec<_>>()
This question already has an answer here:
Integers not properly returned from a property list (plist) array in Objective-C
(1 answer)
Closed 8 years ago.
I am trying to take a small integer (eg 4) from a pList and put it into a managed object for later manipulation. However, by the time I come to take it out of the managed object and put it into an NSInteger it has changed completely. 4 has become 237371328 !
The number is stored as "Number" in the pList and integer 16 in the managed object.
I have two fields: timesAsNumber which is integer 16 and timesUsed which is string (my current work around!).
The lines of code involved are:
NSArray *usageFetchResults = [self.objectContext executeFetchRequest:request error:&error];
NSLog(#"Here is the usageArray: %#, with error: %#",usageFetchResults, error);
This gives the log result:
data: {\n feature = video;\n timesAsNumber = 4;\n timesUsed = 4;\n})"
), with error: (null)
So the logger knows the value of timesAsNumber is 4.
NSLog(#"timesAsNumber straight from the Managed Object: %#", [currentUseData valueForKey:#"timesAsNumber"]);
Produces result: timesAsNumber straight from the Managed Object: 4 so still no problem.
However,
NSInteger timesUsedAsInt = [currentUseData valueForKey:#"timesAsNumber"];
NSLog(#"times As Number now reads: %ld", (long)timesUsedAsInt);
Produces the result: times As Number now reads: 237371328
I need to have the number as an integer for manipulation and my workaround of storing as string and converting to and fro is hardly elegant!
I teach High School computing so I know about storage of floating point numbers: excess-127, twos complement etc. I assume the problem arises from the different ways the integer is stored in the pList, the managed object and the NSInteger. However, I cannot figure out what those storage methods are so that I can work with them.
Any help gratefully received.
Tim.
When you are storing a number in plist or coreData, it is stored as NSNumber. So you access the value as NSInteger myInt = myNumber.intValue. When you are converting it back, use NSNumber *myNumber = [NSNumber numberWithInt:myInt]. That large number (237371328) could appear because you forgot to convert the NSNumber to int. Hope this helps.
Edit:
Try:
NSInteger timesUsedAsInt = [[currentUseData valueForKey:#"timesAsNumber"] intValue];
NSLog(#"times As Number now reads: %ld", (long)timesUsedAsInt);
I'm working on a DSP related iOS app. Part of the work is to copy audio data from outBuffer ->mAudioData to an user-specified array for data processing. The read method is like this:
OSStatus result = AudioFileReadPackets(myInfo->mAudioFile, // The audio file from which packets of audio data are to be read.
false, // Set to true to cache the data. Otherwise, set to false.
&numBytes, // On output, a pointer to the number of bytes actually returned.
myInfo->mPacketDescs, // A pointer to an array of packet descriptions that have been allocated.
myInfo->mCurrentPacket, // The packet index of the first packet you want to be returned.
&nPackets, // On input, a pointer to the number of packets to read. On output, the number of packets actually read.
outBuffer->mAudioData); // A pointer to user-allocated memory.
This process is successful. But when I'm trying to read data from outBuffer->mAudioData, there is always an error saying invalid conversion from 'void* const' to 'SInt16*':
outBuffer->mAudioDataByteSize = numBytes;
SInt16 *testBuffer = outBuffer->mAudioData; //Read data from buffer... Error!
for (int i=0; i<numBytes; i++)
{
UInt16 currentData = testBuffer[i];
printf("Current data in testbuffer is %d", currentData);
}
I have gone through several related questions like THIS and THIS, seems theirs are working...
I also tried to replace outBuffer->mAudioData to testBuffer in AudioFileReadPackets(), but the testBuffer turns out to be an empty array.
So is it the right approach? Is there any other way to read the raw data to an int/float array?
Or more generally, how to access an void constant pointer and perform read/write operation to it? (Yeah my C++ is not that strong...)
Any help will be appreciated :-)
Cheers,
Manca
I just put a cast in front and it seemed to work:
SInt16* frames = (SInt16*)inBuffer->mAudioData;