Introduction

Generative art represents the involvement of a human-independent system (such as an algorithm) in a creative process. Such a system is a key element within the creative process, including its outputs.

Unsurprisingly, there are many “tools” you can use if you want to delve into generative art. In case you want to have “hands-on” experience in R, there are two basic directions you can go.

If you are a person proficient working with code, you may write your code straight away. I dare to argue that this is the way of the “individual” expression as it allows for more flexibility, and, well, freedom.

However, getting to that point takes time. Luckily, you can begin experimenting with your pieces of generative art by using one of the existing packages. Not only it could be quite rewarding, but it also works perfectly for grasping the basics of the “trade”.

In this article, I am going to present to you some of the “ready-to-use” packages for making generative art. Also, I will tap into some of the examples of using general packages or libraries to arrive at the same goal.

jasmines

Danielle Navarro, the author of the Learning Statistics with R Learning Statistics with R handbook, is a well-known person among psychology students.

Besides her teaching and research activities at the University of Adelaide, she also released the jasmines package, a tool allowing for creating a generative art in R.

This package gives you an opportunity to play with simulation parameters (e.g. grain or interaction), shapes (e.g. entity_circle or scene_discs) and their modifications (like style_ribbon) or colours (palette or alpha). And noise, linked to the ambient library.

kdtree

mathart + ggart

The mathart package wraps many of commonly used algorithms into functions. One of such examples is the nearest neighbor graph, a visualisation of the k-d tree, a data structuring procedure of multidimensional space:

kdtree


mathart is a well-documented package. This fact widens the scope for experimenting. Maybe more importantly, by looking “under the hood”, the package improves understanding of data simulation.

General purpose packages

In many instances, previously mentioned packages built on more generally used packages such as magritr (the pipeline operator comes handy even in the art creation), ggplot, dplyr, or purr.

The k-d tree from the mathart package is no different. As we can see from the example of Marcus Volz, the original k-d tree algorithm can be tweaked using even base R:

# Metropolis: Generative city visualisations

# Packages
library(ggart)
library(tidyverse)
library(tweenr)
library(viridis)

# Make reproducible
set.seed(10001)

# Parameters
n <- 10000 # iterations
r <- 75 # neighbourhood
width <- 10000 # canvas width
height <- 10000 # canvas height
delta <- 2 * pi / 180 # angle direction noise
p_branch <- 0.1 # probability of branching
initial_pts <- 3 # number of initial points
nframes <- 500 # number of tweenr frames

# Initialise data frames
points <- data.frame(x = numeric(n), y = numeric(n), dir = numeric(n), level = integer(n))
edges <-  data.frame(x = numeric(n), y = numeric(n), xend = numeric(n), yend = numeric(n), level = integer(n))

if(initial_pts > 1) {
  i <- 2
  while(i <= initial_pts) {
    points[i, ] <- c(runif(1, 0, width), runif(1, 0, height), runif(1, -2*pi, 2*pi), 1)
    i <- i + 1
  }
}

t0 <- Sys.time()

# Main loop ----
i <- initial_pts + 1
while (i <= n) {
  valid <- FALSE
  while (!valid) {
    random_point <- sample_n(points[seq(1:(i-1)), ], 1) # Pick a point at random
    branch <- ifelse(runif(1, 0, 1) <= p_branch, TRUE, FALSE)
    alpha <- random_point$dir[1] + runif(1, -(delta), delta) + (branch * (ifelse(runif(1, 0, 1) < 0.5, -1, 1) * pi/2))
    v <- c(cos(alpha), sin(alpha)) * r * (1 + 1 / ifelse(branch, random_point$level[1]+1, random_point$level[1])) # Create directional vector
    xj <- random_point$x[1] + v[1]
    yj <- random_point$y[1] + v[2]
    lvl <- random_point$level[1]
    lvl_new <- ifelse(branch, lvl+1, lvl)
    if(xj < 0 | xj > width | yj < 0 | yj > height) {
      next
    }
    points_dist <- points %>% mutate(d = sqrt((xj - x)^2 + (yj - y)^2))
    if (min(points_dist$d) >= 1 * r) {
      points[i, ] <- c(xj, yj, alpha, lvl_new)
      edges[i, ] <- c(xj, yj, random_point$x[1], random_point$y[1], lvl_new)
      # Add a building if possible
      buiding <- 1
      valid <- TRUE
    }
  }
  i <- i + 1
  print(i)
}
edges <- edges %>% filter(level > 0)

sand <- data.frame(alpha = numeric(0), x = numeric(0), y = numeric(0))
perp <- data.frame(x = numeric(0), y = numeric(0), xend = numeric(0), yend = numeric(0))

# Create plot
p2 <- ggplot() +
  geom_segment(aes(x, y, xend = xend, yend = yend, size = -level), edges, lineend = "round") +
  #geom_segment(aes(x, y, xend = xend, yend = yend), perp, lineend = "round", alpha = 0.15) +
  #geom_point(aes(x, y), points) +
  #geom_point(aes(x, y), sand, size = 0.05, alpha = 0.05, colour = "black") +
  xlim(0, 10000) +
  ylim(0, 10000) +
  coord_equal() +
  scale_size_continuous(range = c(0.5, 0.5)) +
  #scale_color_viridis() +
  theme_blankcanvas(bg_col = "#fafafa", margin_cm = 0)

# print plot
ggsave("plot007w.png", p2, width = 20, height = 20, units = "cm", dpi = 300)
kdtree


You don’t need to stop here. Some time spent on playing with the code can easily end up by creating your distinct wall poster.

Closing remarks

Generative art demonstrates that code can be beautiful. If you are still not persuaded, go and see more elaborated works like these.

Not only can generative art result in something astonishing, but it also helps you to understand the code itself. Interestingly, getting to the code underlying generative art may not be as easy as with other open-source areas. Some “generative artists” conclude not to share the code used in the creative process:

“I do not share the code I use to create my pieces. The main reason for this is that I don’t think it would be beneficial to anyone. People interested in getting started with generative art would become to focused on my ideas instead of developing their own. Knowing the answer is the killer of creativity.”

Thomas Lin Pedersen, Data Imaginist


Regardless if we agree or not, generative art confronts us with ideas that are not that common in the world of coding.

So, what are your ideas on the matter? Do you have any favourite generative artists? Or maybe your pieces of art you would like to share? Feel free to discuss on twitter.

   

Go back to Blog

LS0tCnRpdGxlOiAiR2V0dGluZyBzdGFydGVkIHdpdGggZ2VuZXJhdGl2ZSBhcnQgaW4gUiIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgYWxsaWduOiByaWdodAogICAgdGhlbWU6IGZsYXRseQogICAgaGlnaGxpZ2h0OiBtb25vY2hyb21lCiAgICBjc3M6IH4vRGVza3RvcC9HaXQvV2VicGFnZS9kYXRhbXVzdGZsb3cvcHVibGljL2Nzcy9jb2Rlci5taW4uYTRmMzMyMjEzYTIxY2U4ZWI1MjE2NzBjNjE0NDcwYzU4OTIzYWFhZjM4NWUyYTczOTgyYzMxZGQ3NjQyZGVjYi5jc3MKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgojIyBJbnRyb2R1Y3Rpb24KCkdlbmVyYXRpdmUgYXJ0IHJlcHJlc2VudHMgdGhlIGludm9sdmVtZW50IG9mIGEgaHVtYW4taW5kZXBlbmRlbnQgc3lzdGVtIChzdWNoIGFzIGFuIGFsZ29yaXRobSkgaW4gYSBjcmVhdGl2ZSBwcm9jZXNzLiBTdWNoIGEgc3lzdGVtIGlzIGEga2V5IGVsZW1lbnQgd2l0aGluIHRoZSBjcmVhdGl2ZSBwcm9jZXNzLCBpbmNsdWRpbmcgaXRzIG91dHB1dHMuIAoKVW5zdXJwcmlzaW5nbHksIHRoZXJlIGFyZSBtYW55ICJ0b29scyIgeW91IGNhbiB1c2UgaWYgeW91IHdhbnQgdG8gZGVsdmUgaW50byBnZW5lcmF0aXZlIGFydC4gSW4gY2FzZSB5b3Ugd2FudCB0byBoYXZlICoiaGFuZHMtb24iKiBleHBlcmllbmNlIGluIFIsIHRoZXJlIGFyZSB0d28gYmFzaWMgZGlyZWN0aW9ucyB5b3UgY2FuIGdvLgoKSWYgeW91IGFyZSBhIHBlcnNvbiBwcm9maWNpZW50IHdvcmtpbmcgd2l0aCBjb2RlLCB5b3UgbWF5IHdyaXRlIHlvdXIgY29kZSBzdHJhaWdodCBhd2F5LiBJIGRhcmUgdG8gYXJndWUgdGhhdCB0aGlzIGlzICoqdGhlIHdheSoqIG9mIHRoZSAq4oCcaW5kaXZpZHVhbOKAnSogZXhwcmVzc2lvbiBhcyBpdCBhbGxvd3MgZm9yIG1vcmUgZmxleGliaWxpdHksIGFuZCwgd2VsbCwgZnJlZWRvbS4KCkhvd2V2ZXIsIGdldHRpbmcgdG8gdGhhdCBwb2ludCB0YWtlcyB0aW1lLiBMdWNraWx5LCB5b3UgY2FuIGJlZ2luIGV4cGVyaW1lbnRpbmcgd2l0aCB5b3VyIHBpZWNlcyBvZiBnZW5lcmF0aXZlIGFydCBieSB1c2luZyBvbmUgb2YgdGhlIGV4aXN0aW5nIHBhY2thZ2VzLiBOb3Qgb25seSBpdCBjb3VsZCBiZSBxdWl0ZSByZXdhcmRpbmcsIGJ1dCBpdCBhbHNvIHdvcmtzIHBlcmZlY3RseSBmb3IgZ3Jhc3BpbmcgdGhlIGJhc2ljcyBvZiB0aGUgKiJ0cmFkZSIqLgoKSW4gdGhpcyBhcnRpY2xlLCBJIGFtIGdvaW5nIHRvIHByZXNlbnQgdG8geW91IHNvbWUgb2YgdGhlICoicmVhZHktdG8tdXNlIiogcGFja2FnZXMgZm9yIG1ha2luZyBnZW5lcmF0aXZlIGFydC4gQWxzbywgSSB3aWxsIHRhcCBpbnRvIHNvbWUgb2YgdGhlIGV4YW1wbGVzIG9mIHVzaW5nIGdlbmVyYWwgcGFja2FnZXMgb3IgbGlicmFyaWVzIHRvIGFycml2ZSBhdCB0aGUgc2FtZSBnb2FsLgoKIyMgZ2VuZXJhdGl2ZWFydAoKVGhlIGZpcnN0IHBhY2thZ2UgSSB3b3VsZCBsaWtlIHRvIHByZXNlbnQgaXMgY2FsbGVkIHNpbXBseSBgZ2VuZXJhdGl2ZWFydGAuCgpPbmUgb2YgaXRzIGtleSBmZWF0dXJlcyBpcyB0aGUgd2F5IGhvdyBpdCBzdHJ1Y3R1cmVzIHRoZSBvdXRwdXQgZmlsZXMuIEluIG9yZGVyIHRvIGdldCB0aGUgb3V0cHV0IGZpbGVzLCB5b3UgaGF2ZSB0byBzcGVjaWZ5IHRoZSBsb2NhdGlvbiB3aGVyZSBpdCB3aWxsIGJlIHN0b3JlZC4gQWxzbywgaXQgaXRlcmF0ZXMgb24gdGhlIHByb3ZpZGVkIGZvcm11bGEgdGhhdCBkb2Vzbid0IG5lZWQgdG8gYmUgc3VwcG9ydGVkIHdpdGggYSBzZWVkLiBJbiB0aGlzIHNjZW5hcmlvLCBlYWNoIG9mIHRoZSBvdXRjb21lIGZpbGVzIGlzIHVuaXF1ZS4gCgpBbHNvLCBpdCBpcyB3b3J0aCBtZW50aW9uaW5nIHRoYXQgdGhlIGBnZW5lcmF0aXZlYXJ0YCBwYWNrYWdlIGlzIHdlbGwgW2RvY3VtZW50ZWRdKGh0dHBzOi8vZ2l0aHViLmNvbS9jdXR0ZXJrb20vZ2VuZXJhdGl2ZWFydCkgYW5kIGVhc3kgdG8gdXNlLgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGVjaG89VFJVRSwgcmVzdWx0cz0naGlkZSd9CgpsaWJyYXJ5KGdlbmVyYXRpdmVhcnQpICMgZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJjdXR0ZXJrb20vZ2VuZXJhdGl2ZWFydCIpCmxpYnJhcnkoYW1iaWVudCkKbGlicmFyeShkcGx5cikKCiMgc2V0IHRoZSBwYXRocwpJTUdfRElSIDwtICJpbWcvIgpJTUdfU1VCRElSIDwtICJldmVyeXRoaW5nLyIKSU1HX1NVQkRJUjIgPC0gImhhbmRwaWNrZWQvIgpJTUdfUEFUSCA8LSBwYXN0ZTAoSU1HX0RJUiwgCiAgICAgICAgICAgICAgICAgICBJTUdfU1VCRElSKQoKTE9HRklMRV9ESVIgPC0gImxvZ2ZpbGUvIgpMT0dGSUxFIDwtICJsb2dmaWxlLmNzdiIKTE9HRklMRV9QQVRIIDwtIHBhc3RlMChMT0dGSUxFX0RJUiwgCiAgICAgICAgICAgICAgICAgICAgICAgTE9HRklMRSkKCiMgY3JlYXRlIHRoZSBkaXJlY3Rvcnkgc3RydWN0dXJlCmdlbmVyYXRpdmVhcnQ6OnNldHVwX2RpcmVjdG9yaWVzKElNR19ESVIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJTUdfU1VCRElSLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSU1HX1NVQkRJUjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMT0dGSUxFX0RJUikKCiMgaW5jbHVkZSBhIHNwZWNpZmljIGZvcm11bGEsIGZvciBleGFtcGxlOgpteV9mb3JtdWxhIDwtIGxpc3QoCiAgeCA9IHF1b3RlKHJ1bmlmKDEsIC0xLCAxMCkgKiB4X2leMiAtIHNpbih5X2leMikpLAogIHkgPSBxdW90ZShydW5pZigxLCAtMSwgMTApICogeV9pXjMgLSBjb3MoeF9pXjIpICogeV9pXjQpCikKCiMgY2FsbCB0aGUgbWFpbiBmdW5jdGlvbiB0byBjcmVhdGUgZml2ZSBpbWFnZXMgd2l0aCBhIHBvbGFyIGNvb3JkaW5hdGUgc3lzdGVtCmdlbmVyYXRpdmVhcnQ6OmdlbmVyYXRlX2ltZyhmb3JtdWxhID0gbXlfZm9ybXVsYSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBucl9vZl9pbWcgPSA1LCAjIHNldCB0aGUgbnVtYmVyIG9mIGl0ZXJhdGlvbnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvbGFyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxldHlwZSA9ICJwbmciLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiNjMWEwNmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3IgPSAiIzFhMzY1NyIpCmBgYAoKYGBge3IgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDYsIGZpZy5hbGlnbj0nY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGVjaG89RkFMU0V9CiMgYW4gZXhhbXBsZQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL2hvbWUvdml0Z2FicmhlbC9EZXNrdG9wL0dpdC9XZWJwYWdlL2RhdGFtdXN0Zmxvd19SL2ltZy9ldmVyeXRoaW5nLzIwMjAtMDYtMjEtMjEtMTVfc2VlZF84NDQ3LnBuZyIpCmBgYAoKCiMjIGphc21pbmVzCgpEYW5pZWxsZSBOYXZhcnJvLCB0aGUgYXV0aG9yIG9mIHRoZSBMZWFybmluZyBTdGF0aXN0aWNzIHdpdGggUiBbTGVhcm5pbmcgU3RhdGlzdGljcyB3aXRoIFJdKGh0dHBzOi8vbGVhcm5pbmdzdGF0aXN0aWNzd2l0aHIuY29tLykgaGFuZGJvb2ssIGlzIGEgd2VsbC1rbm93biBwZXJzb24gYW1vbmcgcHN5Y2hvbG9neSBzdHVkZW50cy4KCkJlc2lkZXMgaGVyIHRlYWNoaW5nIGFuZCByZXNlYXJjaCBhY3Rpdml0aWVzIGF0IHRoZSBVbml2ZXJzaXR5IG9mIEFkZWxhaWRlLCBzaGUgYWxzbyByZWxlYXNlZCB0aGUgW2phc21pbmVzXShodHRwczovL2dpdGh1Yi5jb20vZGpuYXZhcnJvL2phc21pbmVzKSBwYWNrYWdlLCBhIHRvb2wgYWxsb3dpbmcgZm9yIGNyZWF0aW5nIGEgZ2VuZXJhdGl2ZSBhcnQgaW4gUi4KClRoaXMgcGFja2FnZSBnaXZlcyB5b3UgYW4gb3Bwb3J0dW5pdHkgdG8gcGxheSB3aXRoIHNpbXVsYXRpb24gcGFyYW1ldGVycyAoZS5nLiBgZ3JhaW5gIG9yIGBpbnRlcmFjdGlvbmApLCBzaGFwZXMgKGUuZy4gYGVudGl0eV9jaXJjbGVgIG9yIGBzY2VuZV9kaXNjc2ApIGFuZCB0aGVpciBtb2RpZmljYXRpb25zIChsaWtlIGBzdHlsZV9yaWJib25gKSBvciBjb2xvdXJzIChgcGFsZXR0ZWAgb3IgYGFscGhhYCkuIEFuZCBub2lzZSwgbGlua2VkIHRvIHRoZSBbYW1iaWVudF0oaHR0cHM6Ly9naXRodWIuY29tL3Rob21hc3A4NS9hbWJpZW50KSBsaWJyYXJ5LgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGVjaG89VFJVRSwgcmVzdWx0cz0naGlkZSd9CmxpYnJhcnkoZHBseXIpICMgb3IgaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKSBmaXJzdApsaWJyYXJ5KGphc21pbmVzKSAjIG9yIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZGpuYXZhcnJvL2phc21pbmVzIikKCnAwIDwtIHVzZV9zZWVkKDEwMCkgJT4lICMgU2V0IHRoZSBzZWVkIG9mIFLigJhzIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yLCB3aGljaCBpcyB1c2VmdWwgZm9yIGNyZWF0aW5nIHNpbXVsYXRpb25zIG9yIHJhbmRvbSBvYmplY3RzIHRoYXQgY2FuIGJlIHJlcHJvZHVjZWQuCiAgc2NlbmVfZGlzY3MoCiAgICByaW5ncyA9IDEwLCAKICAgIHBvaW50cyA9IDUwMDAwLCAKICAgIHNpemUgPSA1MAogICkgJT4lCiAgbXV0YXRlKGluZCA9IDE6bigpKSAlPiUKICB1bmZvbGRfd2FycCgKICAgIGl0ZXJhdGlvbnMgPSAxMCwKICAgIHNjYWxlID0gLjUsIAogICAgb3V0cHV0ID0gImxheWVyIiAKICApICU+JQogIHVuZm9sZF90ZW1wZXN0KAogICAgaXRlcmF0aW9ucyA9IDUsCiAgICBzY2FsZSA9IC4wMQogICkgJT4lCiAgc3R5bGVfcmliYm9uKAogICAgY29sb3IgPSAiI0UwNTQyRSIsCiAgICBjb2xvdXIgPSAiaW5kIiwKICAgIGFscGhhID0gYygxLDEpLAogICAgYmFja2dyb3VuZCA9ICIjNEQ3MTg2IgogICkKCmdnc2F2ZSgicDAucG5nIiwgcDAsIHdpZHRoID0gMjAsIGhlaWdodCA9IDIwLCB1bml0cyA9ICJpbiIpCmBgYAoKYGBge3IgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDYsIGZpZy5hbGlnbj0nY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGVjaG89RkFMU0V9CiMgYW4gZXhhbXBsZQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL2hvbWUvdml0Z2FicmhlbC9EZXNrdG9wL0dpdC9XZWJwYWdlL2RhdGFtdXN0Zmxvd19SL3AwLnBuZyIpCmBgYAoKIyMgbWF0aGFydCArIGdnYXJ0CgpUaGUgYG1hdGhhcnRgIHBhY2thZ2Ugd3JhcHMgbWFueSBvZiBjb21tb25seSB1c2VkIGFsZ29yaXRobXMgaW50byBmdW5jdGlvbnMuIE9uZSBvZiBzdWNoIGV4YW1wbGVzIGlzIHRoZSBbbmVhcmVzdCBuZWlnaGJvciBncmFwaF0oaHR0cHM6Ly9naXRodWIuY29tL21hcmN1c3ZvbHovbWF0aGFydC9ibG9iL21hc3Rlci9SL2tfbmVhcmVzdF9uZWlnaGJvdXJfZ3JhcGguUiksIGEgdmlzdWFsaXNhdGlvbiBvZiB0aGUgW2stZCB0cmVlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9LLWRfdHJlZSksIGEgZGF0YSBzdHJ1Y3R1cmluZyBwcm9jZWR1cmUgb2YgbXVsdGlkaW1lbnNpb25hbCBzcGFjZTogIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGVjaG89VFJVRSwgcmVzdWx0cz0naGlkZSd9CgpsaWJyYXJ5KG1hdGhhcnQpICMgZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJtYXJjdXN2b2x6L21hdGhhcnQiKQpsaWJyYXJ5KGdnYXJ0KSAjIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigibWFyY3Vzdm9sei9nZ2FydCIpCmxpYnJhcnkoZ2dmb3JjZSkKbGlicmFyeShSY3BwKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKCnBvaW50cyA8LSBtYXRoYXJ0Ojpwb2ludHMKCnJlc3VsdCA8LSBrZHRyZWUocG9pbnRzKQoKcDEgPC0gZ2dwbG90KCkgKwogIGdlb21fc2VnbWVudChhZXMoeCwgeSwgeGVuZCA9IHhlbmQsIHllbmQgPSB5ZW5kKSwgcmVzdWx0KSArCiAgY29vcmRfZXF1YWwoKSArCiAgeGxpbSgwLCAxMDAwMCkgKyB5bGltKDAsIDEwMDAwKSArCiAgdGhlbWVfYmxhbmtjYW52YXMoYmdfY29sID0gIiNmYWZhZmEiLCBtYXJnaW5fY20gPSAwKQoKIyBzYXZlIHBsb3QKZ2dzYXZlKCJrZHRyZWUucG5nIiwgcDEsIHdpZHRoID0gMjAsIGhlaWdodCA9IDIwLCB1bml0cyA9ICJpbiIpCmBgYAoKYGBge3IgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDYsIGZpZy5hbGlnbj0nY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGVjaG89RkFMU0V9CiMgYW4gZXhhbXBsZQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL2hvbWUvdml0Z2FicmhlbC9EZXNrdG9wL0dpdC9XZWJwYWdlL2RhdGFtdXN0Zmxvd19SL2tkdHJlZS5wbmciKQpgYGAKCjxicj4KCmBtYXRoYXJ0YCBpcyBhIHdlbGwtZG9jdW1lbnRlZCBwYWNrYWdlLiBUaGlzIGZhY3Qgd2lkZW5zIHRoZSBzY29wZSBmb3IgZXhwZXJpbWVudGluZy4gTWF5YmUgbW9yZSBpbXBvcnRhbnRseSwgYnkgbG9va2luZyAqInVuZGVyIHRoZSBob29kIiosIHRoZSBwYWNrYWdlIGltcHJvdmVzIHVuZGVyc3RhbmRpbmcgb2YgZGF0YSBzaW11bGF0aW9uLgoKIyMgR2VuZXJhbCBwdXJwb3NlIHBhY2thZ2VzCgpJbiBtYW55IGluc3RhbmNlcywgcHJldmlvdXNseSBtZW50aW9uZWQgcGFja2FnZXMgYnVpbHQgb24gbW9yZSBnZW5lcmFsbHkgdXNlZCBwYWNrYWdlcyBzdWNoIGFzIGBtYWdyaXRyYCAodGhlIHBpcGVsaW5lIG9wZXJhdG9yIGNvbWVzIGhhbmR5IGV2ZW4gaW4gdGhlIGFydCBjcmVhdGlvbiksIGBnZ3Bsb3RgLCBgZHBseXJgLCBvciBgcHVycmAuCgpUaGUgKiprLWQgdHJlZSoqIGZyb20gdGhlIGBtYXRoYXJ0YCBwYWNrYWdlIGlzIG5vIGRpZmZlcmVudC4gQXMgd2UgY2FuIHNlZSBmcm9tIHRoZSBleGFtcGxlIG9mIFtNYXJjdXMgVm9sel0oaHR0cHM6Ly9naXRodWIuY29tL21hcmN1c3ZvbHovbWV0cm9wb2xpcy9ibG9iL21hc3Rlci9tZXRyb3BvbGlzLlIpLCB0aGUgb3JpZ2luYWwgay1kIHRyZWUgYWxnb3JpdGhtIGNhbiBiZSB0d2Vha2VkIHVzaW5nIGV2ZW4gYmFzZSBSOgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGVjaG89VFJVRSwgcmVzdWx0cz0naGlkZSd9CiMgTWV0cm9wb2xpczogR2VuZXJhdGl2ZSBjaXR5IHZpc3VhbGlzYXRpb25zCgojIFBhY2thZ2VzCmxpYnJhcnkoZ2dhcnQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHR3ZWVucikKbGlicmFyeSh2aXJpZGlzKQoKIyBNYWtlIHJlcHJvZHVjaWJsZQpzZXQuc2VlZCgxMDAwMSkKCiMgUGFyYW1ldGVycwpuIDwtIDEwMDAwICMgaXRlcmF0aW9ucwpyIDwtIDc1ICMgbmVpZ2hib3VyaG9vZAp3aWR0aCA8LSAxMDAwMCAjIGNhbnZhcyB3aWR0aApoZWlnaHQgPC0gMTAwMDAgIyBjYW52YXMgaGVpZ2h0CmRlbHRhIDwtIDIgKiBwaSAvIDE4MCAjIGFuZ2xlIGRpcmVjdGlvbiBub2lzZQpwX2JyYW5jaCA8LSAwLjEgIyBwcm9iYWJpbGl0eSBvZiBicmFuY2hpbmcKaW5pdGlhbF9wdHMgPC0gMyAjIG51bWJlciBvZiBpbml0aWFsIHBvaW50cwpuZnJhbWVzIDwtIDUwMCAjIG51bWJlciBvZiB0d2VlbnIgZnJhbWVzCgojIEluaXRpYWxpc2UgZGF0YSBmcmFtZXMKcG9pbnRzIDwtIGRhdGEuZnJhbWUoeCA9IG51bWVyaWMobiksIHkgPSBudW1lcmljKG4pLCBkaXIgPSBudW1lcmljKG4pLCBsZXZlbCA9IGludGVnZXIobikpCmVkZ2VzIDwtICBkYXRhLmZyYW1lKHggPSBudW1lcmljKG4pLCB5ID0gbnVtZXJpYyhuKSwgeGVuZCA9IG51bWVyaWMobiksIHllbmQgPSBudW1lcmljKG4pLCBsZXZlbCA9IGludGVnZXIobikpCgppZihpbml0aWFsX3B0cyA+IDEpIHsKICBpIDwtIDIKICB3aGlsZShpIDw9IGluaXRpYWxfcHRzKSB7CiAgICBwb2ludHNbaSwgXSA8LSBjKHJ1bmlmKDEsIDAsIHdpZHRoKSwgcnVuaWYoMSwgMCwgaGVpZ2h0KSwgcnVuaWYoMSwgLTIqcGksIDIqcGkpLCAxKQogICAgaSA8LSBpICsgMQogIH0KfQoKdDAgPC0gU3lzLnRpbWUoKQoKIyBNYWluIGxvb3AgLS0tLQppIDwtIGluaXRpYWxfcHRzICsgMQp3aGlsZSAoaSA8PSBuKSB7CiAgdmFsaWQgPC0gRkFMU0UKICB3aGlsZSAoIXZhbGlkKSB7CiAgICByYW5kb21fcG9pbnQgPC0gc2FtcGxlX24ocG9pbnRzW3NlcSgxOihpLTEpKSwgXSwgMSkgIyBQaWNrIGEgcG9pbnQgYXQgcmFuZG9tCiAgICBicmFuY2ggPC0gaWZlbHNlKHJ1bmlmKDEsIDAsIDEpIDw9IHBfYnJhbmNoLCBUUlVFLCBGQUxTRSkKICAgIGFscGhhIDwtIHJhbmRvbV9wb2ludCRkaXJbMV0gKyBydW5pZigxLCAtKGRlbHRhKSwgZGVsdGEpICsgKGJyYW5jaCAqIChpZmVsc2UocnVuaWYoMSwgMCwgMSkgPCAwLjUsIC0xLCAxKSAqIHBpLzIpKQogICAgdiA8LSBjKGNvcyhhbHBoYSksIHNpbihhbHBoYSkpICogciAqICgxICsgMSAvIGlmZWxzZShicmFuY2gsIHJhbmRvbV9wb2ludCRsZXZlbFsxXSsxLCByYW5kb21fcG9pbnQkbGV2ZWxbMV0pKSAjIENyZWF0ZSBkaXJlY3Rpb25hbCB2ZWN0b3IKICAgIHhqIDwtIHJhbmRvbV9wb2ludCR4WzFdICsgdlsxXQogICAgeWogPC0gcmFuZG9tX3BvaW50JHlbMV0gKyB2WzJdCiAgICBsdmwgPC0gcmFuZG9tX3BvaW50JGxldmVsWzFdCiAgICBsdmxfbmV3IDwtIGlmZWxzZShicmFuY2gsIGx2bCsxLCBsdmwpCiAgICBpZih4aiA8IDAgfCB4aiA+IHdpZHRoIHwgeWogPCAwIHwgeWogPiBoZWlnaHQpIHsKICAgICAgbmV4dAogICAgfQogICAgcG9pbnRzX2Rpc3QgPC0gcG9pbnRzICU+JSBtdXRhdGUoZCA9IHNxcnQoKHhqIC0geCleMiArICh5aiAtIHkpXjIpKQogICAgaWYgKG1pbihwb2ludHNfZGlzdCRkKSA+PSAxICogcikgewogICAgICBwb2ludHNbaSwgXSA8LSBjKHhqLCB5aiwgYWxwaGEsIGx2bF9uZXcpCiAgICAgIGVkZ2VzW2ksIF0gPC0gYyh4aiwgeWosIHJhbmRvbV9wb2ludCR4WzFdLCByYW5kb21fcG9pbnQkeVsxXSwgbHZsX25ldykKICAgICAgIyBBZGQgYSBidWlsZGluZyBpZiBwb3NzaWJsZQogICAgICBidWlkaW5nIDwtIDEKICAgICAgdmFsaWQgPC0gVFJVRQogICAgfQogIH0KICBpIDwtIGkgKyAxCiAgcHJpbnQoaSkKfQoKZWRnZXMgPC0gZWRnZXMgJT4lIGZpbHRlcihsZXZlbCA+IDApCgpzYW5kIDwtIGRhdGEuZnJhbWUoYWxwaGEgPSBudW1lcmljKDApLCB4ID0gbnVtZXJpYygwKSwgeSA9IG51bWVyaWMoMCkpCnBlcnAgPC0gZGF0YS5mcmFtZSh4ID0gbnVtZXJpYygwKSwgeSA9IG51bWVyaWMoMCksIHhlbmQgPSBudW1lcmljKDApLCB5ZW5kID0gbnVtZXJpYygwKSkKCiMgQ3JlYXRlIHBsb3QKcDIgPC0gZ2dwbG90KCkgKwogIGdlb21fc2VnbWVudChhZXMoeCwgeSwgeGVuZCA9IHhlbmQsIHllbmQgPSB5ZW5kLCBzaXplID0gLWxldmVsKSwgZWRnZXMsIGxpbmVlbmQgPSAicm91bmQiKSArCiAgI2dlb21fc2VnbWVudChhZXMoeCwgeSwgeGVuZCA9IHhlbmQsIHllbmQgPSB5ZW5kKSwgcGVycCwgbGluZWVuZCA9ICJyb3VuZCIsIGFscGhhID0gMC4xNSkgKwogICNnZW9tX3BvaW50KGFlcyh4LCB5KSwgcG9pbnRzKSArCiAgI2dlb21fcG9pbnQoYWVzKHgsIHkpLCBzYW5kLCBzaXplID0gMC4wNSwgYWxwaGEgPSAwLjA1LCBjb2xvdXIgPSAiYmxhY2siKSArCiAgeGxpbSgwLCAxMDAwMCkgKwogIHlsaW0oMCwgMTAwMDApICsKICBjb29yZF9lcXVhbCgpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuNSwgMC41KSkgKwogICNzY2FsZV9jb2xvcl92aXJpZGlzKCkgKwogIHRoZW1lX2JsYW5rY2FudmFzKGJnX2NvbCA9ICIjZmFmYWZhIiwgbWFyZ2luX2NtID0gMCkKCiMgcHJpbnQgcGxvdApnZ3NhdmUoInBsb3QwMDd3LnBuZyIsIHAyLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSAyMCwgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDApCmBgYAoKYGBge3IgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDYsIGZpZy5hbGlnbj0nY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGVjaG89RkFMU0V9CiMgYW4gZXhhbXBsZQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL2hvbWUvdml0Z2FicmhlbC9EZXNrdG9wL0dpdC9XZWJwYWdlL2RhdGFtdXN0Zmxvd19SL3Bsb3QwMDd3LnBuZyIpCmBgYAoKPGJyPgoKWW91IGRvbid0IG5lZWQgdG8gc3RvcCBoZXJlLiBTb21lIHRpbWUgc3BlbnQgb24gcGxheWluZyB3aXRoIHRoZSBjb2RlIGNhbiBlYXNpbHkgZW5kIHVwIGJ5IGNyZWF0aW5nIHlvdXIgZGlzdGluY3QgW3dhbGwgcG9zdGVyXShodHRwczovL3d3dy5yLWJsb2dnZXJzLmNvbS9nZW5lcmF0aXZlLWFydC1sZXQteW91ci1jb21wdXRlci1kZXNpZ24teW91LWEtcGFpbnRpbmcvKS4KCiMjIENsb3NpbmcgcmVtYXJrcwoKR2VuZXJhdGl2ZSBhcnQgZGVtb25zdHJhdGVzIHRoYXQgY29kZSBjYW4gYmUgYmVhdXRpZnVsLiBJZiB5b3UgYXJlIHN0aWxsIG5vdCBwZXJzdWFkZWQsIGdvIGFuZCBzZWUgbW9yZSBlbGFib3JhdGVkIHdvcmtzIGxpa2UgW3RoZXNlXShodHRwczovL3d3dy5kYXRhLWltYWdpbmlzdC5jb20vYXJ0KS4KCk5vdCBvbmx5IGNhbiBnZW5lcmF0aXZlIGFydCByZXN1bHQgaW4gc29tZXRoaW5nIGFzdG9uaXNoaW5nLCBidXQgaXQgYWxzbyBoZWxwcyB5b3UgdG8gdW5kZXJzdGFuZCB0aGUgY29kZSBpdHNlbGYuIEludGVyZXN0aW5nbHksIGdldHRpbmcgdG8gdGhlIGNvZGUgdW5kZXJseWluZyBnZW5lcmF0aXZlIGFydCBtYXkgbm90IGJlIGFzIGVhc3kgYXMgd2l0aCBvdGhlciBvcGVuLXNvdXJjZSBhcmVhcy4gU29tZSAqImdlbmVyYXRpdmUgYXJ0aXN0cyIqIGNvbmNsdWRlIG5vdCB0byBzaGFyZSB0aGUgY29kZSB1c2VkIGluIHRoZSBjcmVhdGl2ZSBwcm9jZXNzOgoKPiAqIkkgZG8gbm90IHNoYXJlIHRoZSBjb2RlIEkgdXNlIHRvIGNyZWF0ZSBteSBwaWVjZXMuIFRoZSBtYWluIHJlYXNvbiBmb3IgdGhpcyBpcyB0aGF0IEkgZG9u4oCZdCB0aGluayBpdCB3b3VsZCBiZSBiZW5lZmljaWFsIHRvIGFueW9uZS4gUGVvcGxlIGludGVyZXN0ZWQgaW4gZ2V0dGluZyBzdGFydGVkIHdpdGggZ2VuZXJhdGl2ZSBhcnQgd291bGQgYmVjb21lIHRvIGZvY3VzZWQgb24gbXkgaWRlYXMgaW5zdGVhZCBvZiBkZXZlbG9waW5nIHRoZWlyIG93bi4gS25vd2luZyB0aGUgYW5zd2VyIGlzIHRoZSBraWxsZXIgb2YgY3JlYXRpdml0eS4iKgoKPHAgc3R5bGU9InRleHQtYWxpZ246IHJpZ2h0OyI+VGhvbWFzIExpbiBQZWRlcnNlbiwgPGEgaHJlZj0iaHR0cHM6Ly93d3cuZGF0YS1pbWFnaW5pc3QuY29tL2FydCI+RGF0YSBJbWFnaW5pc3Q8L2E+PC9wPgoKPGJyPgpSZWdhcmRsZXNzIGlmIHdlIGFncmVlIG9yIG5vdCwgZ2VuZXJhdGl2ZSBhcnQgY29uZnJvbnRzIHVzIHdpdGggaWRlYXMgdGhhdCBhcmUgbm90IHRoYXQgY29tbW9uIGluIHRoZSB3b3JsZCBvZiBjb2RpbmcuCgpTbywgd2hhdCBhcmUgeW91ciBpZGVhcyBvbiB0aGUgbWF0dGVyPyBEbyB5b3UgaGF2ZSBhbnkgZmF2b3VyaXRlIGdlbmVyYXRpdmUgYXJ0aXN0cz8gT3IgbWF5YmUgeW91ciBwaWVjZXMgb2YgYXJ0IHlvdSB3b3VsZCBsaWtlIHRvIHNoYXJlPyBGZWVsIGZyZWUgdG8gZGlzY3VzcyBvbiBbKip0d2l0dGVyKipdKCkuCgombmJzcDsKJm5ic3A7CjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij48Yj5HbyBiYWNrIHRvIDxhIGhyZWY9Ii9wb3N0Ij5CbG9nPC9iPjwvYT48L3A+Cgo=