// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Copyright (C) Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// This file incorporates work covered by the following copyright and permission
// notice:
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
//
//===----------------------------------------------------------------------===//

#ifndef _ONEDPL_RANDOM
#define _ONEDPL_RANDOM

#include "oneapi/dpl/internal/common_config.h"
#include "oneapi/dpl/pstl/onedpl_config.h"
#include "oneapi/dpl/pstl/hetero/dpcpp/sycl_defs.h"
#include <utility>
#include <cstdint>
#include <type_traits>
#include <limits>

#include "internal/random_impl/random_common.h"
#include "internal/random_impl/linear_congruential_engine.h"
#include "internal/random_impl/subtract_with_carry_engine.h"
#include "internal/random_impl/discard_block_engine.h"
#include "internal/random_impl/philox_engine.h"
#include "internal/random_impl/uniform_real_distribution.h"
#include "internal/random_impl/uniform_int_distribution.h"
#include "internal/random_impl/normal_distribution.h"
#include "internal/random_impl/exponential_distribution.h"
#include "internal/random_impl/bernoulli_distribution.h"
#include "internal/random_impl/geometric_distribution.h"
#include "internal/random_impl/weibull_distribution.h"
#include "internal/random_impl/lognormal_distribution.h"
#include "internal/random_impl/cauchy_distribution.h"
#include "internal/random_impl/extreme_value_distribution.h"

namespace oneapi
{
namespace dpl
{

// Engines and engine adaptors with predefined parameters
using minstd_rand0 = linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647>;
using minstd_rand = linear_congruential_engine<uint_fast32_t, 48271, 0, 2147483647>;
using default_engine = minstd_rand;
using ranlux24_base = subtract_with_carry_engine<uint_fast32_t, 24, 10, 24>;
using ranlux48_base = subtract_with_carry_engine<uint_fast64_t, 48, 5, 12>;
using ranlux24 = discard_block_engine<ranlux24_base, 223, 23>;
using ranlux48 = discard_block_engine<ranlux48_base, 389, 11>;
namespace experimental
{
using philox4x32 = philox_engine<uint_fast32_t, 32, 4, 10, 0xCD9E8D57, 0x9E3779B9, 0xD2511F53, 0xBB67AE85>;
using philox4x64 = philox_engine<uint_fast64_t, 64, 4, 10, 0xCA5A826395121157, 0x9E3779B97F4A7C15, 0xD2E7470EE14C6C93,
                                 0xBB67AE8584CAA73B>;
} // namespace experimental

// Non-standard engines and engine adaptors with predefined parameters
template <int _N>
using minstd_rand0_vec = linear_congruential_engine<sycl::vec<uint_fast32_t, _N>, 16807, 0, 2147483647>;
template <int _N>
using minstd_rand_vec = linear_congruential_engine<sycl::vec<uint_fast32_t, _N>, 48271, 0, 2147483647>;

template <int _N>
using ranlux24_base_vec = subtract_with_carry_engine<sycl::vec<uint_fast32_t, _N>, 24, 10, 24>;
template <int _N>
using ranlux48_base_vec = subtract_with_carry_engine<sycl::vec<uint_fast64_t, _N>, 48, 5, 12>;

template <int _N>
using ranlux24_vec = discard_block_engine<ranlux24_base_vec<_N>, 223, 23>;
template <int _N>
using ranlux48_vec = discard_block_engine<ranlux48_base_vec<_N>, 389, 11>;

namespace experimental
{
template <int _N>
using philox4x32_vec =
    philox_engine<sycl::vec<uint_fast32_t, _N>, 32, 4, 10, 0xCD9E8D57, 0x9E3779B9, 0xD2511F53, 0xBB67AE85>;

template <int _N>
using philox4x64_vec = philox_engine<sycl::vec<uint_fast64_t, _N>, 64, 4, 10, 0xCA5A826395121157, 0x9E3779B97F4A7C15,
                                     0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B>;
} // namespace experimental

} // namespace dpl
} // namespace oneapi

namespace dpl = oneapi::dpl;

#endif // _ONEDPL_RANDOM
