Skip to content

Xenakis Sieves

Griffin Moe edited this page Dec 5, 2018 · 3 revisions

What Are Sieves?

Xenakis sieves are a method for creating symmetrical and complex integer sequences created by Iannis Xenakis. Sieves consist of a step size i and a modulo value m, and are defined in shorthand using the `@` notation. A sieve defined as 3`@`0 will result in the following residue:

0, 3, 6, 9, ..., 3n

And the sieve defined as 3`@`1 should result in the following residue:

1, 4, 7, 10, ..., 3n + 1

Sieves in Code

To actually get numbers out of a sieve, you can provide it a range of values for which you are "sieving" through. For example, the following REPL output demonstrates how you would use a sieve in practice:

scala> import rc.dsl.gen.sieve._
import rc.dsl.gen.sieve._

scala> 4`@`0
res0: rc.dsl.gen.sieve.Residual = Residual(4,0)

scala> res0(0 to 10)
res1: IndexedSeq[Int] = Vector(0, 4, 8)

scala> (3`@`2)(0 to 10)
res2: IndexedSeq[Int] = Vector(2, 5, 8)

Sieve Operations

A single sieve is purely symmetrical and not complex, but sieves can be joined together using logical operators: unions, intersections, and differences. These work in the same way you would expect if you are familiar with set theory: unions result in a set of all numbers from both sieves, intersections result in a set of all numbers both sieves share, and differences result in a set of all numbers not shared between the sieves. There is also a fourth operation called a complement, which applies to a single sieve rather than combining two, and represents all of the numbers not in the set defined by the sieve.

Union

Unions can be created using the binary | operator, so the union defined by two sieves could look like (4`@`0) | (4`@`1). When run in the REPL it will result in the following sequence:

scala> (4`@`0) | (4`@`1)
res2: rc.dsl.gen.sieve.package.Sieve = Union(Residual(4,0),Residual(4,1))

scala> res2(0 to 10)
res3: IndexedSeq[Int] = Vector(0, 1, 4, 5, 8, 9)

Intersection

Intersections can be created using the binary & operator, so an intersection can be defined as (2`@`0) & (4`@`0). When run in the REPL it will result in the following sequence:

scala> (2`@`0) & (4`@`0)
res4: rc.dsl.gen.sieve.package.Sieve = Intersection(Residual(2,0),Residual(4,0))

scala> res4(0 to 10)
res5: IndexedSeq[Int] = Vector(0, 4, 8)

Difference

Differences can be created using the binary ^ operator, so a difference can be defined as (3`@`2) ^ (4`@`1). When run in the REPL it will result in the following sequence:

scala> (3`@`2) ^ (4`@`1)
res10: rc.dsl.gen.sieve.package.Sieve = Difference(Residual(3,2),Residual(4,1))

scala> res10(0 to 10)
res11: IndexedSeq[Int] = Vector(2, 8)

Complement

Complements can be create using the unary operator -, so a complement of a sieve can be defined as -(2`@`0). When run in the REPL it will result in the following sequence:

scala> -(2`@`0)
res12: rc.dsl.gen.sieve.Sieve = Complement(Residual(2,0))

scala> res12(0 to 10)
res13: IndexedSeq[Int] = Vector(1, 3, 5, 7, 9)

Use Cases

Sieves have multiple uses due to their symmetrical and complex nature, such as defining a set of pitches in a serialistic piece, creating a melodic line, or a sequence of beats.

TODO: Provide examples...

Clone this wiki locally