Skip to content

Commit

Permalink
Use cached stencil functions, add opts.buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
hughsk committed Jul 16, 2013
1 parent b06d81e commit d9335aa
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 16 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Takes an ndarray and prepares it for cave generation. Options include:
* `iterations`: The amount of iterations to apply immediately. Defaults to 0.
* `border`: If truthy, will include a solid border around the results.
Defaults to 1.
* `buffer`: An ndarray buffer to use between iterations, which must be the same
shape as the original array. If none is supplied, one will be created.

Note that this function will modify the array directly.

Expand Down
57 changes: 41 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,49 @@ var fill = require('ndarray-fill')
var zero = require('zeros')

var neighbors = neighborhood.length
var stencils = {}

module.exports = generate

// ndarray-stencil generates code using cwise, and as
// such incurs a slight performance hit initially.
// To work around this, we can keep two cached functions
// which use shared parameters. See `iterator` for more info.
var sharedWidth = null
var sharedHeight = null
var sharedBorder = null
var sharedThreshold = null

stencils.vanilla = stencil(neighborhood, function(p1,p2,p3,p4,p5,p6,p7,p8,p9,pos) {
return (
p1+p2+p3+p4+p5+p6+p7+p8+p9 >= sharedThreshold
) ? 1 : 0
}, { useIndex: false })

stencils.border = stencil(neighborhood, function(p1,p2,p3,p4,p5,p6,p7,p8,p9,pos) {
return (
p1+p2+p3+p4+p5+p6+p7+p8+p9 >= sharedThreshold ||
pos[0] < sharedBorder ||
pos[0] > sharedWidth - sharedBorder - 3 ||
pos[1] < sharedBorder ||
pos[1] > sharedHeight - sharedBorder - 3
) ? 1 : 0
}, { useIndex: true })

function generate(array, opts) {
opts = opts || {}

var width = array.shape[0]
, height = array.shape[1]
, buffer = zero([ width, height ])
, buffer = opts.buffer || zero([ width, height ])

var density = opts.density || 0.5
, threshold = opts.threshold || 5
, border = 'border' in opts ? opts.border : 1
, hood = opts.hood || 1
, shouldFill = 'fill' in opts ? opts.fill : true
, iterate = stencils[
border ? 'border' : 'vanilla'
]

if (shouldFill) fill(array, function(x, y) {
return Math.random() <= density || (
Expand All @@ -26,27 +55,23 @@ function generate(array, opts) {
) ? 1 : 0
})

var iterate = border ? stencil(neighborhood, function(p1,p2,p3,p4,p5,p6,p7,p8,p9,pos) {
return (
p1+p2+p3+p4+p5+p6+p7+p8+p9 >= threshold ||
pos[0] < border ||
pos[0] > width - border - 3 ||
pos[1] < border ||
pos[1] > height - border - 3
) ? 1 : 0
}, { useIndex: true }) : stencil(neighborhood, function(p1,p2,p3,p4,p5,p6,p7,p8,p9,pos) {
return (
p1+p2+p3+p4+p5+p6+p7+p8+p9 >= threshold
) ? 1 : 0
}, { useIndex: true })

if (opts.iterations) {
iterator(opts.iterations)
}

return iterator

// Updates the shared variables that are available
// on the module-level scope. This is a synchronous
// operation, so it's totally safe (though not
// necessarily pretty) provided these values are
// updated before any iteration.
function iterator(iterations) {
sharedWidth = width
sharedHeight = height
sharedBorder = border
sharedThreshold = threshold

iterations = iterations || 1

for (var i = 0; i < iterations; i += 1) {
Expand Down

0 comments on commit d9335aa

Please sign in to comment.