tsuki 0.4.8

Lua 5.4 ported to Rust
Documentation
#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut
)]
#![allow(unsafe_op_in_unsafe_fn)]

use crate::lapi::{
    lua_compare, lua_createtable, lua_gettop, lua_isinteger, lua_newuserdatauv, lua_pushboolean,
    lua_pushinteger, lua_pushnil, lua_pushnumber, lua_pushstring, lua_pushvalue, lua_setfield,
    lua_tointegerx, lua_touserdata, lua_type,
};
use crate::lauxlib::{
    luaL_Reg, luaL_argerror, luaL_checkany, luaL_checkinteger, luaL_checknumber, luaL_error,
    luaL_optinteger, luaL_optnumber, luaL_setfuncs,
};
use crate::{Thread, lua_settop};
use libc::time;
use libm::{
    acos, asin, atan2, ceil, cos, exp, fabs, floor, fmod, log, log2, log10, sin, sqrt, tan,
};
use std::boxed::Box;
use std::ffi::c_int;
use std::ptr::null_mut;

#[derive(Copy, Clone)]
#[repr(C)]
struct RanState {
    s: [libc::c_ulong; 4],
}

unsafe extern "C" fn rotl(mut x: libc::c_ulong, mut n: libc::c_int) -> libc::c_ulong {
    return x << n | (x & 0xffffffffffffffff as libc::c_ulong) >> 64 as libc::c_int - n;
}

unsafe extern "C" fn nextrand(mut state: *mut libc::c_ulong) -> libc::c_ulong {
    let mut state0: libc::c_ulong = *state.offset(0 as libc::c_int as isize);
    let mut state1: libc::c_ulong = *state.offset(1 as libc::c_int as isize);
    let mut state2: libc::c_ulong = *state.offset(2 as libc::c_int as isize) ^ state0;
    let mut state3: libc::c_ulong = *state.offset(3 as libc::c_int as isize) ^ state1;
    let mut res: libc::c_ulong = (rotl(
        state1.wrapping_mul(5 as libc::c_int as libc::c_ulong),
        7 as libc::c_int,
    ))
    .wrapping_mul(9 as libc::c_int as libc::c_ulong);
    *state.offset(0 as libc::c_int as isize) = state0 ^ state3;
    *state.offset(1 as libc::c_int as isize) = state1 ^ state2;
    *state.offset(2 as libc::c_int as isize) = state2 ^ state1 << 17 as libc::c_int;
    *state.offset(3 as libc::c_int as isize) = rotl(state3, 45 as libc::c_int);
    return res;
}

unsafe extern "C" fn I2d(mut x: libc::c_ulong) -> f64 {
    let mut sx: libc::c_long = ((x & 0xffffffffffffffff as libc::c_ulong)
        >> 64 as libc::c_int - 53 as libc::c_int) as libc::c_long;
    let mut res: f64 = sx as f64
        * (0.5f64
            / ((1 as libc::c_int as libc::c_ulong) << 53 as libc::c_int - 1 as libc::c_int)
                as libc::c_double);
    if sx < 0 as libc::c_int as libc::c_long {
        res += 1.0f64;
    }
    return res;
}

unsafe extern "C" fn project(mut ran: u64, mut n: u64, mut state: *mut RanState) -> u64 {
    if n & n.wrapping_add(1 as libc::c_int as u64) == 0 as libc::c_int as u64 {
        return ran & n;
    } else {
        let mut lim: u64 = n;
        lim |= lim >> 1 as libc::c_int;
        lim |= lim >> 2 as libc::c_int;
        lim |= lim >> 4 as libc::c_int;
        lim |= lim >> 8 as libc::c_int;
        lim |= lim >> 16 as libc::c_int;
        lim |= lim >> 32 as libc::c_int;
        loop {
            ran &= lim;
            if !(ran > n) {
                break;
            }
            ran =
                (nextrand(((*state).s).as_mut_ptr()) & 0xffffffffffffffff as libc::c_ulong) as u64;
        }
        return ran;
    };
}

unsafe fn math_random(mut L: *const Thread) -> Result<c_int, Box<dyn std::error::Error>> {
    let mut low: i64 = 0;
    let mut up: i64 = 0;
    let mut p: u64 = 0;
    let mut state: *mut RanState = lua_touserdata(
        L,
        -(1000000 as libc::c_int) - 1000 as libc::c_int - 1 as libc::c_int,
    ) as *mut RanState;
    let mut rv: libc::c_ulong = nextrand(((*state).s).as_mut_ptr());
    match lua_gettop(L) {
        0 => {
            lua_pushnumber(L, I2d(rv));
            return Ok(1 as libc::c_int);
        }
        1 => {
            low = 1 as libc::c_int as i64;
            up = luaL_checkinteger(L, 1 as libc::c_int)?;
            if up == 0 as libc::c_int as i64 {
                lua_pushinteger(L, (rv & 0xffffffffffffffff as libc::c_ulong) as u64 as i64);
                return Ok(1 as libc::c_int);
            }
        }
        2 => {
            low = luaL_checkinteger(L, 1 as libc::c_int)?;
            up = luaL_checkinteger(L, 2 as libc::c_int)?;
        }
        _ => {
            return luaL_error(L, "wrong number of arguments");
        }
    }
    (((low <= up) as libc::c_int != 0 as libc::c_int) as libc::c_int as libc::c_long != 0
        || luaL_argerror(L, 1 as libc::c_int, "interval is empty")? != 0) as libc::c_int;
    p = project(
        (rv & 0xffffffffffffffff as libc::c_ulong) as u64,
        (up as u64).wrapping_sub(low as u64),
        state,
    );
    lua_pushinteger(L, p.wrapping_add(low as u64) as i64);
    return Ok(1 as libc::c_int);
}

unsafe fn setseed(mut L: *const Thread, mut state: *mut libc::c_ulong, mut n1: u64, mut n2: u64) {
    let mut i: libc::c_int = 0;
    *state.offset(0 as libc::c_int as isize) = n1 as libc::c_ulong;
    *state.offset(1 as libc::c_int as isize) = 0xff as libc::c_int as libc::c_ulong;
    *state.offset(2 as libc::c_int as isize) = n2 as libc::c_ulong;
    *state.offset(3 as libc::c_int as isize) = 0 as libc::c_int as libc::c_ulong;
    i = 0 as libc::c_int;
    while i < 16 as libc::c_int {
        nextrand(state);
        i += 1;
    }
    lua_pushinteger(L, n1 as i64);
    lua_pushinteger(L, n2 as i64);
}

unsafe fn randseed(mut L: *const Thread, mut state: *mut RanState) {
    let mut seed1: u64 = time(null_mut()) as u64;
    let mut seed2: u64 = L as usize as u64;
    setseed(L, ((*state).s).as_mut_ptr(), seed1, seed2);
}

unsafe fn math_randomseed(mut L: *const Thread) -> Result<c_int, Box<dyn std::error::Error>> {
    let mut state: *mut RanState = lua_touserdata(
        L,
        -(1000000 as libc::c_int) - 1000 as libc::c_int - 1 as libc::c_int,
    ) as *mut RanState;
    if lua_type(L, 1 as libc::c_int) == -(1 as libc::c_int) {
        randseed(L, state);
    } else {
        let mut n1: i64 = luaL_checkinteger(L, 1 as libc::c_int)?;
        let mut n2: i64 = luaL_optinteger(L, 2 as libc::c_int, 0 as libc::c_int as i64)?;
        setseed(L, ((*state).s).as_mut_ptr(), n1 as u64, n2 as u64);
    }
    return Ok(2 as libc::c_int);
}

static mut randfuncs: [luaL_Reg; 3] = [
    {
        let mut init = luaL_Reg {
            name: b"random\0" as *const u8 as *const libc::c_char,
            func: Some(math_random),
        };
        init
    },
    {
        let mut init = luaL_Reg {
            name: b"randomseed\0" as *const u8 as *const libc::c_char,
            func: Some(math_randomseed),
        };
        init
    },
];

unsafe fn setrandfunc(mut L: *const Thread) -> Result<(), Box<dyn std::error::Error>> {
    let state = lua_newuserdatauv(L, ::core::mem::size_of::<RanState>(), 0) as *mut RanState;
    randseed(L, state);
    lua_settop(L, -(2 as libc::c_int) - 1 as libc::c_int)?;
    luaL_setfuncs(L, &raw const randfuncs as *const luaL_Reg, 1 as libc::c_int)?;
    Ok(())
}

static mut mathlib: [luaL_Reg; 28] = [
    {
        let mut init = luaL_Reg {
            name: b"random\0" as *const u8 as *const libc::c_char,
            func: None,
        };
        init
    },
    {
        let mut init = luaL_Reg {
            name: b"randomseed\0" as *const u8 as *const libc::c_char,
            func: None,
        };
        init
    },
];

pub unsafe fn luaopen_math(mut L: *const Thread) -> Result<c_int, Box<dyn std::error::Error>> {
    lua_createtable(
        L,
        0 as libc::c_int,
        (::core::mem::size_of::<[luaL_Reg; 28]>() as libc::c_ulong)
            .wrapping_div(::core::mem::size_of::<luaL_Reg>() as libc::c_ulong)
            .wrapping_sub(1 as libc::c_int as libc::c_ulong) as libc::c_int,
    );
    luaL_setfuncs(L, &raw const mathlib as *const luaL_Reg, 0 as libc::c_int)?;
    setrandfunc(L)?;
    return Ok(1 as libc::c_int);
}