// This is part of Leandro Motta Barros' DUMP project
// http://stackedboxes.org/2020/01/05/dump-of-unsorted-morsels-for-programmers/
// Code is licensed under the MIT license
//
//
// Copyright 2017-2020 Leandro Motta Barros
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

let polarMethodNormalRNG_haveSpare = false;
let polarMethodNormalRNG_spare = 0.0;

function polarMethodNormalRNG(): number {
    if (polarMethodNormalRNG_haveSpare/**/ && dump.data.get("ignoreSpare") !== true/**/) {
        polarMethodNormalRNG_haveSpare = false;
        return polarMethodNormalRNG_spare;
    }
    let u0, u1, s: number;
    
    dump.data.set("first", true); // __DUMP_HIDE__
    do {
        u0 = Math.random() * 2.0 - 1.0;
        u1 = Math.random() * 2.0 - 1.0;
        s = u0*u0 + u1*u1;
        if (dump.data.get("first") === true) {   // __DUMP_HIDE__
            dump.data.set("first", false);       // __DUMP_HIDE__
            dump.data.set("in", s > 0 && s < 1); // __DUMP_HIDE__
            dump.data.set("before", [u0, u1]);   // __DUMP_HIDE__
        }                                        // __DUMP_HIDE__
    } while (s >= 1 || s == 0);
    let m = Math.sqrt(-2.0 * Math.log(s) / s);
    let z0 = u0 * m;
    let z1 = u1 * m;
    dump.data.set("after", [z0, z1]); // __DUMP_HIDE__
    polarMethodNormalRNG_haveSpare = true;
    polarMethodNormalRNG_spare = z1;
    
    return z0;
}
