Given the performance difference and the different behavior, I'm tempted to
just deprecate the two-argument form of pointer.

On Wed, Mar 25, 2015 at 12:53 PM, Sebastian Good <
[email protected]> wrote:

> I guess what I find most confusing is that there would be a difference,
> since adding 1 to a pointer only adds one byte, not one element size.
>
> > p1 = pointer(zeros(UInt64));
> Ptr{UInt64} @0x000000010b28c360
> > p1 + 1
> Ptr{UInt64} @0x000000010b28c361
>
> I would have expected the latter to end in 68. the two argument pointer
> function gets this “right”.
>
> > a=zeros(UInt64);
> > pointer(a,1)
> Ptr{Int64} @0x000000010b9c72e0
> > pointer(a,2)
> Ptr{Int64} @0x000000010b9c72e8
>
> I can see arguments multiple ways, but when I’m given a strongly typed
> pointer (Ptr{T}), I would expect it to participate in arithmetic in
> increments of sizeof(T).
>
> On March 25, 2015 at 6:36:37 AM, Stefan Karpinski ([email protected])
> wrote:
>
> That does seem to be the issue. It's tricky to fix since you can't
> evaluate sizeof(Ptr) unless the condition is true.
>
> On Tue, Mar 24, 2015 at 7:13 PM, Stefan Karpinski <[email protected]>
> wrote:
>
>> There's a branch in eltype, which is probably causing this difference.
>>
>> On Tue, Mar 24, 2015 at 7:00 PM, Sebastian Good <
>> [email protected]> wrote:
>>
>>>  Yep, that’s done it. The only difference I can see in the code I wrote
>>> before and this code is that previously I had
>>>
>>> convert(Ptr{T}, pointer(raw, byte_number))
>>>
>>>  whereas here we have
>>>
>>> convert(Ptr{T}, pointer(raw) + byte_number - 1)
>>>
>>> The former construction seems to emit a call to a Julia-intrinsic
>>> function, while the latter executes the more expected simple machine loads.
>>> Is there a subtle difference between the two calls to pointer?
>>>
>>> Thanks all for your help!
>>>
>>> On March 24, 2015 at 12:19:00 PM, Matt Bauman ([email protected]) wrote:
>>>
>>>  (The key is to ensure that the method gets specialized for different
>>> types with the parametric `::Type{T}` in the signature instead of
>>> `T::DataType`).
>>>
>>> On Tuesday, March 24, 2015 at 12:10:59 PM UTC-4, Stefan Karpinski wrote:
>>>>
>>>> This seems like it works fine to me (on both 0.3 and 0.4):
>>>>
>>>>  immutable Test
>>>> x::Float32
>>>> y::Int64
>>>> z::Int8
>>>> end
>>>>
>>>>  julia> a = [Test(1,2,3)]
>>>> 1-element Array{Test,1}:
>>>>  Test(1.0f0,2,3)
>>>>
>>>> julia> b = copy(reinterpret(UInt8, a))
>>>> 24-element Array{UInt8,1}:
>>>>  0x00
>>>>  0x00
>>>>  0x80
>>>>  0x3f
>>>>  0x03
>>>>  0x00
>>>>  0x00
>>>>  0x00
>>>>  0x02
>>>>  0x00
>>>>  0x00
>>>>  0x00
>>>>  0x00
>>>>  0x00
>>>>  0x00
>>>>  0x00
>>>>  0x03
>>>>  0xe0
>>>>  0x82
>>>>  0x10
>>>>  0x01
>>>>  0x00
>>>>  0x00
>>>>  0x00
>>>>
>>>> julia> prim_read{T}(::Type{T}, data::Array{Uint8,1}, offset::Int) =
>>>> unsafe_load(convert(Ptr{T}, pointer(data) + offset))
>>>> prim_read (generic function with 1 method)
>>>>
>>>> julia> prim_read(Test, b, 0)
>>>> Test(1.0f0,2,3)
>>>>
>>>> julia> @code_native prim_read(Test, b, 0)
>>>> .section __TEXT,__text,regular,pure_instructions
>>>> Filename: none
>>>> Source line: 1
>>>> push RBP
>>>> mov RBP, RSP
>>>> Source line: 1
>>>> mov RCX, QWORD PTR [RSI + 8]
>>>> vmovss XMM0, DWORD PTR [RCX + RDX]
>>>> mov RAX, QWORD PTR [RCX + RDX + 8]
>>>> mov DL, BYTE PTR [RCX + RDX + 16]
>>>> pop RBP
>>>> ret
>>>>
>>>>
>>>> On Tue, Mar 24, 2015 at 5:04 PM, Simon Danisch <[email protected]>
>>>> wrote:
>>>>
>>>>> There is a high chance that I simply don't understand llvmcall well
>>>>> enough, though ;)
>>>>>
>>>>> Am Montag, 23. März 2015 20:20:09 UTC+1 schrieb Sebastian Good:
>>>>>>
>>>>>> I'm trying to read some binary formatted data. In C, I would define
>>>>>> an appropriately padded struct and cast away. Is is possible to do
>>>>>> something similar in Julia, though for only one value at a time?
>>>>>> Philosophically, I'd like to approximate the following, for some simple
>>>>>> bittypes T (Int32, Float32, etc.)
>>>>>>
>>>>>> T read<T>(char* data, size_t offset) { return *(T*)(data + offset); }
>>>>>>
>>>>>> The transliteration of this brain-dead approach results in the
>>>>>> following, which seems to allocate a boxed Pointer object on every
>>>>>> invocation. The pointer function comes with ample warnings about how it
>>>>>> shouldn't be used, and I imagine that it's not polite to the garbage
>>>>>> collector.
>>>>>>
>>>>>>  prim_read{T}(::Type{T}, data::AbstractArray{Uint8, 1}, byte_number)
>>>>>> = unsafe_load(convert(Ptr{T}, pointer(data, byte_number)))
>>>>>>
>>>>>> I can reinterpret the whole array, but this will involve a division
>>>>>> of the offset to calculate the new offset relative to the reinterpreted
>>>>>> array, and it allocates an array object.
>>>>>>
>>>>>> Is there a better way to simply read the machine word at a particular
>>>>>> offset in a byte array? I would think it should inline to a single 
>>>>>> assembly
>>>>>> instruction if done right.
>>>>>>
>>>>>>
>>>>>
>>>>
>>
>

Reply via email to