@@ -177,21 +177,22 @@ Experiment.defaults =
177177} ;
178178
179179Regression = Utilities . createClass (
180- function ( samples , getComplexity , getFrameLength , startIndex , endIndex , options )
180+ // `samples` is [ [ complexity, frameLength ], [ complexity, frameLength ], ... ]
181+ // All samples are analyzed. startIndex, endIndex are just stored for use by the caller.
182+ function ( samples , startIndex , endIndex , options )
181183 {
182184 const desiredFrameLength = options . desiredFrameLength ;
183185 var profile ;
184186
185187 if ( ! options . preferredProfile || options . preferredProfile == Strings . json . profiles . slope ) {
186- profile = this . _calculateRegression ( samples , getComplexity , getFrameLength , startIndex , endIndex , {
188+ profile = this . _calculateRegression ( samples , {
187189 shouldClip : true ,
188190 s1 : desiredFrameLength ,
189191 t1 : 0
190192 } ) ;
191193 this . profile = Strings . json . profiles . slope ;
192- }
193- else if ( options . preferredProfile == Strings . json . profiles . flat ) {
194- profile = this . _calculateRegression ( samples , getComplexity , getFrameLength , startIndex , endIndex , {
194+ } else if ( options . preferredProfile == Strings . json . profiles . flat ) {
195+ profile = this . _calculateRegression ( samples , {
195196 shouldClip : true ,
196197 s1 : desiredFrameLength ,
197198 t1 : 0 ,
@@ -233,11 +234,14 @@ Regression = Utilities.createClass(
233234 //
234235 // x is assumed to be complexity, y is frame length. Can be used for pure complexity-FPS
235236 // analysis or for ramp controllers since complexity monotonically decreases with time.
236- _calculateRegression : function ( samples , getComplexity , getFrameLength , startIndex , endIndex , options )
237+ _calculateRegression : function ( samples , options )
237238 {
238- if ( startIndex == endIndex ) {
239+ const complexityIndex = 0 ;
240+ const frameLengthIndex = 1 ;
241+
242+ if ( samples . length == 1 ) {
239243 // Only one sample point; we can't calculate any regression.
240- var x = getComplexity ( samples , startIndex ) ;
244+ var x = samples [ 0 ] [ complexityIndex ] ;
241245 return {
242246 complexity : x ,
243247 s1 : x ,
@@ -249,17 +253,19 @@ Regression = Utilities.createClass(
249253 } ;
250254 }
251255
256+ // Sort by increasing complexity.
257+ var sortedSamples = samples . slice ( ) . sort ( ( a , b ) => a [ complexityIndex ] - b [ complexityIndex ] ) ;
258+
252259 // x is expected to increase in complexity
253- var iterationDirection = endIndex > startIndex ? 1 : - 1 ;
254- var lowComplexity = getComplexity ( samples , startIndex ) ;
255- var highComplexity = getComplexity ( samples , endIndex ) ;
260+ var lowComplexity = sortedSamples [ 0 ] [ complexityIndex ] ;
261+ var highComplexity = sortedSamples [ samples . length - 1 ] [ complexityIndex ] ;
262+
256263 var a1 = 0 , b1 = 0 , c1 = 0 , d1 = 0 , h1 = 0 , k1 = 0 ;
257264 var a2 = 0 , b2 = 0 , c2 = 0 , d2 = 0 , h2 = 0 , k2 = 0 ;
258265
259- // Iterate from low to high complexity
260- for ( var i = startIndex ; iterationDirection * ( endIndex - i ) > - 1 ; i += iterationDirection ) {
261- var x = getComplexity ( samples , i ) ;
262- var y = getFrameLength ( samples , i ) ;
266+ for ( var i = 0 ; i < sortedSamples . length ; ++ i ) {
267+ var x = sortedSamples [ i ] [ complexityIndex ] ;
268+ var y = sortedSamples [ i ] [ frameLengthIndex ] ;
263269 a2 += 1 ;
264270 b2 += x ;
265271 c2 += x * x ;
@@ -279,9 +285,9 @@ Regression = Utilities.createClass(
279285 t2_best = t2 ;
280286 error2_best = error2 ;
281287 // Number of samples included in the first segment, inclusive of splitIndex
282- n1_best = iterationDirection * ( splitIndex - startIndex ) + 1 ;
288+ n1_best = splitIndex + 1 ;
283289 // Number of samples included in the second segment
284- n2_best = iterationDirection * ( endIndex - splitIndex ) ;
290+ n2_best = samples . length - splitIndex - 1 ;
285291 if ( ! options . shouldClip || ( x_prime >= lowComplexity && x_prime <= highComplexity ) )
286292 x_best = x_prime ;
287293 else {
@@ -290,21 +296,21 @@ Regression = Utilities.createClass(
290296 }
291297 }
292298
293- // Iterate from startIndex to endIndex - 1 , inclusive
294- for ( var i = startIndex ; iterationDirection * ( endIndex - i ) > 0 ; i += iterationDirection ) {
295- var x = getComplexity ( samples , i ) ;
296- var y = getFrameLength ( samples , i ) ;
299+ // Iterate from 0 to n - 2 , inclusive
300+ for ( var i = 0 ; i < sortedSamples . length - 1 ; ++ i ) {
301+ var x = sortedSamples [ i ] [ complexityIndex ] ;
302+ var y = sortedSamples [ i ] [ frameLengthIndex ] ;
297303 var xx = x * x ;
298304 var yx = y * x ;
299305 var yy = y * y ;
300- // a1, b1, etc. is sum from startIndex to i, inclusive
306+ // a1, b1, etc. is sum from 0 to i, inclusive
301307 a1 += 1 ;
302308 b1 += x ;
303309 c1 += xx ;
304310 d1 += y ;
305311 h1 += yx ;
306312 k1 += yy ;
307- // a2, b2, etc. is sum from i+1 to endIndex , inclusive
313+ // a2, b2, etc. is sum from i+1 to sortedSamples.length - 1 , inclusive
308314 a2 -= 1 ;
309315 b2 -= x ;
310316 c2 -= xx ;
@@ -328,7 +334,7 @@ Regression = Utilities.createClass(
328334 var error1 = ( k1 + a1 * s1 * s1 + c1 * t1 * t1 - 2 * d1 * s1 - 2 * h1 * t1 + 2 * b1 * s1 * t1 ) || Number . MAX_VALUE ;
329335 var error2 = ( k2 + a2 * s2 * s2 + c2 * t2 * t2 - 2 * d2 * s2 - 2 * h2 * t2 + 2 * b2 * s2 * t2 ) || Number . MAX_VALUE ;
330336
331- if ( i == startIndex ) {
337+ if ( i == 0 ) {
332338 setBest ( s1 , t1 , error1 , s2 , t2 , error2 , i , x_prime , x ) ;
333339 continue ;
334340 }
@@ -337,7 +343,8 @@ Regression = Utilities.createClass(
337343 continue ;
338344
339345 // Projected point is not between this and the next sample
340- if ( x_prime > getComplexity ( samples , i + iterationDirection ) || x_prime < x ) {
346+ var nextSampleComplexity = sortedSamples [ i + 1 ] [ complexityIndex ] ;
347+ if ( x_prime > nextSampleComplexity || x_prime < x ) {
341348 // Calculate lambda, which divides the weight of this sample between the two lines
342349
343350 // These values remove the influence of this sample
0 commit comments