'use strict';
var utils = require('./utils');
var jStat = require('jstat').jStat;

function scaleToRate(scale) {
    scale = scale || 1;
    return 1 / scale;
}

function convertProbability(probability) {
    var errorMsg;
    if (probability <= 0 || probability >= 1) {
        errorMsg = [
            'probability must be in range [0,1]: `',
            probability,
            '` given'
        ].join('');
        throw new Error(errorMsg);
    }

    return 1 - (2 * probability);
}

function convertDistrubution(expX, probability, mean) {
    mean = mean || 0;
    return expX * utils.sign(probability - 0.5) + mean;
}

/**
 * calculate the inverse Laplace CDN at the given location
 * @param  {number} probability a number between 0 and 1
 * @param  {number} scale of the CDN (defaults to 1)
 * @param  {number} mean of the CDN (default to 0)
 * @return {number}   The inverse transform of the CDN at location
 */
function inverseCdn(probability, scale, mean) {
    var rate = scaleToRate(scale);
    var expProbability = convertProbability(probability);
    var expX = jStat.exponential.inv(expProbability, rate);
    return convertDistrubution(expX, probability, mean);
}

/**
 * sample from the Laplace inverse CDN
 * @param  {number} scale the scale of the CDN (defaults to 1)
 * @param  {number} mean  the mean of the CDN (defaults to 0)
 * @return {number}       random sample from Laplace CDN
 */
function sampleInverseCdn(scale, mean) {
    var probability = Math.random();
    var rate =  scaleToRate(scale);
    var expX = jStat.exponential.sample(rate);
    return convertDistrubution(expX, probability, mean);
}

/**
 * calculate random Laplace noise. Assumes CDN has a mean of 0
 * @param  {number} scale the scale of the CDN (defaults to 1)
 * @return {number}       the noise
 */
function noise(scale) {
    return sampleInverseCdn(scale);
}

module.exports = {
    inverse: inverseCdn,
    sampleInverse: sampleInverseCdn,
    noise: noise
};

@@ -80,86 +80,489 @@
 t;%0A%0A
-function scaleToRate(scale) %7B%0A    scale = scale %7C%7C 1;%0A    return 1 / scale;%0A%7D%0A
+/**%0A * Convert Laplace CDF scale to exponential CDF rate (lambda)%0A * @param  %7Bnumber%7D scale the Laplace CDF scale%0A * @return %7Bnumber%7D       the exponential CDF rate (lamdba)%0A */%0Afunction scaleToRate(scale) %7B%0A    scale = scale %7C%7C 1;%0A    return 1 / scale;%0A%7D%0A%0A/**%0A * Convert a Laplace CDF probability to an Exponential CDF probability%0A * @param  %7Bnumber%7D probability the Laplace probability (between 0, 1)%0A * @return %7Bnumber%7D             the Exponential probability (between 0, 1)%0A */
 %0Afun
@@ -861,16 +861,25 @@
  return 
+Math.abs(
 1 - (2 *
@@ -891,21 +891,333 @@
 ability)
+)
 ;%0A%7D%0A%0A
+/**%0A * convert Exponential CDF value (x) to Laplace CDF value%0A * @param  %7Bnumber%7D expX        the exponential CDF value%0A * @param  %7Bnumber%7D probability the laplace probability of the CDF value%0A * @param  %7Bnumber%7D mean        the mean of the Laplace CDF%0A * @return %7Bnumber%7D             The Laplace CDF value%0A */%0A
 function
@@ -1658,17 +1658,17 @@
 nverseCd
-n
+f
 (probabi
@@ -2150,25 +2150,25 @@
 pleInverseCd
-n
+f
 (scale, mean
@@ -2212,91 +2212,8 @@
 ();%0A
-    var rate =  scaleToRate(scale);%0A    var expX = jStat.exponential.sample(rate);%0A
     
@@ -2223,34 +2223,19 @@
 urn 
-co
+i
 nver
-tDistrubution(expX, 
+seCdf(
 prob
@@ -2234,32 +2234,39 @@
 Cdf(probability,
+ scale,
  mean);%0A%7D%0A%0A/**%0A 
@@ -2480,17 +2480,17 @@
 nverseCd
-n
+f
 (scale);
@@ -2530,25 +2530,25 @@
 e: inverseCd
-n
+f
 ,%0A    sample
@@ -2571,17 +2571,17 @@
 nverseCd
-n
+f
 ,%0A    no

add doc blocks