docs: function midsummary( arr, n, opts ) {
  	if ( !Array.isArray( arr ) ) {
  		throw new TypeError( 'midsummary()::invalid input argument. Must provide an array.' );
  	}
  	if ( typeof n !== 'number' || n !== n ) {
  		throw new TypeError( 'midsummary()::invalid input argument. Percentage must be numeric.' );
  	}
  	if ( n < 0.0 || n > 0.50 ) {
  		throw new TypeError( 'midsummary()::invalid input argument. Must provide a percentage between 0 and 0.5 inclusive.' );
  	}
  	if ( arguments.length > 2 ) {
  		if ( !isObject( opts ) ) {
  			throw new TypeError( 'midsummary()::invalid input argument. Options should be an object.' );
  		}
  	} else {
  		opts = {
  			'sorted': false
  		};
  	}
  	if ( !opts.sorted ) {
  		arr = arr.slice();
  		arr.sort( ascending );
  		opts.sorted = true;
  	}
  	var len = arr.length,
  		el = 0;
  
  	if ( n === 0 ) {
  		// special case: midrange
  		return ( arr[0] + arr[len-1] ) / 2.0;
  	}
  	else if ( n === 0.5 ) {
  		// special case: median
  		el = Math.floor( len / 2.0 );
   		if ( len % 2.0 ) {
   			// Middle index exists
   			return arr[ el ];
   		}
   		else {
   			return ( arr[ el ] + arr[ el-1 ] ) / 2.0;
   		}
  	}	
  	else {
  		return ( quantile( arr, n, opts ) + quantile( arr, 1 - n, opts ) ) / 2.0;
  	}
  }