Movatterモバイル変換


[0]ホーム

URL:


GitHub

Base.Cartesian

The (non-exported) Cartesian module provides macros that facilitate writing multidimensional algorithms. Most often you can write such algorithms withstraightforward techniques; however, there are a few cases whereBase.Cartesian is still useful or necessary.

Principles of usage

A simple example of usage is:

@nloops 3 i A begin    s += @nref 3 A iend

which generates the following code:

for i_3 = axes(A, 3)    for i_2 = axes(A, 2)        for i_1 = axes(A, 1)            s += A[i_1, i_2, i_3]        end    endend

In general, Cartesian allows you to write generic code that contains repetitive elements, like the nested loops in this example. Other applications include repeated expressions (e.g., loop unwinding) or creating function calls with variable numbers of arguments without using the "splat" construct (i...).

Basic syntax

The (basic) syntax of@nloops is as follows:

There are some additional features of@nloops described in thereference section.

@nref follows a similar pattern, generatingA[i_1,i_2,i_3] from@nref 3 A i. The general practice is to read from left to right, which is why@nloops is@nloops 3 i A expr (as infor i_2 = axes(A, 2), wherei_2 is to the left and the range is to the right) whereas@nref is@nref 3 A i (as inA[i_1,i_2,i_3], where the array comes first).

If you're developing code with Cartesian, you may find that debugging is easier when you examine the generated code, using@macroexpand:

julia> @macroexpand @nref 2 A i:(A[i_1, i_2])

Supplying the number of expressions

The first argument to both of these macros is the number of expressions, which must be an integer. When you're writing a function that you intend to work in multiple dimensions, this may not be something you want to hard-code. The recommended approach is to use a@generated function. Here's an example:

@generated function mysum(A::Array{T,N}) where {T,N}    quote        s = zero(T)        @nloops $N i A begin            s += @nref $N A i        end        s    endend

Naturally, you can also prepare expressions or perform calculations before thequote block.

Anonymous-function expressions as macro arguments

Perhaps the single most powerful feature inCartesian is the ability to supply anonymous-function expressions that get evaluated at parsing time. Let's consider a simple example:

@nexprs 2 j->(i_j = 1)

@nexprs generatesn expressions that follow a pattern. This code would generate the following statements:

i_1 = 1i_2 = 1

In each generated statement, an "isolated"j (the variable of the anonymous function) gets replaced by values in the range1:2. Generally speaking, Cartesian employs a LaTeX-like syntax. This allows you to do math on the indexj. Here's an example computing the strides of an array:

s_1 = 1@nexprs 3 j->(s_{j+1} = s_j * size(A, j))

would generate expressions

s_1 = 1s_2 = s_1 * size(A, 1)s_3 = s_2 * size(A, 2)s_4 = s_3 * size(A, 3)

Anonymous-function expressions have many uses in practice.

Macro reference

Base.Cartesian.@nloopsMacro
@nloops N itersym rangeexpr bodyexpr@nloops N itersym rangeexpr preexpr bodyexpr@nloops N itersym rangeexpr preexpr postexpr bodyexpr

GenerateN nested loops, usingitersym as the prefix for the iteration variables.rangeexpr may be an anonymous-function expression, or a simple symbolvar in which case the range isaxes(var, d) for dimensiond.

Optionally, you can provide "pre" and "post" expressions. These get executed first and last, respectively, in the body of each loop. For example:

@nloops 2 i A d -> j_d = min(i_d, 5) begin    s += @nref 2 A jend

would generate:

for i_2 = axes(A, 2)    j_2 = min(i_2, 5)    for i_1 = axes(A, 1)        j_1 = min(i_1, 5)        s += A[j_1, j_2]    endend

If you want just a post-expression, supplynothing for the pre-expression. Using parentheses and semicolons, you can supply multi-statement expressions.

source
Base.Cartesian.@nrefMacro
@nref N A indexexpr

Generate expressions likeA[i_1, i_2, ...].indexexpr can either be an iteration-symbol prefix, or an anonymous-function expression.

Examples

julia> @macroexpand Base.Cartesian.@nref 3 A i:(A[i_1, i_2, i_3])
source
Base.Cartesian.@nextractMacro
@nextract N esym isym

GenerateN variablesesym_1,esym_2, ...,esym_N to extract values fromisym.isym can be either aSymbol or anonymous-function expression.

@nextract 2 x y would generate

x_1 = y[1]x_2 = y[2]

while@nextract 3 x d->y[2d-1] yields

x_1 = y[1]x_2 = y[3]x_3 = y[5]
source
Base.Cartesian.@nexprsMacro
@nexprs N expr

GenerateN expressions.expr should be an anonymous-function expression.

Examples

julia> @macroexpand Base.Cartesian.@nexprs 4 i -> y[i] = A[i+j]quote    y[1] = A[1 + j]    y[2] = A[2 + j]    y[3] = A[3 + j]    y[4] = A[4 + j]end
source
Base.Cartesian.@ncallMacro
@ncall N f sym...

Generate a function call expression.sym represents any number of function arguments, the last of which may be an anonymous-function expression and is expanded intoN arguments.

For example,@ncall 3 func a generates

func(a_1, a_2, a_3)

while@ncall 2 func a b i->c[i] yields

func(a, b, c[1], c[2])
source
Base.Cartesian.@ncallkwMacro
@ncallkw N f kw sym...

Generate a function call expression with keyword argumentskw.... As in the case of@ncall,sym represents any number of function arguments, the last of which may be an anonymous-function expression and is expanded intoN arguments.

Examples

julia> using Base.Cartesianjulia> f(x...; a, b = 1, c = 2, d = 3) = +(x..., a, b, c, d);julia> x_1, x_2 = (-1, -2); b = 0; kw = (c = 0, d = 0);julia> @ncallkw 2 f (; a = 0, b, kw...) x-3
source
Base.Cartesian.@ntupleMacro
@ntuple N expr

Generates anN-tuple.@ntuple 2 i would generate(i_1, i_2), and@ntuple 2 k->k+1 would generate(2,3).

source
Base.Cartesian.@nallMacro
@nall N expr

Check whether all of the expressions generated by the anonymous-function expressionexpr evaluate totrue.

@nall 3 d->(i_d > 1) would generate the expression(i_1 > 1 && i_2 > 1 && i_3 > 1). This can be convenient for bounds-checking.

source
Base.Cartesian.@nanyMacro
@nany N expr

Check whether any of the expressions generated by the anonymous-function expressionexpr evaluate totrue.

@nany 3 d->(i_d > 1) would generate the expression(i_1 > 1 || i_2 > 1 || i_3 > 1).

source
Base.Cartesian.@nifMacro
@nif N conditionexpr expr@nif N conditionexpr expr elseexpr

Generates a sequence ofif ... elseif ... else ... end statements. For example:

@nif 3 d->(i_d >= size(A,d)) d->(error("Dimension ", d, " too big")) d->println("All OK")

would generate:

if i_1 > size(A, 1)    error("Dimension ", 1, " too big")elseif i_2 > size(A, 2)    error("Dimension ", 2, " too big")else    println("All OK")end
source

Settings


This document was generated withDocumenter.jl version 1.8.0 onWednesday 9 July 2025. Using Julia version 1.11.6.


[8]ページ先頭

©2009-2025 Movatter.jp