JuliaGPU / ArrayFire.jl
1
import Base: RefValue, @pure, show, clamp, findall
2
import Base: cumsum, cumprod, abs2
3
import LinearAlgebra: cholesky
4

5
export constant, get_last_error, err_to_string, sort_index, fir, iir
6
export mean_weighted, var_weighted, set_array_indexer, set_seq_param_indexer
7
export afeval, iota, sortbykey, select, device_mem_info, setafgcthreshold
8

9
const af_threshold = Ref(4*1024*1024*1024)
10

11
function device_gc()
12 0
    _error(ccall((:af_device_gc,af_lib),af_err,()), false)
13
end
14

15
function device_mem_info()
16 4
    alloc_bytes = RefValue{Csize_t}(0)
17 3
    alloc_buffers = RefValue{Csize_t}(0)
18 3
    lock_bytes = RefValue{Csize_t}(0)
19 3
    lock_buffers = RefValue{Csize_t}(0)
20 4
    _error(ccall((:af_device_mem_info,af_lib),af_err,
21
                 (Ptr{Csize_t},Ptr{Csize_t},Ptr{Csize_t},Ptr{Csize_t}),
22
                 alloc_bytes,alloc_buffers,lock_bytes,lock_buffers),
23
           false)
24 4
    (alloc_bytes[],alloc_buffers[],lock_bytes[],lock_buffers[])
25
end
26

27
function setafgcthreshold(threshold)
28 0
    af_threshold[] = threshold
29
end
30

31
function _afgc()
32 4
    for full in (false, true)
33 4
        alloc_bytes, alloc_buffers, lock_bytes, lock_buffers =  device_mem_info()
34 4
        if max(lock_bytes, alloc_bytes - lock_bytes) > af_threshold[]
35 0
            GC.gc(full)
36 0
            if full
37 4
                device_gc()
38
            end
39
        end
40
    end
41 4
    nothing
42
end
43

44
function release_array(arr::AFArray)
45 4
    _error(ccall((:af_release_array,af_lib),af_err,(af_array,),arr.arr), false)
46
end
47

48 0
toa(a) = issparse(a) ?  SparseMatrixCSC(a) : Array(a)
49 0
show(c::IOContext, a::AFArray) = (print(c, "AFArray: "); show(c, toa(a)))
50 0
show(io::IO, a::AFArray) = print(io, "AFArray: ", toa(a))
51
function show(io::IO, m::MIME"text/plain", a::AFArray)
52 0
    print(io, "AFArray: "); show(io, m, toa(a))
53
end
54

55
global const af_lib = Sys.isunix() ? (Sys.isapple() ? "libaf.3" : "libaf.so.3") : "af"
56
global const bcast = Ref{Bool}(false)
57

58
function __init__()
59 4
    Libdl.dlopen(af_lib)
60

61
    backend_envvar_name = "JULIA_ARRAYFIRE_BACKEND"
62 4
    if haskey(ENV, backend_envvar_name)
63 0
        backend_str = lowercase(ENV[backend_envvar_name])
64 0
        backends = Dict(
65
            "cpu" => AF_BACKEND_CPU,
66
            "cuda" => AF_BACKEND_CUDA,
67
            "opencl" => AF_BACKEND_OPENCL
68
        )
69 0
        if haskey(backends, backend_str)
70 0
            set_backend(backends[backend_str])
71
        else
72 0
            error("Unknown arrayfire backend \"$backend_str\".")
73
        end
74
    end
75

76 3
    afinit()
77 4
    if !haskey(ENV, "JULIA_ARRAYFIRE_SILENT")
78 3
        afinfo()
79
    end
80 3
    set_seed(rand(RandomDevice(), UInt64))
81 4
    nothing
82
end
83

84
function _error(err::af_err, gc = true)
85 4
    if err == 0
86 4
        if gc
87 4
            _afgc()
88
        end
89 4
    elseif err == AF_ERR_NO_MEM
90 0
        error("GPU is out of memory, to avoid this in the future you can:
91
  setafgcthreshold(threshold) # lower garbage collect threshold (default 4Gb)
92
  finalize(array)             # manually free GPU memory")
93
    else
94 3
        str = err_to_string(err)
95 3
        str2 = get_last_error()
96 4
        error("ArrayFire Error ($err) : $str\n$str2")
97
    end
98
end
99

100 4
@pure batched(n1, n2) = max(n1, n2)
101

102
function typed(::Type{T1},::Type{T2}) where {T1,T2}
103 0
    if T1 == T2
104 0
        return T1
105 0
    elseif T1 == Complex{Float64} || T2 == Complex{Float64}
106 0
        return Complex{Float64}
107 0
    elseif T1 == Complex{Float32} || T2 == Complex{Float32}
108 0
        (T1 == Float64 || T2 == Float64) && return Complex{Float64}
109 0
        return Complex{Float32}
110 0
    elseif T1 == Float64 || T2 == Float64
111 0
        return Float64
112 0
    elseif T1 == Float32 || T2 == Float32
113 0
        return Float32
114 0
    elseif T1 == Float16 || T2 == Float16
115 0
        return Float16
116 0
    elseif T1 == UInt64 || T2 == UInt64
117 0
        return UInt64
118 0
    elseif T1 == Int64 || T2 == Int64
119 0
        return Int64
120 0
    elseif T1 == UInt32 || T2 == UInt32
121 0
        return UInt32
122 0
    elseif T1 == Int32 || T2 == Int32
123 0
        return Int32
124 0
    elseif T1 == UInt16 || T2 == UInt16
125 0
        return UInt16
126 0
    elseif T1 == Int16 || T2 == Int16
127 0
        return Int16
128 0
    elseif T1 == UInt8 || T2 == UInt8
129 0
        return UInt8
130 0
    elseif T1 == Bool || T2 == Bool
131 0
        return Bool
132
    else
133 0
        return Float32
134
    end
135
end
136

137 4
af_type(::Type{Float32})          = f32
138 4
af_type(::Type{Complex{Float32}}) = c32
139 4
af_type(::Type{Float64})          = f64
140 4
af_type(::Type{Complex{Float64}}) = c64
141 3
af_type(::Type{Bool})             = b8
142 4
af_type(::Type{Int32})            = s32
143 0
af_type(::Type{Int16})            = s16
144 0
af_type(::Type{UInt16})           = u16
145 4
af_type(::Type{UInt32})           = u32
146 4
af_type(::Type{UInt8})            = u8
147 4
af_type(::Type{Int64})            = s64
148 4
af_type(::Type{UInt64})           = u64
149 0
af_type(::Type{Float16})          = f16
150

151
function af_jltype(i::af_dtype)::Type
152 4
    if i == f32
153 4
        return Float32
154 4
    elseif i == c32
155 4
        return Complex{Float32}
156 4
    elseif i == f64
157 4
        return Float64
158 4
    elseif i == c64
159 4
        return Complex{Float64}
160 4
    elseif i == b8
161 4
        return Bool
162 4
    elseif i == s32
163 4
        return Int32
164 4
    elseif i == u32
165 4
        return UInt32
166 4
    elseif i == u8
167 4
        return UInt8
168 4
    elseif i == s64
169 4
        return Int64
170 4
    elseif i == u64
171 4
        return UInt64
172 0
    elseif i == s16
173 0
        return Int16
174 0
    elseif i == u16
175 0
        return UInt16
176 0
    elseif i == f16
177 0
        return Float16
178
    else
179 0
        error("Unknown type: $i")
180
    end
181
end
182

183
function get_numdims(arr::af_array)
184 3
    result = RefValue{UInt32}(0)
185 4
    _error(ccall((:af_get_numdims,af_lib),af_err,
186
                 (Ptr{UInt32},af_array),result,arr))
187 3
    Int(result[])
188
end
189

190
function get_type(arr::af_array)
191 3
    _type = RefValue{af_dtype}(0)
192 4
    _error(ccall((:af_get_type,af_lib),af_err,
193
                 (Ptr{af_dtype},af_array),_type,arr), false)
194 4
    af_jltype(_type[])
195
end
196

197
function check_type_numdims(arr::AFArray{T,N}) where {T,N}
198 0
    @assert get_type(arr) == T "type mismatch: $(get_type(arr)) != $T"
199 0
    @assert get_numdims(arr) == N "dims mismatch: $(get_numdims(arr)) != $N"
200
end
201

202
function convert_array(data::AbstractArray{T,N}) where {T,N}
203 4
    arr = RefValue{af_array}(0)
204 3
    sz = size(data)
205 4
    _error(ccall((:af_create_array,af_lib),af_err,
206
                 (Ptr{af_array},Ptr{Cvoid},UInt32,Ptr{dim_t},af_dtype),
207
                 arr,data,UInt32(length(sz)),[sz...],af_type(T)))
208 4
    AFArray{T,N}(arr[])
209
end
210

211
function convert_array(a::AFArray{T,N}) where {T,N}
212 4
    if issparse(a)
213 0
        a = full(a)
214
    end
215 4
    ret = Array{T,N}(undef, size(a))
216 3
    get_data_ptr(ret, a)
217 4
    ret
218
end
219

220
function convert_array_to_sparse(a::SparseMatrixCSC)
221 4
    sz = size(a)
222 3
    at = sparse(transpose(a))
223 3
    colptr = AFArray(Vector{Int32}(at.colptr.-1))
224 3
    rowval = AFArray(Vector{Int32}(at.rowval.-1))
225 4
    create_sparse_array(sz[1], sz[2], AFArray(at.nzval), colptr, rowval, AF_STORAGE_CSR)
226
end
227

228
function convert_array_to_sparse(a::AFArray)
229 4
    @assert issparse(a) "AFArray is not sparse"
230 3
    sz = size(a)
231
    @assert length(sz) == 2 "AFArray is not a matrix"
232 3
    nzval, colptr, rowval, d = sparse_get_info(a)
233 4
    if d == AF_STORAGE_CSR
234 4
        transpose(SparseMatrixCSC(sz[2], sz[1],
235
                                  Array(colptr.+1), Array(rowval.+1), Array(nzval)))
236
    else
237 0
        convert_array_to_sparse(sparse_convert_to(a, AF_STORAGE_CSR))
238
    end
239
end
240

241
function recast_array(::Type{AFArray{T1}},_in::AFArray{T2,N}) where {T1,N,T2}
242 3
    out = RefValue{af_array}(0)
243 4
    _error(ccall((:af_cast,af_lib),af_err,
244
                 (Ptr{af_array},af_array,af_dtype),out,_in.arr,af_type(T1)))
245 4
    AFArray{T1,N}(out[])
246
end
247

248 4
AFArray!(arr::af_array) = AFArray{get_type(arr), get_numdims(arr)}(arr)
249

250
function constant(val::T,sz::NTuple{N,Int}) where {T<:Real,N}
251 4
    arr = RefValue{af_array}(0)
252 4
    _error(ccall((:af_constant,af_lib),af_err,
253
                 (Ptr{af_array},Cdouble,UInt32,Ptr{dim_t},af_dtype),
254
                 arr,Cdouble(val),UInt32(N),[sz...],af_type(T)))
255 4
    AFArray{T,N}(arr[])
256
end
257

258
function constant(val::Complex{Bool},sz::NTuple{N,Int}) where {N}
259 4
    arr = RefValue{af_array}(0)
260 4
    _error(ccall((:af_constant_complex,af_lib),af_err,
261
                 (Ptr{af_array},Cdouble,Cdouble,UInt32,Ptr{dim_t},af_dtype),
262
                 arr,Cdouble(real(val)),Cdouble(imag(val)),UInt32(N),[sz...],c32))
263 4
    AFArray{Complex{Float32},N}(arr[])
264
end
265

266
function constant(val::T,sz::NTuple{N,Int}) where {T<:Complex,N}
267 4
    arr = RefValue{af_array}(0)
268 4
    _error(ccall((:af_constant_complex,af_lib),af_err,
269
                 (Ptr{af_array},Cdouble,Cdouble,UInt32,Ptr{dim_t},af_dtype),
270
                 arr,Cdouble(real(val)),Cdouble(imag(val)),UInt32(N),[sz...],af_type(T)))
271 4
    AFArray{T,N}(arr[])
272
end
273

274
function constant(val::Int,sz::NTuple{N,Int}) where {N}
275 4
    arr = RefValue{af_array}(0)
276 4
    _error(ccall((:af_constant_long,af_lib),af_err,
277
                 (Ptr{af_array},intl,UInt32,Ptr{dim_t}),
278
                 arr,val,UInt32(N),[sz...]))
279 4
    AFArray{Int,N}(arr[])
280
end
281

282
function constant(val::UInt,sz::NTuple{N,Int}) where {N}
283 4
    arr = RefValue{af_array}(0)
284 4
    _error(ccall((:af_constant_ulong,af_lib),af_err,
285
                 (Ptr{af_array},uintl,UInt32,Ptr{dim_t}),
286
                 arr,val,UInt32(N),[sz...]))
287 4
    AFArray{UInt,N}(arr[])
288
end
289

290
function select(cond::AFArray{Bool},a::AFArray{T1,N1},b::AFArray{T2,N2}) where {T1,N1,T2,N2}
291 4
    out = RefValue{af_array}(0)
292 4
    _error(ccall((:af_select,af_lib),af_err,
293
                 (Ptr{af_array},af_array,af_array,af_array),
294
                 out,cond.arr,a.arr,b.arr))
295 4
    AFArray{typed(T1,T2),batched(N1,N2)}(out[])
296
end
297

298
function select(cond::AFArray{Bool},a::AFArray{T1,N1},b::T2) where {T1,N1,T2<:Real}
299 4
    out = RefValue{af_array}(0)
300 4
    _error(ccall((:af_select_scalar_r,af_lib),af_err,
301
                 (Ptr{af_array},af_array,af_array,Cdouble),
302
                 out,cond.arr,a.arr,Cdouble(b)))
303 4
    AFArray{typed(T1,T2),N1}(out[])
304
end
305

306
function select(cond::AFArray{Bool},a::T1,b::AFArray{T2,N2}) where {T1,T2,N2}
307 4
    out = RefValue{af_array}(0)
308 4
    _error(ccall((:af_select_scalar_l,af_lib),af_err,
309
                 (Ptr{af_array},af_array,Cdouble,af_array),
310
                 out,cond.arr,Cdouble(a),b.arr))
311 4
    AFArray{typed(T1,T2),N2}(out[])
312
end
313

314
function err_to_string(err::af_err)
315 4
    unsafe_string(ccall((:af_err_to_string,af_lib),Cstring,(af_err,),err))
316
end
317

318
function get_last_error()
319 3
    msg = RefValue{Cstring}()
320 3
    len = RefValue{dim_t}(0)
321 4
    ccall((:af_get_last_error,af_lib),Cvoid,(Ptr{Cstring},Ptr{dim_t}),msg,len)
322 4
    unsafe_string(msg[])
323
end
324

325
function cat(dim::Integer,first::AFArray{T,N1},second::AFArray{T,N2}) where {T,N1,N2}
326 4
    out = RefValue{af_array}(0)
327 4
    _error(ccall((:af_join,af_lib),af_err,
328
                 (Ptr{af_array},Cint,af_array,af_array),
329
                 out,Cint(dim - 1),first.arr,second.arr))
330 4
    AFArray!(out[])
331
end
332

333
function cat(A::AFArray...; dims::Integer)
334 0
    out = RefValue{af_array}(0)
335 0
    _error(ccall((:af_join_many,af_lib),af_err,
336
                 (Ptr{af_array},Cint, Cuint, Ptr{af_array}),
337 0
                 out,Cint(dims - 1), Cuint(length(A)), [map(x->x.arr, A)...]))
338 0
    AFArray!(out[])
339
end
340

341 4
hcat(first::AFArray, second::AFArray) = cat(2, first, second)
342 4
vcat(first::AFArray, second::AFArray) = cat(1, first, second)
343

344
import DSP: conv
345

346
function conv(signal::AFArray{T,N}, filter::AFArray) where {T,N}
347 4
    out = RefValue{af_array}(0)
348 4
    _error(ccall((:af_convolve1,af_lib),af_err,
349
                 (Ptr{af_array},af_array,af_array,af_conv_mode,af_conv_domain),
350
                 out,signal.arr,filter.arr,AF_CONV_EXPAND,AF_CONV_AUTO))
351 4
    AFArray{T,N}(out[])
352
end
353

354
function conv_fft(signal::AFArray{T,N}, filter::AFArray) where {T,N}
355 0
    out = RefValue{af_array}(0)
356 0
    _error(ccall((:af_fft_convolve1,af_lib),af_err,(Ptr{af_array},af_array,af_array,af_conv_mode),
357
                 out,signal.arr,filter.arr,AF_CONV_EXPAND))
358 0
    AFArray{T,N}(out[])
359
end
360

361 4
norm(a::AFArray{T}) where T = T(norm(a, AF_NORM_EUCLID, 0, 0))
362 0
vecnorm(a::AFArray{T}) where T = T(norm(a, AF_NORM_EUCLID, 0, 0))
363

364
function svd(_in::AFArray{T,2}) where {T}
365 4
    u = RefValue{af_array}(0)
366 3
    s = RefValue{af_array}(0)
367 3
    vt = RefValue{af_array}(0)
368 4
    _error(ccall((:af_svd,af_lib),af_err,
369
                 (Ptr{af_array},Ptr{af_array},Ptr{af_array},af_array),
370
                 u,s,vt,_in.arr))
371 4
    (AFArray{T,2}(u[]),AFArray{T,1}(s[]),AFArray{T,2}(vt[]))
372
end
373

374
function sort(_in::AFArray{T,N},dim::Integer,isAscending::Bool=true) where {T,N}
375 3
    out = RefValue{af_array}(0)
376 4
    _error(ccall((:af_sort,af_lib),af_err,
377
                 (Ptr{af_array},af_array,UInt32,Bool),
378
                 out,_in.arr,UInt32(dim - 1),isAscending))
379 4
    AFArray{T,N}(out[])
380
end
381

382
function sort_index(_in::AFArray{T,N},dim::Integer=1,isAscending::Bool=true) where {T,N}
383 3
    out = RefValue{af_array}(0)
384 3
    indices = RefValue{af_array}(0)
385 4
    _error(ccall((:af_sort_index,af_lib),af_err,
386
                 (Ptr{af_array},Ptr{af_array},af_array,UInt32,Bool),
387
                 out,indices,_in.arr,UInt32(dim - 1),isAscending))
388 4
    (AFArray{T,N}(out[]),AFArray{UInt32,N}(indices[])+UInt32(1))
389
end
390

391
function sortperm(a::AFArray{T,N}, dim::Integer=1,isAscending::Bool=true) where {T,N}
392 4
    sort_index(a,dim,isAscending)[2]
393
end
394

395
function mean(_in::AFArray{T,N},dim::dim_t) where {T,N}
396 0
    out = RefValue{af_array}(0)
397 0
    _error(ccall((:af_mean,af_lib),af_err,(Ptr{af_array},af_array,dim_t),
398
                 out,_in.arr,dim-1))
399 0
    AFArray{T,N}(out[])
400
end
401

402
function mean_weighted(_in::AFArray{T,N},weights::AFArray,dim::dim_t) where {T,N}
403 0
    out = RefValue{af_array}(0)
404 0
    _error(ccall((:af_mean_weighted,af_lib),af_err,
405
                 (Ptr{af_array},af_array,af_array,dim_t),
406
                 out,_in.arr,weights.arr,dim-1))
407 0
    AFArray{T,N}(out[])
408
end
409

410
function var(_in::AFArray{T,N},isbiased::Bool,dim::dim_t) where {T,N}
411 0
    out = RefValue{af_array}(0)
412 0
    _error(ccall((:af_var,af_lib),af_err,
413
                 (Ptr{af_array},af_array,Bool,dim_t),
414
                 out,_in.arr,isbiased,dim-1))
415 0
    AFArray{T,N}(out[])
416
end
417

418
function var_weighted(_in::AFArray{T,N},weights::AFArray,dim::dim_t) where {T,N}
419 0
    out = RefValue{af_array}(0)
420 0
    _error(ccall((:af_var_weighted,af_lib),af_err,
421
                 (Ptr{af_array},af_array,af_array,dim_t),
422
                 out,_in.arr,weights.arr,dim-1))
423 0
    AFArray{T,N}(out[])
424
end
425

426
function std(_in::AFArray{T,N},dim::dim_t) where {T,N}
427 0
    out = RefValue{af_array}(0)
428 0
    _error(ccall((:af_stdev,af_lib),af_err,
429
                 (Ptr{af_array},af_array,dim_t),out,_in.arr,dim-1))
430 0
    AFArray{T,N}(out[])
431
end
432

433
function median(_in::AFArray{T,N},dim::dim_t) where {T,N}
434 0
    out = RefValue{af_array}(0)
435 0
    _error(ccall((:af_median,af_lib),af_err,
436
                 (Ptr{af_array},af_array,dim_t),
437
                 out,_in.arr,dim-1))
438 0
    AFArray{T,N}(out[])
439
end
440

441
function set_seq_param_indexer(_begin::Real,_end::Real,step::Real,dim::dim_t,is_batch::Bool)
442 0
    indexer = RefValue{af_index_t}(0)
443 0
    _error(ccall((:af_set_seq_param_indexer,af_lib),af_err,
444
                 (Ptr{af_index_t},Cdouble,Cdouble,Cdouble,dim_t,Bool),
445
                 indexer,Cdouble(_begin),Cdouble(_end),Cdouble(step),dim-1,is_batch))
446 0
    indexer[]
447
end
448

449
function clamp(_in::AFArray{T1,N1},lo::AFArray{T2,N2},hi::AFArray{T2,N2}) where {T1,N1,T2,N2}
450 0
    out = RefValue{af_array}(0)
451 0
    _error(ccall((:af_clamp,af_lib),af_err,
452
                 (Ptr{af_array},af_array,af_array,af_array,Bool),
453
                 out,_in.arr,lo.arr,hi.arr,bcast[]))
454 0
    AFArray{typed(T1,T2),batched(N1,N2)}(out[])
455
end
456

457
function af_where(_in::AFArray{T,N}) where {T,N}
458 3
    idx = RefValue{af_array}(0)
459 4
    _error(ccall((:af_where,af_lib),af_err,(Ptr{af_array},af_array),idx,_in.arr))
460 4
    return AFArray{UInt32,1}(idx[])
461
end
462

463
function findall(_in::AFArray{T,N}) where {T,N}
464 0
    out = af_where(_in)
465 0
    if length(out) > 0
466 0
        out = out + UInt32(1)
467
    end
468 0
    return out
469
end
470

471 4
cumsum(a::AFArray, dim::Int) = scan(a, dim, AF_BINARY_ADD, true)
472 0
cumprod(a::AFArray, dim::Int) = scan(a, dim, AF_BINARY_MUL, true)
473 0
cummin(a::AFArray, dim::Int) = scan(a, dim, AF_BINARY_MIN, true)
474 0
cummax(a::AFArray, dim::Int) = scan(a, dim, AF_BINARY_MAX, true)
475

476
function sync(a::AFArray)
477 4
    afeval(a)
478 3
    sync(get_device_id(a))
479 4
    a
480
end
481

482
function afeval(a::AFArray)
483 4
    _error(ccall((:af_eval,af_lib),af_err,(af_array,),a.arr))
484
    a
485
end
486

487
function afeval(A::AFArray...)
488 0
    _error(ccall((:af_eval_multiple,af_lib),af_err,(Cuint, Ptr{af_array}),
489 0
                 Cuint(length(A)), [map(x->x.arr, A)...]))
490 0
    A
491
end
492 0
afeval(A::Tuple) = afeval(A...)
493

494
function cholesky(_in::AFArray{T,N},is_upper::Bool=false) where {T,N}
495 0
    out = RefValue{af_array}(0)
496 0
    info = RefValue{Cint}(0)
497 0
    _error(ccall((:af_cholesky,af_lib),af_err,(Ptr{af_array},Ptr{Cint},af_array,Bool),out,info,_in.arr,is_upper))
498 0
    (AFArray{T,N}(out[]),info[])
499
end
500

501 4
abs2(a::AFArray{T}) where {T<:Real} = a.*a
502 4
abs2(a::AFArray{T}) where {T<:Complex} = (r = real(a); i = imag(a); r.*r+i.*i)
503

504
function complex(lhs::AFArray{T1,N1},rhs::AFArray{T2,N2}) where {T1,N1,T2,N2}
505 4
    batch = bcast[]
506 3
    out = RefValue{af_array}(0)
507 4
    _error(ccall((:af_cplx2,af_lib),af_err,(Ptr{af_array},af_array,af_array,Bool),out,lhs.arr,rhs.arr,batch))
508 4
    AFArray{Complex{typed(T1,T2)},batched(N1,N2)}(out[])
509
end
510

511
function fir(b::AFArray,x::AFArray{T,N}) where {T,N}
512 4
    y = RefValue{af_array}(0)
513 4
    _error(ccall((:af_fir,af_lib),af_err,(Ptr{af_array},af_array,af_array),y,b.arr,x.arr))
514 4
    AFArray{T,N}(y[])
515
end
516

517
function iir(b::AFArray{T},a::AFArray{T},x::AFArray{T,N}) where {T,N}
518 4
    y = RefValue{af_array}(0)
519 4
    _error(ccall((:af_iir,af_lib),af_err,(Ptr{af_array},af_array,af_array,af_array),y,b.arr,a.arr,x.arr))
520 4
    AFArray{T,N}(y[])
521
end
522

523
function iota(dims::NTuple{N,Int}, typ::Type{T} = Int32) where {T,N}
524 4
    out = RefValue{af_array}(0)
525 4
    _error(ccall((:af_iota,af_lib), af_err,
526
                 (Ptr{af_array},UInt32,Ptr{dim_t},UInt32,Ptr{dim_t},af_dtype),
527
                 out,UInt32(N),[dims...],UInt32(1),[1],af_type(T)))
528 4
    AFArray{T,N}(out[])+T(1)
529
end
530

531
function sortbykey(keys::AFArray{T1,N},values::AFArray{T2,N},dim::Integer,isAscending::Bool=true) where {T1,T2,N}
532 0
    out_keys = RefValue{af_array}(0)
533 0
    out_values = RefValue{af_array}(0)
534 0
    _error(ccall((:af_sort_by_key,af_lib),af_err,(Ptr{af_array},Ptr{af_array},af_array,af_array,UInt32,Bool),out_keys,out_values,keys.arr,values.arr,UInt32(dim - 1),isAscending))
535 0
    (AFArray{T1,N}(out_keys[]),AFArray{T2,N}(out_values[]))
536
end
537

538
function sum(_in::AFArray{UInt8,N},dim::Integer) where N
539 0
    out = RefValue{af_array}(0)
540 0
    _error(ccall((:af_sum,af_lib),af_err,(Ptr{af_array},af_array,Cint),out,_in.arr,Cint(dim - 1)))
541 0
    AFArray{UInt32,N}(out[])
542
end
543

544
function sum(_in::AFArray{Bool,N},dim::Integer) where N
545 0
    out = RefValue{af_array}(0)
546 0
    _error(ccall((:af_sum,af_lib),af_err,(Ptr{af_array},af_array,Cint),out,_in.arr,Cint(dim - 1)))
547 0
    AFArray{UInt32,N}(out[])
548
end

Read our documentation on viewing source code .

Loading