From 42f15f000be95b06240b155de5a8d2afb0791288 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 30 May 2013 19:55:09 +0200 Subject: [PATCH] Add ol.structs.Buffer#getSplit32 --- src/ol/structs/buffer.js | 57 +++++++++++++++++++++++++++++ test/spec/ol/structs/buffer.test.js | 39 ++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/ol/structs/buffer.js b/src/ol/structs/buffer.js index bc049f7a08..65178cfb0c 100644 --- a/src/ol/structs/buffer.js +++ b/src/ol/structs/buffer.js @@ -22,6 +22,12 @@ ol.structs.BufferUsage = { ol.BUFFER_REPLACE_UNUSED_ENTRIES_WITH_NANS = goog.DEBUG; +/** + * @typedef {{high: Float32Array, low: Float32Array}} + */ +ol.structs.BufferSplit32; + + /** * @constructor @@ -62,6 +68,18 @@ ol.structs.Buffer = function(opt_arr, opt_used, opt_usage) { } } + /** + * @private + * @type {?ol.structs.BufferSplit32} + */ + this.split32_ = null; + + /** + * @private + * @type {ol.structs.IntegerSet} + */ + this.split32DirtySet_ = null; + /** * @private * @type {number} @@ -146,6 +164,45 @@ ol.structs.Buffer.prototype.getFreeSet = function() { }; +/** + * Splits this buffer into two Float32Arrays. + * @see http://blogs.agi.com/insight3d/index.php/2008/09/03/precisions-precisions/ + * @return {ol.structs.BufferSplit32} Split. + */ +ol.structs.Buffer.prototype.getSplit32 = function() { + var arr = this.arr_; + var n = arr.length; + if (goog.isNull(this.split32DirtySet_)) { + this.split32DirtySet_ = new ol.structs.IntegerSet([0, n]); + this.addDirtySet(this.split32DirtySet_); + } + if (goog.isNull(this.split32_)) { + this.split32_ = { + high: new Float32Array(n), + low: new Float32Array(n) + }; + } + var split32 = this.split32_; + this.split32DirtySet_.forEachRange(function(start, stop) { + var doubleHigh, i, value; + for (i = start; i < stop; ++i) { + value = arr[i]; + if (value < 0) { + doubleHigh = 65536 * Math.floor(-value / 65536); + split32.high[i] = -doubleHigh; + split32.low[i] = value + doubleHigh; + } else { + doubleHigh = 65536 * Math.floor(value / 65536); + split32.high[i] = doubleHigh; + split32.low[i] = value - doubleHigh; + } + } + }); + this.split32DirtySet_.clear(); + return this.split32_; +}; + + /** * @return {number} Usage. */ diff --git a/test/spec/ol/structs/buffer.test.js b/test/spec/ol/structs/buffer.test.js index 2e3710cfa3..956364c706 100644 --- a/test/spec/ol/structs/buffer.test.js +++ b/test/spec/ol/structs/buffer.test.js @@ -220,6 +220,45 @@ describe('ol.structs.Buffer', function() { }); + describe('with a populated instance', function() { + + var b; + beforeEach(function() { + b = new ol.structs.Buffer([1234567.1234567, -7654321.7654321]); + }); + + describe('getSplit32', function() { + + it('returns the expected value', function() { + var split32 = b.getSplit32(); + expect(split32.high).to.be.a(Float32Array); + expect(split32.low).to.be.a(Float32Array); + expect(split32.high).to.have.length(2); + expect(split32.low).to.have.length(2); + expect(split32.high[0]).to.roughlyEqual(1179648.0, 1e1); + expect(split32.low[0]).to.roughlyEqual(54919.12345670001, 1e-2); + expect(split32.high[1]).to.roughlyEqual(-7602176.0, 1e1); + expect(split32.low[1]).to.roughlyEqual(-52145.76543209981, 1e-2); + }); + + it('tracks updates', function() { + b.getSplit32(); + b.getArray()[0] = 0; + b.markDirty(1, 0); + var split32 = b.getSplit32(); + expect(split32.high).to.be.a(Float32Array); + expect(split32.low).to.be.a(Float32Array); + expect(split32.high).to.have.length(2); + expect(split32.low).to.have.length(2); + expect(split32.high[0]).to.be(0); + expect(split32.low[0]).to.be(0); + expect(split32.high[1]).to.roughlyEqual(-7602176.0, 1e1); + expect(split32.low[1]).to.roughlyEqual(-52145.76543209981, 1e-2); + }); + + }); + }); + describe('usage tests', function() { it('allows multiple adds and removes', function() {