text: /* global require, describe, it */
  'use strict';
  
  // MODULES //
  
  var // Expectation library:
  	chai = require( 'chai' ),
  
  	// Matrix data structure:
  	matrix = require( 'dstructs-matrix' ),
  
  	// Validate a value is NaN:
  	isnan = require( 'validate.io-nan' ),
  
  	// Module to be tested:
  	pdf = require( './../lib' ),
  
  	// Error function:
  	PDF = require( './../lib/number.js' );
  
  
  // VARIABLES //
  
  var expect = chai.expect,
  	assert = chai.assert;
  
  
  // TESTS //
  
  describe( 'distributions-pareto-pdf', function tests() {
  
  	it( 'should export a function', function test() {
  		expect( pdf ).to.be.a( 'function' );
  	});
  
  	it( 'should throw an error if provided an invalid option', function test() {
  		var values = [
  			'5',
  			5,
  			true,
  			undefined,
  			null,
  			NaN,
  			[],
  			{}
  		];
  
  		for ( var i = 0; i < values.length; i++ ) {
  			expect( badValue( values[i] ) ).to.throw( TypeError );
  		}
  		function badValue( value ) {
  			return function() {
  				pdf( [1,2,3], {
  					'accessor': value
  				});
  			};
  		}
  	});
  
  	it( 'should throw an error if provided an array and an unrecognized/unsupported data type option', function test() {
  		var values = [
  			'beep',
  			'boop'
  		];
  
  		for ( var i = 0; i < values.length; i++ ) {
  			expect( badValue( values[i] ) ).to.throw( Error );
  		}
  		function badValue( value ) {
  			return function() {
  				pdf( [1,2,3], {
  					'dtype': value
  				});
  			};
  		}
  	});
  
  	it( 'should throw an error if provided a typed-array and an unrecognized/unsupported data type option', function test() {
  		var values = [
  			'beep',
  			'boop'
  		];
  
  		for ( var i = 0; i < values.length; i++ ) {
  			expect( badValue( values[i] ) ).to.throw( Error );
  		}
  		function badValue( value ) {
  			return function() {
  				pdf( new Int8Array([1,2,3]), {
  					'dtype': value
  				});
  			};
  		}
  	});
  
  	it( 'should throw an error if provided a matrix and an unrecognized/unsupported data type option', function test() {
  		var values = [
  			'beep',
  			'boop'
  		];
  
  		for ( var i = 0; i < values.length; i++ ) {
  			expect( badValue( values[i] ) ).to.throw( Error );
  		}
  		function badValue( value ) {
  			return function() {
  				pdf( matrix( [2,2] ), {
  					'dtype': value
  				});
  			};
  		}
  	});
  
  	it( 'should return NaN if the first argument is neither a number, array-like, or matrix-like', function test() {
  		var values = [
  			// '5', // valid as is array-like (length)
  			true,
  			undefined,
  			null,
  			// NaN, // allowed
  			function(){},
  			{}
  		];
  
  		for ( var i = 0; i < values.length; i++ ) {
  			assert.isTrue( isnan( pdf( values[ i ] ) ) );
  		}
  	});
  
  	it( 'should compute the Pareto pdf when provided a number', function test() {
  		assert.strictEqual( pdf( -1 ), 0 );
  		assert.strictEqual( pdf( 2, {
  			'alpha': 4,
  			'beta': 2
  		}), 2 );
  	});
  
  	it( 'should evaluate the Pareto pdf when provided a plain array', function test() {
  		var data, actual, expected, i;
  
  		data = [ 0, 1, 2, 3, 4, 5 ];
  		expected = [
  			0, 1, 1/4, 1/9, 1/16, 1/25
  		];
  
  		actual = pdf( data );
  		assert.notEqual( actual, data );
  
  		for ( i = 0; i < actual.length; i++ ) {
  			assert.closeTo( actual[ i ], expected[ i ], 1e-7 );
  		}
  
  		// Mutate...
  		actual = pdf( data, {
  			'copy': false
  		});
  		assert.strictEqual( actual, data );
  
  		for ( i = 0; i < actual.length; i++ ) {
  			assert.closeTo( data[ i ], expected[ i ], 1e-7 );
  		}
  	});
  
  	it( 'should evaluate the Pareto pdf when provided a typed array', function test() {
  		var data, actual, expected, i;
  
  		data = new Int8Array( [  0, 1, 2, 3, 4, 5 ] );
  
  		expected = new Float64Array([
  			0, 1, 1/4, 1/9, 1/16, 1/25
  		]);
  
  		actual = pdf( data );
  		assert.notEqual( actual, data );
  
  		for ( i = 0; i < actual.length; i++ ) {
  			assert.closeTo( actual[ i ], expected[ i ], 1e-7 );
  		}
  
  		// Mutate:
  		actual = pdf( data, {
  			'copy': false
  		});
  		expected = new Int8Array([
  			0, 1, 0, 0, 0, 0
  		]);
  		assert.strictEqual( actual, data );
  
  		for ( i = 0; i < actual.length; i++ ) {
  			assert.closeTo( data[ i ], expected[ i ], 1e-7 );
  		}
  	});
  
  	it( 'should evaluate the Pareto pdf element-wise and return an array of a specific type', function test() {
  		var data, actual, expected;
  
  		data = [ 0, 1, 2, 3, 4, 5 ];
  		expected = new Int8Array([
  			0, 1, 0, 0, 0, 0
  		]);
  
  		actual = pdf( data, {
  			'dtype': 'int8'
  		});
  
  		assert.notEqual( actual, data );
  		assert.strictEqual( actual.BYTES_PER_ELEMENT, 1 );
  		assert.deepEqual( actual, expected );
  	});
  
  	it( 'should evaluate the Pareto pdf element-wise using an accessor', function test() {
  		var data, actual, expected, i;
  
  		data = [
  			[0,0],
  			[1,1],
  			[2,2],
  			[3,3],
  			[4,4],
  			[5,5],
  			[6,6]
  		];
  
  		expected = [
  			0,
  			1,
  			1/4,
  			1/9,
  			1/16,
  			1/25,
  			1/36
  		];
  
  		actual = pdf( data, {
  			'accessor': getValue
  		});
  		assert.notEqual( actual, data );
  
  		for ( i = 0; i < actual.length; i++ ) {
  			assert.closeTo( actual[ i ], expected[ i ], 1e-7 );
  		}
  
  		// Mutate:
  		actual = pdf( data, {
  			'accessor': getValue,
  			'copy': false
  		});
  		assert.strictEqual( actual, data );
  
  		for ( i = 0; i < actual.length; i++ ) {
  			assert.closeTo( data[ i ], expected[ i ], 1e-7 );
  		}
  
  		function getValue( d ) {
  			return d[ 1 ];
  		}
  	});
  
  	it( 'should evaluate the Pareto pdf element-wise and deep set', function test() {
  		var data, actual, expected, i;
  
  		data = [
  			{'x':[9,0]},
  			{'x':[9,1]},
  			{'x':[9,2]},
  			{'x':[9,3]},
  			{'x':[9,4]},
  			{'x':[9,5]},
  			{'x':[9,6]},
  			{'x':[9,7]},
  			{'x':[9,8]},
  		];
  		expected = [
  			{'x':[9,0]},
  			{'x':[9,1]},
  			{'x':[9,1/4]},
  			{'x':[9,1/9]},
  			{'x':[9,1/16]},
  			{'x':[9,1/25]},
  			{'x':[9,1/36]},
  			{'x':[9,1/49]},
  			{'x':[9,1/64]},
  		];
  
  		actual = pdf( data, {
  			'path': 'x.1'
  		});
  
  		assert.strictEqual( actual, data );
  
  		for ( i = 0; i < actual.length; i++ ) {
  			assert.closeTo( data[ i ].x[ 1 ], expected[ i ].x[ 1 ], 1e-7 );
  		}
  
  		// Specify a path with a custom separator...
  		data = [
  			{'x':[9,0]},
  			{'x':[9,1]},
  			{'x':[9,2]},
  			{'x':[9,3]},
  			{'x':[9,4]},
  			{'x':[9,5]},
  			{'x':[9,6]},
  			{'x':[9,7]},
  			{'x':[9,8]},
  		];
  		actual = pdf( data, {
  			'path': 'x/1',
  			'sep': '/'
  		});
  		assert.strictEqual( actual, data );
  
  		for ( i = 0; i < actual.length; i++ ) {
  			assert.closeTo( actual[ i ].x[ 1 ], expected[ i ].x[ 1 ], 1e-7 );
  		}
  	});
  
  	it( 'should evaluate the Pareto pdf element-wise when provided a matrix', function test() {
  		var mat,
  			out,
  			d1,
  			d2,
  			i;
  
  		d1 = new Float64Array( 25 );
  		d2 = new Float64Array( 25 );
  		for ( i = 0; i < d1.length; i++ ) {
  			d1[ i ] = i / 5;
  			d2[ i ] = PDF( i / 5, 1, 1 );
  		}
  		mat = matrix( d1, [5,5], 'float64' );
  		out = pdf( mat );
  
  		assert.deepEqual( out.data, d2 );
  
  		// Mutate...
  		out = pdf( mat, {
  			'copy': false
  		});
  		assert.strictEqual( mat, out );
  		assert.deepEqual( mat.data, d2 );
  	});
  
  	it( 'should evaluate the Pareto pdf element-wise and return a matrix of a specific type', function test() {
  		var mat,
  			out,
  			d1,
  			d2,
  			i;
  
  		d1 = new Float64Array( 25 );
  		d2 = new Float32Array( 25 );
  		for ( i = 0; i < d1.length; i++ ) {
  			d1[ i ] = i / 5;
  			d2[ i ] = PDF( i / 5, 1, 1 );
  		}
  		mat = matrix( d1, [5,5], 'float64' );
  		out = pdf( mat, {
  			'dtype': 'float32'
  		});
  
  		assert.strictEqual( out.dtype, 'float32' );
  		assert.deepEqual( out.data, d2 );
  	});
  
  	it( 'should return an empty data structure if provided an empty data structure', function test() {
  		assert.deepEqual( pdf( [] ), [] );
  		assert.deepEqual( pdf( matrix( [0,0] ) ).data, new Float64Array() );
  		assert.deepEqual( pdf( new Int8Array() ), new Float64Array() );
  	});
  
  });
  