/** * Implementation of Dynamic Markov Compression, using byte-oriented * nodes/transitions. * * Currently no model-shrinking is done, so be careful trying to use * this on large inputs! * * Notes for the future / TO DO: * * Add node merging to Dmc: * - once (total states traversed / total node count) exceeds a certain value * - find the median node w/rt total visits * - combine all nodes w/ less visits into a single node, with transitions * to node[0] - node[255] (initial context-1 states) * - initially transition counts are zero? or summed from components? * needs to be summed so kirchoff principle holds * - halve the edge counts of all nodes, to provide for adaptation * - enforce property that all nodes point "higher" except for * links to nodes 0-255. So we can resum all nodes in one pass, * after resetting all node.sum to zero. X YES because we know * what the total sum must be, so we can arrange to scale to maintain * proper sum. XXX what about node 0-255? XXX maybe just clear all * edge counts XXX * * Fix buglet: ensure that kirchoff principle *exactly* holds by * paying attention to rounding when we distribute edge counts. track * highest edge and give (desiredSum - newSum) extra counts to that * outgoing edge? add one to each nonzero edge until all gone? * * Split 'to' nodes when to.sum grows too high -- only if we're * highest incoming edge? Fix bug again here with saturating counts; * we can't ignore counts w/o violating kirchoff principle, so we need * to clone it. Maybe start trying to clone early (before our counter * saturates) so we have a better chance of cloning on the high * incoming edge? XXX we don't track incoming edges. XXX so just * clone when we visit. */ if (typeof define !== 'function') { var define = require('amdefine')(module); } define(['./MTFModel', './RangeCoder', './Stream', './Util'],function(MTFModel, RangeCoder, Stream, Util){ // nm = no model cloning, MAX_TRANS_CNT=0xFF, MAX_MODEL_PROB=0xFFFF // nm2 = " 0xFFFF 0xFFFF // nm3 = " 0xFFF 0x0FFF // nm4 = " 0xFFFF 0xFF // cl1 = model cloning, MAX_TRANS_CNT=0xFFFF MAX_MODEL_PROB=0xFF // cl2 = model cloning, MAX_TRANS_CNT= 0xFF MAX_MODEL_PROB=0xFF // cl3 = model cloning, MAX_TRANS_CNT=0xFFFF MAX_MODEL_PROB=0xFFFF var MAX_TRANS_CNT = 0xFFFF; var DEFAULT_MIN_CNT1 = 8; var DEFAULT_MIN_CNT2 = 128; var MODEL_PROB_MAX = 0xFF00; var MODEL_PROB_INCR= 0x0100; var CLONE_MODELS=false; var PRINT_STATS=false; // for quick benchmarking // XXX need to limit growth of model (throw away and retrain if model // gets too large) var Dmc = Object.create(null); Dmc.MAGIC = 'dmc!'; var MarkovNode = function(coder, size, optModel) { this.out = []; this.model = optModel ? optModel.clone() : new MTFModel(coder, size, MODEL_PROB_MAX, MODEL_PROB_INCR); this.count = Util.makeU16Buffer(size); this.sum = 0; }; MarkovNode.prototype.clone = function(coder, size) { var i; var newNode = new MarkovNode(coder, size, CLONE_MODELS ? this.model : null); for (i=0; i