'use strict' module.exports = gradient var dup = require('dup') var cwiseCompiler = require('cwise-compiler') var TEMPLATE_CACHE = {} var GRADIENT_CACHE = {} var EmptyProc = { body: "", args: [], thisVars: [], localVars: [] } var centralDiff = cwiseCompiler({ args: [ 'array', 'array', 'array' ], pre: EmptyProc, post: EmptyProc, body: { args: [ { name: 'out', lvalue: true, rvalue: false, count: 1 }, { name: 'left', lvalue: false, rvalue: true, count: 1 }, { name: 'right', lvalue: false, rvalue: true, count: 1 }], body: "out=0.5*(left-right)", thisVars: [], localVars: [] }, funcName: 'cdiff' }) var zeroOut = cwiseCompiler({ args: [ 'array' ], pre: EmptyProc, post: EmptyProc, body: { args: [ { name: 'out', lvalue: true, rvalue: false, count: 1 }], body: "out=0", thisVars: [], localVars: [] }, funcName: 'zero' }) function generateTemplate(d) { if(d in TEMPLATE_CACHE) { return TEMPLATE_CACHE[d] } var code = [] for(var i=0; i= 0) { pickStr.push('0') } else if(facet.indexOf(-(i+1)) >= 0) { pickStr.push('s['+i+']-1') } else { pickStr.push('-1') loStr.push('1') hiStr.push('s['+i+']-2') } } var boundStr = '.lo(' + loStr.join() + ').hi(' + hiStr.join() + ')' if(loStr.length === 0) { boundStr = '' } if(cod > 0) { code.push('if(1') for(var i=0; i= 0 || facet.indexOf(-(i+1)) >= 0) { continue } code.push('&&s[', i, ']>2') } code.push('){grad', cod, '(src.pick(', pickStr.join(), ')', boundStr) for(var i=0; i= 0 || facet.indexOf(-(i+1)) >= 0) { continue } code.push(',dst.pick(', pickStr.join(), ',', i, ')', boundStr) } code.push(');') } for(var i=0; i1){dst.set(', pickStr.join(), ',', bnd, ',0.5*(src.get(', cPickStr.join(), ')-src.get(', dPickStr.join(), ')))}else{dst.set(', pickStr.join(), ',', bnd, ',0)};') } else { code.push('if(s[', bnd, ']>1){diff(', outStr, ',src.pick(', cPickStr.join(), ')', boundStr, ',src.pick(', dPickStr.join(), ')', boundStr, ');}else{zero(', outStr, ');};') } break case 'mirror': if(cod === 0) { code.push('dst.set(', pickStr.join(), ',', bnd, ',0);') } else { code.push('zero(', outStr, ');') } break case 'wrap': var aPickStr = pickStr.slice() var bPickStr = pickStr.slice() if(facet[i] < 0) { aPickStr[bnd] = 's[' + bnd + ']-2' bPickStr[bnd] = '0' } else { aPickStr[bnd] = 's[' + bnd + ']-1' bPickStr[bnd] = '1' } if(cod === 0) { code.push('if(s[', bnd, ']>2){dst.set(', pickStr.join(), ',', bnd, ',0.5*(src.get(', aPickStr.join(), ')-src.get(', bPickStr.join(), ')))}else{dst.set(', pickStr.join(), ',', bnd, ',0)};') } else { code.push('if(s[', bnd, ']>2){diff(', outStr, ',src.pick(', aPickStr.join(), ')', boundStr, ',src.pick(', bPickStr.join(), ')', boundStr, ');}else{zero(', outStr, ');};') } break default: throw new Error('ndarray-gradient: Invalid boundary condition') } } if(cod > 0) { code.push('};') } } //Enumerate ridges, facets, etc. of hypercube for(var i=0; i<(1<