[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/WhyNot135/daScript/master/src/builtin/module_builtin_math.cpp [Back]  [Original]

#include "daScript/misc/platform.h"

#include "module_builtin.h"

#include "daScript/simulate/simulate_nodes.h"
#include "daScript/ast/ast_interop.h"
#include "daScript/ast/ast_policy_types.h"
#include "daScript/ast/ast_simulate.h"
#include "daScript/ast/ast_handle.h"
#include "daScript/simulate/sim_policy.h"
#include "daScript/simulate/aot_builtin_math.h"
#include "daScript/simulate/simulate_visit_op.h"
#include "daScript/misc/performance_time.h"

namespace das {
#define MATH_FUN_OP1(fun)\
      DEFINE_POLICY(fun);\
      IMPLEMENT_OP1_FUNCTION_POLICY(fun,Float,float);  \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, float2); \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, float3); \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, float4);

#define MATH_FUN_OP1_INT(fun)\
      DEFINE_POLICY(fun);\
      IMPLEMENT_OP1_FUNCTION_POLICY_EX(fun,Int,int32_t,Float,float);\
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, float2); \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, float3); \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, float4);

#define MATH_FUN_OP2(fun)\
      DEFINE_POLICY(fun);\
      IMPLEMENT_OP2_FUNCTION_POLICY(fun,Float,float);  \
      IMPLEMENT_OP2_EVAL_FUNCTION_POLICY(fun, float2); \
      IMPLEMENT_OP2_EVAL_FUNCTION_POLICY(fun, float3); \
      IMPLEMENT_OP2_EVAL_FUNCTION_POLICY(fun, float4);

#define MATH_FUN_OP1I(fun)\
      DEFINE_POLICY(fun);\
      IMPLEMENT_OP1_FUNCTION_POLICY(fun,Int,int32_t); \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, int2);  \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, int3);  \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, int4);  \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, uint2); \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, uint3); \
      IMPLEMENT_OP1_EVAL_FUNCTION_POLICY(fun, uint4);

#define MATH_FUN_OP2I(fun)\
      IMPLEMENT_OP2_FUNCTION_POLICY(fun,Int,int32_t); \
      IMPLEMENT_OP2_EVAL_FUNCTION_POLICY(fun, int2);  \
      IMPLEMENT_OP2_EVAL_FUNCTION_POLICY(fun, int3);  \
      IMPLEMENT_OP2_EVAL_FUNCTION_POLICY(fun, int4);  \
      IMPLEMENT_OP2_EVAL_FUNCTION_POLICY(fun, uint2); \
      IMPLEMENT_OP2_EVAL_FUNCTION_POLICY(fun, uint3); \
      IMPLEMENT_OP2_EVAL_FUNCTION_POLICY(fun, uint4);

#define MATH_FUN_OP3I(fun)\
      IMPLEMENT_OP3_FUNCTION_POLICY(fun,Int,int32_t); \
      IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(fun, int2);  \
      IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(fun, int3);  \
      IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(fun, int4);  \
      IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(fun, uint2); \
      IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(fun, uint3); \
      IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(fun, uint4);

#define MATH_FUN_OP3(fun)\
      DEFINE_POLICY(fun);\
      IMPLEMENT_OP3_FUNCTION_POLICY(fun,Float,float);  \
      IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(fun, float2); \
      IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(fun, float3); \
      IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(fun, float4);

#define MATH_FUN_OP1A(fun)                               \
    DEFINE_POLICY(fun);                                  \
    MATH_FUN_OP1(fun);                                   \
    MATH_FUN_OP1I(fun);                                  \
    IMPLEMENT_OP1_FUNCTION_POLICY(fun,UInt,uint32_t);    \
    IMPLEMENT_OP1_FUNCTION_POLICY(fun,Int64,int64_t);    \
    IMPLEMENT_OP1_FUNCTION_POLICY(fun,UInt64,uint64_t);  \
    IMPLEMENT_OP1_FUNCTION_POLICY(fun,Double,double);


#define MATH_FUN_OP2A(fun)                              \
    MATH_FUN_OP2(fun);                                  \
    MATH_FUN_OP2I(fun);                                 \
    IMPLEMENT_OP2_FUNCTION_POLICY(fun,UInt,uint32_t);   \
    IMPLEMENT_OP2_FUNCTION_POLICY(fun,Int64,int64_t);   \
    IMPLEMENT_OP2_FUNCTION_POLICY(fun,UInt64,uint64_t); \
    IMPLEMENT_OP2_FUNCTION_POLICY(fun,Double,double);

#define MATH_FUN_OP3A(fun)                              \
    MATH_FUN_OP3(fun);                                  \
    MATH_FUN_OP3I(fun);                                 \
    IMPLEMENT_OP3_FUNCTION_POLICY(fun,UInt,uint32_t);   \
    IMPLEMENT_OP3_FUNCTION_POLICY(fun,Int64,int64_t);   \
    IMPLEMENT_OP3_FUNCTION_POLICY(fun,UInt64,uint64_t); \
    IMPLEMENT_OP3_FUNCTION_POLICY(fun,Double,double);

    // everything
    MATH_FUN_OP2A(Min)
    MATH_FUN_OP2A(Max)
    MATH_FUN_OP3A(Clamp)
    MATH_FUN_OP1A(Sign)
    MATH_FUN_OP1A(Abs)

    //common
    MATH_FUN_OP1(Floor)
    MATH_FUN_OP1(Ceil)
    MATH_FUN_OP1(Fract)
    MATH_FUN_OP1(Round)
    MATH_FUN_OP1(Sqrt)
    MATH_FUN_OP1(RSqrt)
    MATH_FUN_OP1(RSqrtEst)
    MATH_FUN_OP1(Sat)
    MATH_FUN_OP3(Lerp)
    IMPLEMENT_OP3_FUNCTION_POLICY(Lerp,Double,double);
    //common - double
    IMPLEMENT_OP1_FUNCTION_POLICY(Floor,Double,double);
    IMPLEMENT_OP1_FUNCTION_POLICY(Ceil,Double,double);
    IMPLEMENT_OP1_FUNCTION_POLICY(Fract,Double,double);
    IMPLEMENT_OP1_FUNCTION_POLICY(Round,Double,double);
    IMPLEMENT_OP1_FUNCTION_POLICY(Sat,Double,double);

    // mad
    MATH_FUN_OP3A(Mad)

    MATH_FUN_OP1_INT(Trunci)
    MATH_FUN_OP1_INT(Floori)
    MATH_FUN_OP1_INT(Ceili)
    MATH_FUN_OP1_INT(Roundi)

    IMPLEMENT_OP1_FUNCTION_POLICY_EX(Trunci,Int,int32_t,Double,double);
    IMPLEMENT_OP1_FUNCTION_POLICY_EX(Floori,Int,int32_t,Double,double);
    IMPLEMENT_OP1_FUNCTION_POLICY_EX(Ceili,Int,int32_t,Double,double);
    IMPLEMENT_OP1_FUNCTION_POLICY_EX(Roundi,Int,int32_t,Double,double);

    //exp
    MATH_FUN_OP1(Exp)
    MATH_FUN_OP1(Log)
    MATH_FUN_OP1(Exp2)
    MATH_FUN_OP1(Log2)
    MATH_FUN_OP2(Pow)
    MATH_FUN_OP1(Rcp)
    MATH_FUN_OP1(RcpEst)

    //trig
    MATH_FUN_OP1(Sin)
    MATH_FUN_OP1(Cos)
    MATH_FUN_OP1(Tan)

    DEFINE_POLICY(MadS)     // vector_a*scalar_b + vector_c
    IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(MadS,float2);
    IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(MadS,float3);
    IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(MadS,float4);
    IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(MadS,int2);
    IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(MadS,int3);
    IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(MadS,int4);
    IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(MadS,uint2);
    IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(MadS,uint3);
    IMPLEMENT_OP3_EVAL_FUNCTION_POLICY(MadS,uint4);

    // trig types
    template 
    void addFunctionTrig(Module & mod, const ModuleLibrary & lib) {
        //                                    policy              ret   arg1 arg2     name
        mod.addFunction( (new BuiltInFn("sin",       lib, "Sin"))->arg("x") );
        mod.addFunction( (new BuiltInFn("cos",       lib, "Cos"))->arg("x") );
        mod.addFunction( (new BuiltInFn("tan",       lib, "Tan"))->arg("x") );
    }

    template 
    void addFunctionCommonTyped(Module & mod, const ModuleLibrary & lib) {
        //                                    policy              ret   arg1 arg2   name
        mod.addFunction( (new BuiltInFn("min",   lib, "Min"))->args({"x","y"}) );
        mod.addFunction( (new BuiltInFn("max",   lib, "Max"))->args({"x","y"}) );
        mod.addFunction( (new BuiltInFn("clamp", lib, "Clamp"))->args({"t","a","b"}) );
        mod.addFunction( (new BuiltInFn("abs",   lib, "Abs"))->arg("x") );
        mod.addFunction( (new BuiltInFn("sign",  lib, "Sign"))->arg("x") );
    }

    template 
    void addFunctionCommon(Module & mod, const ModuleLibrary & lib) {
        //                                    policy            ret   arg1     name
        mod.addFunction( (new BuiltInFn("floor",       lib, "Floor"))->arg("x") );
        mod.addFunction( (new BuiltInFn("ceil",        lib, "Ceil"))->arg("x") );
        mod.addFunction( (new BuiltInFn("fract",       lib, "Fract"))->arg("x") );
        mod.addFunction( (new BuiltInFn("round",       lib, "Round"))->arg("x") );
        mod.addFunction( (new BuiltInFn("sqrt",        lib, "Sqrt"))->arg("x") );
        mod.addFunction( (new BuiltInFn("rsqrt",       lib, "RSqrt"))->arg("x") );
        mod.addFunction( (new BuiltInFn("rsqrt_est",   lib, "RSqrtEst"))->arg("x") );
        mod.addFunction( (new BuiltInFn("saturate",    lib, "Sat"))->arg("x") );
    }
    template 
    void addFunctionCommonConversion(Module & mod, const ModuleLibrary & lib) {
        //                                    policy          ret    arg1     name
        mod.addFunction( (new BuiltInFn("floori",  lib, "Floori"))->arg("x") );
        mod.addFunction( (new BuiltInFn("ceili",   lib, "Ceili"))->arg("x") );
        mod.addFunction( (new BuiltInFn("roundi",  lib, "Roundi"))->arg("x") );
        mod.addFunction( (new BuiltInFn("trunci",  lib, "Trunci"))->arg("x") );
    }

    template 
    void addFunctionPow(Module & mod, const ModuleLibrary & lib) {
        //                                    policy           ret   arg1   name
        mod.addFunction( (new BuiltInFn("exp",      lib, "Exp"))->arg("x") );
        mod.addFunction( (new BuiltInFn("log",      lib, "Log"))->arg("x") );
        mod.addFunction( (new BuiltInFn("exp2",     lib, "Exp2"))->arg("x") );
        mod.addFunction( (new BuiltInFn("log2",     lib, "Log2"))->arg("x") );
        mod.addFunction( (new BuiltInFn("rcp",      lib, "Rcp"))->arg("x") );
        mod.addFunction( (new BuiltInFn("rcp_est",  lib, "RcpEst"))->arg("x") );
        mod.addFunction( (new BuiltInFn("pow",   lib, "Pow"))->args({"x","y"}) );
    }

    template 
    void addFunctionOp3i(Module & mod, const ModuleLibrary & lib) {
        //                                    policy         ret arg1 arg2 arg3   name
        mod.addFunction( (new BuiltInFn("mad",   lib, "Mad"))->args({"a","b","c"}) );
    }

    template 
    void addFunctionOp3(Module & mod, const ModuleLibrary & lib) {
        addFunctionOp3i(mod, lib);
        //                                    policy         ret arg1 arg2 arg3   name
        mod.addFunction( (new BuiltInFn("lerp",  lib, "Lerp"))->args({"a","b","t"}) );
    }

    template 
    class MatrixAnnotation : public ManagedStructureAnnotation {
        enum { ColC = sizeof(VecT) / sizeof(float) };
    public:
        MatrixAnnotation(ModuleLibrary & lib) :
            ManagedStructureAnnotation( "float" + to_string(ColC) + "x" + to_string(RowC), lib,
                 "float" + to_string(ColC) + "x" + to_string(RowC)) {
            const char * fieldNames [] = {"x","y","z","w"};
            for ( int r=0; r!=RowC; ++r ) {
                this->addFieldEx(fieldNames[r], "m[" + to_string(r) + "]", r*ColC*sizeof(float),
                    new TypeDecl(TypeDecl::getVectorType(Type::tFloat, ColC)));
            }
        }
        virtual bool isIndexable ( const TypeDeclPtr & decl ) const override {
            return decl->isIndex();
        }
        virtual TypeDeclPtr makeIndexType ( ExpressionPtr, ExpressionPtr idx ) const override {
            auto decl = idx->type;
            if ( !decl->isIndex() ) return nullptr;
            auto bt = TypeDecl::getVectorType(Type::tFloat, ColC);
            auto pt = new TypeDecl(bt);
            pt->ref = true;
            return pt;
        }
        SimNode * trySimulate ( Context & context, ExpressionPtr subexpr, ExpressionPtr index,
                               const TypeDeclPtr & r2vType, uint32_t ofs ) const {
            if ( index->rtti_isConstant() ) {
                // if its constant index, like a[3]..., we try to let node bellow simulate
                auto idxCE = static_cast(index);
                uint32_t idxC = cast::to(idxCE->value);
                if ( idxC >= RowC ) {
                    context.thisProgram->error("matrix index out of range", "", "",
                        subexpr->at, CompilationError::exceeds_array_index);
                    return nullptr;
                }
                uint32_t stride = sizeof(float)*ColC;
                auto tnode = trySimulateExpression(context, subexpr, idxC*stride + ofs, r2vType);
                if ( tnode ) {
                    return tnode;
                }
            }
            return nullptr;
        }
        virtual SimNode * simulateGetAt ( Context & context, const LineInfo & at, const TypeDeclPtr &,
                                         ExpressionPtr rv, ExpressionPtr idx, uint32_t ofs ) const override {
            gc_local none = new TypeDecl(Type::none);
            if ( auto tnode = trySimulate(context, rv, idx, none.ptr, ofs) ) {
                return tnode;
            } else {
                return context.code->makeNode(at,
                                                          simulateExpression(context, rv),
                                                          simulateExpression(context, idx),
                                                          uint32_t(sizeof(float)*ColC), ofs, RowC, "matrix[index]");
            }
        }
        virtual SimNode * simulateGetAtR2V ( Context & context, const LineInfo & at, const TypeDeclPtr & readType,
                                            ExpressionPtr rv, ExpressionPtr idx, uint32_t ofs ) const override {
            auto r2vType = readType->baseType;
            gc_local r2vTypeDecl = new TypeDecl(r2vType);
            if ( auto tnode = trySimulate(context, rv, idx, r2vTypeDecl.ptr, ofs) ) {
                return tnode;
            } else {
                return context.code->makeValueNode(  r2vType, at,
                                                                    simulateExpression(context, rv),
                                                                    simulateExpression(context, idx),
                                                                    uint32_t(sizeof(float)*ColC), ofs, RowC, "matrix[index]");
            }
        }
        virtual bool isRawPod() const override {
            return true;
        }
        virtual bool isPod() const override {
            return true;
        }
    };

    typedef MatrixAnnotation float4x4_ann;
    typedef MatrixAnnotation float3x4_ann;
    typedef MatrixAnnotation float3x3_ann;


    template 
    struct SimNode_MatrixCtor : SimNode_CallBase {
        SimNode_MatrixCtor(const LineInfo & at) : SimNode_CallBase(at,"") {}
        virtual SimNode * visit ( SimVisitor & vis ) override {
            V_BEGIN();
            V_OP(MatrixCtor);
            V_CALL();
            V_END();
        }
        DAS_EVAL_ABI virtual vec4f eval(Context & context) override {
            auto cmres = cmresEval->evalPtr(context);
            memset ( cmres, 0, sizeof(MatT) );
            return cast::from(cmres);
        }
    };

    template 
    __forceinline void matrix_identity ( float * mat ) {
        for ( int y=0; y!=r; ++y ) {
            for ( int x=0; x!=c; ++x ) {
                *mat++ = x==y ? 1.0f : 0.0f;
            }
        }
    }

    float4x4 float4x4_from_float34 ( const float3x4 & mat ) {
        mat44f res;
        v_mat44_make_from_43ca(res, (const float*)&mat);
        return reinterpret_cast(res);
    }

    float3x3 float3x3_from_float44 ( const float4x4 & mat ) {
        float3x3 res;
        res.m[0] = vec4f(mat.m[0]);
        res.m[1] = vec4f(mat.m[1]);
        res.m[2] = vec4f(mat.m[2]);
        return res;
    }

    float3x3 float3x3_from_float34 ( const float3x4 & mat ) {
        float3x3 res;
        res.m[0] = vec4f(mat.m[0]);
        res.m[1] = vec4f(mat.m[1]);
        res.m[2] = vec4f(mat.m[2]);
        return res;
    }

    float3x4 float3x4_from_float44 ( const float4x4 & mat ) {
        float3x4 res;
        res.m[0] = vec4f(mat.m[0]);
        res.m[1] = vec4f(mat.m[1]);
        res.m[2] = vec4f(mat.m[2]);
        res.m[3] = vec4f(mat.m[3]);
        return res;
    }

    void float4x4_identity ( float4x4 & mat ) {
        matrix_identity((float*)&mat);
    }

    void float3x4_identity ( float3x4 & mat ) {
        matrix_identity((float*)&mat);
    }

    void float3x3_identity ( float3x3 & mat ) {
        matrix_identity((float*)&mat);
    }

    float3x3 float3x3_neg ( const float3x3 & mat ) {
        float3x3 res;
        res.m[0] = v_neg(mat.m[0]);
        res.m[1] = v_neg(mat.m[1]);
        res.m[2] = v_neg(mat.m[2]);
        return res;
    }

    float float3x3_det ( const float3x3 & a ) {
        mat33f va;  va.col0 = a.m[0]; va.col1 = a.m[1]; va.col2 = a.m[2];
        return v_extract_x(v_mat33_det(va));
    }

    float3x4 float3x4_neg ( const float3x4 & mat ) {
        float3x4 res;
        res.m[0] = v_neg(mat.m[0]);
        res.m[1] = v_neg(mat.m[1]);
        res.m[2] = v_neg(mat.m[2]);
        res.m[3] = v_neg(mat.m[3]);
        return res;
    }

    float float4x4_det(const float4x4 &a) {
        mat44f va;
        memcpy(&va,&a,sizeof(float4x4));
        return v_extract_x(v_mat44_det(va));
    }

    float4x4 float4x4_identity_m ( void ) {
        float4x4 mat;
        matrix_identity((float*)&mat);
        return mat;
    }

    float3x4 float3x4_identity_m ( void ) {
        float3x4 mat;
        matrix_identity((float*)&mat);
        return mat;
    }

    float3x3 float3x3_identity_m ( void ) {
        float3x3 mat;
        matrix_identity((float*)&mat);
        return mat;
    }

    float4x4 float4x4_translation(float3 xyz) {
        float4x4 mat;
        matrix_identity((float*)&mat);
        mat.m[3].x = xyz.x;
        mat.m[3].y = xyz.y;
        mat.m[3].z = xyz.z;
        return mat;
    }

    float4x4 float4x4_mul(const float4x4 &a, const float4x4 &b) {
        mat44f va,vb,res;
        memcpy(&va,&a,sizeof(float4x4));
        memcpy(&vb,&b,sizeof(float4x4));
        v_mat44_mul(res,va,vb);
        return reinterpret_cast(res);
    }

    float3x3 float3x3_mul(const float3x3 &a, const float3x3 &b) {
        float3x3 res;
        mat33f va;  va.col0 = a.m[0]; va.col1 = a.m[1]; va.col2 = a.m[2];
        res.m[0] = v_mat33_mul_vec3(va, b.m[0]);
        res.m[1] = v_mat33_mul_vec3(va, b.m[1]);
        res.m[2] = v_mat33_mul_vec3(va, b.m[2]);
        return res;
    }

    float4x4 float4x4_transpose ( const float4x4 & src ) {
        mat44f res;
        memcpy ( &res, &src, sizeof(float4x4) );
        v_mat44_transpose(res.col0, res.col1, res.col2, res.col3);
        return reinterpret_cast(res);
    }

    float4x4 float4x4_neg( const float4x4 & src) {
        mat44f res;
        res.col0 = v_neg(src.m[0]);
        res.col1 = v_neg(src.m[1]);
        res.col2 = v_neg(src.m[2]);
        res.col3 = v_neg(src.m[3]);
        return reinterpret_cast(res);
    }

    float4x4 float4x4_inverse( const float4x4 & src) {
        mat44f mat, invMat;
        memcpy(&mat, &src, sizeof(float4x4));
        v_mat44_inverse(invMat, mat);
        return reinterpret_cast(invMat);
    }

    float3x3 float3x3_inverse( const float3x3 & src) {
        mat33f mat, invMat;
        memcpy(&mat, &src, sizeof(float3x3));
        v_mat33_inverse(invMat, mat);
        return reinterpret_cast(invMat);
    }

    float3x3 float3x3_orthonormal_inverse( const float3x3 & src) {
        mat33f mat, invMat;
        memcpy(&mat, &src, sizeof(float3x3));
        v_mat33_orthonormal_inverse(invMat, mat);
        return reinterpret_cast(invMat);
    }

    float4x4 float4x4_persp_forward(float wk, float hk, float zn, float zf) {
        mat44f mat;
        v_mat44_make_persp_forward(mat, wk, hk, zn, zf);
        return reinterpret_cast(mat);
    }

    float4x4 float4x4_persp_reverse(float wk, float hk, float zn, float zf) {
        mat44f mat;
        v_mat44_make_persp_reverse(mat, wk, hk, zn, zf);
        return reinterpret_cast(mat);
    }

    float4x4 float4x4_look_at(float3 eye, float3 at, float3 up) {
        mat44f mat;
        v_mat44_make_look_at(mat, eye, at, up);
        return reinterpret_cast(mat);
    }

    float4x4 float4x4_compose(float3 pos, float4 rot, float3 scale) {
        mat44f mat;
        v_mat44_compose(mat, pos, rot, scale);
        return reinterpret_cast(mat);
    }

    void float4x4_decompose(const float4x4 & mat, float3 & pos, float4 & rot, float3 & scale) {
        mat44f gmat;
        memcpy(&gmat, &mat, sizeof(float4x4));
        vec3f gpos;
        quat4f grot;
        vec4f gscale;
        v_mat4_decompose(gmat, gpos, grot, gscale);
        pos = gpos;
        rot = grot;
        scale = gscale;
    }

    float4 quat_from_unit_arc(float3 v0, float3 v1) {
        return v_quat_from_unit_arc(v_ldu_p3(&v0.x), v_ldu_p3(&v1.x));
    }

    float4 quat_from_unit_vec_ang(float3 v, float ang) {
        return v_quat_from_unit_vec_ang(v_ldu_p3(&v.x), v_splats(ang));
    }

    float4 quat_from_euler_vec(float3 v) {
        return v_quat_from_euler(v_ldu_p3(&v.x));
    }

    float4 quat_from_euler(float x, float y, float z) {
        return v_quat_from_euler(v_make_vec4f(x, y, z, 0.f));
    }

    float3 euler_from_quat_vec(float4 v) {
        return v_euler_from_quat(v);
    }

    float4 quat_from_float3x3(const float3x3 & a) {
        mat33f va;  va.col0 = a.m[0]; va.col1 = a.m[1]; va.col2 = a.m[2];
        return v_quat_from_mat33(va);
    }
    float4 quat_from_float3x4(const float3x4 & a) {
        mat44f tm;
        v_mat44_make_from_43cu_unsafe(tm, &a.m[0].x);
        return v_quat_from_mat43(tm);
    }
    float4 quat_from_float4x4(const float4x4 & a) {
        mat44f va;
        memcpy(&va,&a,sizeof(float4x4));
        return v_quat_from_mat43(va);
    }

    float4 quat_mul(float4 q1, float4 q2) {
        return v_quat_mul_quat(q1, q2);
    }

    float3 quat_mul_vec(float4 q, float3 v) {
        return v_quat_mul_vec3(q, v);
    }

    float4 quat_conjugate(float4 q) {
        return v_quat_conjugate(q);
    }

    float4 quat_slerp(float t, float4 a, float4 b) {
        return v_quat_slerp(v_splats(t), a, b);
    }

    struct floatNxNIndexFn : defaultTempFn {
        floatNxNIndexFn() : defaultTempFn() {}
        ___noinline bool operator () ( Function * fn ) {
            defaultTempFn::operator()(fn);
            if ( !fn->arguments.empty() ) {
                fn->arguments[0]->type->explicitConst = true;
            }
            fn->builtIn = true;
            fn->generated = true;
            fn->jitOnly = true;
            return true;
        }
    };

    template  
    class MatrixCTorFn : public BuiltInFunction {
    public:
        __forceinline MatrixCTorFn(const char * fn, const ModuleLibrary & lib, const char * cna = nullptr, bool pbas = true)
        : BuiltInFunction(fn,cna) {
            this->policyBased = pbas;
            construct(makeBuiltinArgs(lib));
        }
        virtual SimNode * makeSimNode ( Context & context, const vector & ) override {
            return context.code->makeNode(at);
        }
        static RetT ctorFn() {
            RetT res;
            memset(&res, 0, sizeof(RetT));
            return res;
        }
        virtual void * getBuiltinAddress() const override {
            constexpr bool IS_CMRES = true;
            return ImplWrapCall::get_builtin_address();
        }
    };

    class Module_Math : public Module {
    public:
        Module_Math() : Module("math") {
            DAS_PROFILE_SECTION("Module_Math");
            ModuleLibrary lib(this);
            lib.addBuiltInModule();
            // constants
            addConstant(*this,"PI",(float)M_PI);
            addConstant(*this,"DBL_PI",(double)M_PI);
            addConstant(*this,"FLT_EPSILON",FLT_EPSILON);
            addConstant(*this,"DBL_EPSILON",DBL_EPSILON);
            // trigonometry functions
            addFunctionTrig(*this, lib);
            addFunctionTrig(*this,lib);
            addFunctionTrig(*this,lib);
            addFunctionTrig(*this,lib);
            // exp functions
            addFunctionPow(*this, lib);
            addFunctionPow(*this,lib);
            addFunctionPow(*this,lib);
            addFunctionPow(*this,lib);
            // op3
            addFunctionOp3(*this,lib);
            addFunctionOp3(*this,lib);
            addFunctionOp3(*this,lib);
            addFunctionOp3(*this,lib);
            addFunction( (new BuiltInFn("mad", lib, "MadS"))->args({"a","b","c"}) );
            addFunction( (new BuiltInFn("mad", lib, "MadS"))->args({"a","b","c"}) );
            addFunction( (new BuiltInFn("mad", lib, "MadS"))->args({"a","b","c"}) );
            // op3i - int
            addFunctionOp3i(*this,lib);
            addFunctionOp3i(*this,lib);
            addFunctionOp3i(*this,lib);
            addFunctionOp3i(*this,lib);
            addFunction( (new BuiltInFn("mad", lib, "MadS"))->args({"a","b","c"}) );
            addFunction( (new BuiltInFn("mad", lib, "MadS"))->args({"a","b","c"}) );
            addFunction( (new BuiltInFn("mad", lib, "MadS"))->args({"a","b","c"}) );
            // op3i - uint
            addFunctionOp3i(*this,lib);
            addFunctionOp3i(*this,lib);
            addFunctionOp3i(*this,lib);
            addFunctionOp3i(*this,lib);
            addFunction( (new BuiltInFn("mad", lib, "MadS"))->args({"a","b","c"}) );
            addFunction( (new BuiltInFn("mad", lib, "MadS"))->args({"a","b","c"}) );
            addFunction( (new BuiltInFn("mad", lib, "MadS"))->args({"a","b","c"}) );
            // and double
            addFunctionOp3(*this,lib);
            // double common (sqrt/rsqrt/rcp already registered as externs below)
            addFunction( (new BuiltInFn("floor",       lib, "Floor"))->arg("x") );
            addFunction( (new BuiltInFn("ceil",        lib, "Ceil"))->arg("x") );
            addFunction( (new BuiltInFn("fract",       lib, "Fract"))->arg("x") );
            addFunction( (new BuiltInFn("round",       lib, "Round"))->arg("x") );
            addFunction( (new BuiltInFn("saturate",    lib, "Sat"))->arg("x") );
            //common
            addFunctionCommon(*this, lib);
            addFunctionCommon(*this,lib);
            addFunctionCommon(*this,lib);
            addFunctionCommon(*this,lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addFunctionCommonTyped(*this, lib);
            addExtern(*this, lib, "uint32_hash", SideEffects::none, "uint32_hash")->arg("seed");
            addExtern(*this, lib, "uint_noise_1D", SideEffects::none, "uint_noise1D")->args({"position","seed"});
            addExtern(*this, lib, "uint_noise_2D", SideEffects::none, "uint_noise2D_int2")->args({"position","seed"});
            addExtern(*this, lib, "uint_noise_3D", SideEffects::none, "uint_noise3D_int3")->args({"position","seed"});
            addExternEx(*this, lib, "dot", SideEffects::none, "dot2")->args({"x","y"});
            addExternEx(*this, lib, "dot", SideEffects::none, "dot3")->args({"x","y"});
            addExternEx(*this, lib, "dot", SideEffects::none, "dot4")->args({"x","y"});
            addExternEx(*this, lib, "hmin", SideEffects::none, "hmin2")->arg("a");
            addExternEx(*this, lib, "hmin", SideEffects::none, "hmin3")->arg("a");
            addExternEx(*this, lib, "hmin", SideEffects::none, "hmin4")->arg("a");
            addExternEx(*this, lib, "hmax", SideEffects::none, "hmax2")->arg("a");
            addExternEx(*this, lib, "hmax", SideEffects::none, "hmax3")->arg("a");
            addExternEx(*this, lib, "hmax", SideEffects::none, "hmax4")->arg("a");
            addExternEx(*this, lib, "hadd", SideEffects::none, "hadd2")->arg("a");
            addExternEx(*this, lib, "hadd", SideEffects::none, "hadd3")->arg("a");
            addExternEx(*this, lib, "hadd", SideEffects::none, "hadd4")->arg("a");
            addExternEx(*this, lib, "cross", SideEffects::none, "cross3")->args({"x","y"});
            addExternEx(*this, lib, "fast_normalize", SideEffects::none, "normalize2")->arg("x");
            addExternEx(*this, lib, "fast_normalize", SideEffects::none, "normalize3")->arg("x");
            addExternEx(*this, lib, "fast_normalize", SideEffects::none, "normalize4")->arg("x");
            addExternEx(*this, lib, "normalize", SideEffects::none, "safe_normalize2")->arg("x");
            addExternEx(*this, lib, "normalize", SideEffects::none, "safe_normalize3")->arg("x");
            addExternEx(*this, lib, "normalize", SideEffects::none, "safe_normalize4")->arg("x");
            addExternEx(*this, lib, "length", SideEffects::none, "length2")->arg("x");
            addExternEx(*this, lib, "length", SideEffects::none, "length3")->arg("x");
            addExternEx(*this, lib, "length", SideEffects::none, "length4")->arg("x");
            addExternEx(*this, lib, "inv_length", SideEffects::none,"invlength2")->arg("x");
            addExternEx(*this, lib, "inv_length", SideEffects::none,"invlength3")->arg("x");
            addExternEx(*this, lib, "inv_length", SideEffects::none,"invlength4")->arg("x");
            addExternEx(*this, lib, "inv_length_sq", SideEffects::none, "invlengthSq2")->arg("x");
            addExternEx(*this, lib, "inv_length_sq", SideEffects::none, "invlengthSq3")->arg("x");
            addExternEx(*this, lib, "inv_length_sq", SideEffects::none, "invlengthSq4")->arg("x");
            addExternEx(*this, lib, "length_sq", SideEffects::none, "lengthSq2")->arg("x");
            addExternEx(*this, lib, "length_sq", SideEffects::none, "lengthSq3")->arg("x");
            addExternEx(*this, lib, "length_sq", SideEffects::none, "lengthSq4")->arg("x");
            addExternEx(*this, lib, "distance", SideEffects::none, "distance2")->args({"x","y"});
            addExternEx(*this, lib, "distance_sq", SideEffects::none, "distanceSq2")->args({"x","y"});
            addExternEx(*this, lib, "inv_distance", SideEffects::none, "invdistance2")->args({"x","y"});
            addExternEx(*this, lib, "inv_distance_sq", SideEffects::none, "invdistanceSq2")->args({"x","y"});
            addExternEx(*this, lib, "distance", SideEffects::none, "distance3")->args({"x","y"});
            addExternEx(*this, lib, "distance_sq", SideEffects::none, "distanceSq3")->args({"x","y"});
            addExternEx(*this, lib, "inv_distance", SideEffects::none, "invdistance3")->args({"x","y"});
            addExternEx(*this, lib, "inv_distance_sq", SideEffects::none, "invdistanceSq3")->args({"x","y"});
            addExternEx(*this, lib, "distance", SideEffects::none, "distance4")->args({"x","y"});
            addExternEx(*this, lib, "distance_sq", SideEffects::none, "distanceSq4")->args({"x","y"});
            addExternEx(*this, lib, "inv_distance", SideEffects::none, "invdistance4")->args({"x","y"});
            addExternEx(*this, lib, "inv_distance_sq", SideEffects::none, "invdistanceSq4")->args({"x","y"});
            addExternEx(*this, lib, "lerp", SideEffects::none, "lerp_vec_float")->args({"a", "b", "t"});
            addExternEx(*this, lib, "lerp", SideEffects::none, "lerp_vec_float")->args({"a", "b", "t"});
            addExternEx(*this, lib, "lerp", SideEffects::none, "lerp_vec_float")->args({"a", "b", "t"});
            addExternEx(*this, lib, "step", SideEffects::none, "step_float")->args({"edge","x"});
            addExternEx(*this, lib, "step", SideEffects::none, "step_vec")->args({"edge","x"});
            addExternEx(*this, lib, "step", SideEffects::none, "step_vec")->args({"edge","x"});
            addExternEx(*this, lib, "step", SideEffects::none, "step_vec")->args({"edge","x"});
            addExternEx(*this, lib, "smoothstep", SideEffects::none, "smoothstep_float")->args({"edge0","edge1","x"});
            addExternEx(*this, lib, "smoothstep", SideEffects::none, "smoothstep_vec")->args({"edge0","edge1","x"});
            addExternEx(*this, lib, "smoothstep", SideEffects::none, "smoothstep_vec")->args({"edge0","edge1","x"});
            addExternEx(*this, lib, "smoothstep", SideEffects::none, "smoothstep_vec")->args({"edge0","edge1","x"});
            addExternEx(*this, lib, "radians", SideEffects::none, "radians_float")->arg("deg");
            addExternEx(*this, lib, "radians", SideEffects::none, "radians_vec")->arg("deg");
            addExternEx(*this, lib, "radians", SideEffects::none, "radians_vec")->arg("deg");
            addExternEx(*this, lib, "radians", SideEffects::none, "radians_vec")->arg("deg");
            addExternEx(*this, lib, "degrees", SideEffects::none, "degrees_float")->arg("rad");
            addExternEx(*this, lib, "degrees", SideEffects::none, "degrees_vec")->arg("rad");
            addExternEx(*this, lib, "degrees", SideEffects::none, "degrees_vec")->arg("rad");
            addExternEx(*this, lib, "degrees", SideEffects::none, "degrees_vec")->arg("rad");

            // unique float functions
            addExtern(*this, lib, "is_nan", SideEffects::none, "fisnan")->arg("x");
            addExtern(*this, lib, "is_finite", SideEffects::none, "fisfinite")->arg("x");
            //double functions
            addExtern(*this, lib, "is_nan", SideEffects::none, "disnan")->arg("x");
            addExtern(*this, lib, "is_finite", SideEffects::none, "disfinite")->arg("x");
            addExtern(*this, lib, "sqrt",   SideEffects::none, "dsqrt")->arg("x");
            addExtern(*this, lib, "exp",     SideEffects::none, "dexp")->arg("x");
            addExtern(*this, lib, "rcp",     SideEffects::none, "drcp")->arg("x");
            addExtern(*this, lib, "log",     SideEffects::none, "dlog")->arg("x");
            addExtern(*this, lib, "pow",     SideEffects::none, "dpow")->args({"x","y"});
            addExtern(*this, lib, "exp2",   SideEffects::none, "dexp2")->arg("x");
            addExtern(*this, lib, "log2",   SideEffects::none, "dlog2")->arg("x");
            addExtern(*this, lib, "sin",     SideEffects::none, "dsin")->arg("x");
            addExtern(*this, lib, "cos",     SideEffects::none, "dcos")->arg("x");
            addExtern(*this, lib, "asin",   SideEffects::none, "dasin")->arg("x");
            addExtern(*this, lib, "acos",   SideEffects::none, "dacos")->arg("x");
            addExtern(*this, lib, "safe_asin",   SideEffects::none, "dsafe_asin")->arg("x");
            addExtern(*this, lib, "safe_acos",   SideEffects::none, "dsafe_acos")->arg("x");
            addExtern(*this, lib, "tan",     SideEffects::none, "dtan")->arg("x");
            addExtern(*this, lib, "atan",   SideEffects::none, "datan")->arg("x");
            addExtern(*this, lib, "atan2", SideEffects::none, "datan2")->args({"y","x"});
            addExtern(*this, lib, "sinh", SideEffects::none, "dsinh")->arg("x");
            addExtern(*this, lib, "cosh", SideEffects::none, "dcosh")->arg("x");
            addExtern(*this, lib, "tanh", SideEffects::none, "dtanh")->arg("x");
            addExtern(*this, lib, "asinh", SideEffects::none, "dasinh")->arg("x");
            addExtern(*this, lib, "acosh", SideEffects::none, "dacosh")->arg("x");
            addExtern(*this, lib, "atanh", SideEffects::none, "datanh")->arg("x");
            addExtern(*this, lib, "log10", SideEffects::none, "dlog10")->arg("x");
            addExtern(*this, lib, "log1p", SideEffects::none, "dlog1p")->arg("x");
            addExtern(*this, lib, "expm1", SideEffects::none, "dexpm1")->arg("x");
            addExtern(*this, lib, "cbrt", SideEffects::none, "dcbrt")->arg("x");
            addExtern(*this, lib, "trunc", SideEffects::none, "dtrunc")->arg("x");
            addExtern(*this, lib, "hypot", SideEffects::none, "dhypot")->args({"x","y"});
            addExtern(*this, lib, "fmod", SideEffects::none, "dfmod")->args({"x","y"});
            addExtern(*this, lib, "remainder", SideEffects::none, "dremainder")->args({"x","y"});
            addExtern(*this, lib, "sincos", SideEffects::modifyArgument, "sincosF")->args({"x","s","c"});
            addExtern(*this, lib, "sincos", SideEffects::modifyArgument, "sincosD")->args({"x","s","c"});
            // too big for intrinsic
            addExtern(*this, lib, "asin", SideEffects::none, "fasin")->arg("x");
            addExtern(*this, lib, "acos", SideEffects::none, "facos")->arg("x");
            addExtern(*this, lib, "safe_asin", SideEffects::none, "fsafe_asin")->arg("x");
            addExtern(*this, lib, "safe_acos", SideEffects::none, "fsafe_acos")->arg("x");
            addExtern(*this, lib, "atan", SideEffects::none, "fatan")->arg("x");
            addExtern(*this, lib, "atan_est", SideEffects::none, "fatan_est")->arg("x");
            addExtern(*this, lib, "atan2", SideEffects::none, "fatan2")->args({"y","x"});
            addExtern(*this, lib, "atan2_est", SideEffects::none, "fatan2_est")->args({"y","x"});
            addExtern(*this, lib, "sinh", SideEffects::none, "fsinh")->arg("x");
            addExtern(*this, lib, "cosh", SideEffects::none, "fcosh")->arg("x");
            addExtern(*this, lib, "tanh", SideEffects::none, "ftanh")->arg("x");
            addExtern(*this, lib, "asinh", SideEffects::none, "fasinh")->arg("x");
            addExtern(*this, lib, "acosh", SideEffects::none, "facosh")->arg("x");
            addExtern(*this, lib, "atanh", SideEffects::none, "fatanh")->arg("x");
            addExtern(*this, lib, "log10", SideEffects::none, "flog10")->arg("x");
            addExtern(*this, lib, "log1p", SideEffects::none, "flog1p")->arg("x");
            addExtern(*this, lib, "expm1", SideEffects::none, "fexpm1")->arg("x");
            addExtern(*this, lib, "cbrt", SideEffects::none, "fcbrt")->arg("x");
            addExtern(*this, lib, "trunc", SideEffects::none, "ftrunc")->arg("x");
            addExtern(*this, lib, "hypot", SideEffects::none, "fhypot")->args({"x","y"});
            addExtern(*this, lib, "fmod", SideEffects::none, "ffmod")->args({"x","y"});
            addExtern(*this, lib, "remainder", SideEffects::none, "fremainder")->args({"x","y"});
            addExternEx(*this, lib, "asin", SideEffects::none, "vasin")->arg("x");
            addExternEx(*this, lib, "asin", SideEffects::none, "vasin")->arg("x");
            addExternEx(*this, lib, "asin", SideEffects::none, "vasin")->arg("x");
            addExternEx(*this, lib, "acos", SideEffects::none, "vacos")->arg("x");
            addExternEx(*this, lib, "acos", SideEffects::none, "vacos")->arg("x");
            addExternEx(*this, lib, "acos", SideEffects::none, "vacos")->arg("x");
            addExternEx(*this, lib, "safe_asin", SideEffects::none, "vsafe_asin")->arg("x");
            addExternEx(*this, lib, "safe_asin", SideEffects::none, "vsafe_asin")->arg("x");
            addExternEx(*this, lib, "safe_asin", SideEffects::none, "vsafe_asin")->arg("x");
            addExternEx(*this, lib, "safe_acos", SideEffects::none, "vsafe_acos")->arg("x");
            addExternEx(*this, lib, "safe_acos", SideEffects::none, "vsafe_acos")->arg("x");
            addExternEx(*this, lib, "safe_acos", SideEffects::none, "vsafe_acos")->arg("x");
            addExternEx(*this, lib, "atan", SideEffects::none, "vatan")->arg("x");
            addExternEx(*this, lib, "atan", SideEffects::none, "vatan")->arg("x");
            addExternEx(*this, lib, "atan", SideEffects::none, "vatan")->arg("x");
            addExternEx(*this, lib, "atan_est", SideEffects::none, "vatan_est")->arg("x");
            addExternEx(*this, lib, "atan_est", SideEffects::none, "vatan_est")->arg("x");
            addExternEx(*this, lib, "atan_est", SideEffects::none, "vatan_est")->arg("x");
            addExternEx(*this, lib, "atan2", SideEffects::none, "vatan2")->args({"y","x"});
            addExternEx(*this, lib, "atan2", SideEffects::none, "vatan2")->args({"y","x"});
            addExternEx(*this, lib, "atan2", SideEffects::none, "vatan2")->args({"y","x"});
            addExternEx(*this, lib, "atan2_est", SideEffects::none, "vatan2_est")->args({"y","x"});
            addExternEx(*this, lib, "atan2_est", SideEffects::none, "vatan2_est")->args({"y","x"});
            addExternEx(*this, lib, "atan2_est", SideEffects::none, "vatan2_est")->args({"y","x"});
            addExternEx(*this, lib, "sinh", SideEffects::none, "vsinh")->arg("x");
            addExternEx(*this, lib, "sinh", SideEffects::none, "vsinh")->arg("x");
            addExternEx(*this, lib, "sinh", SideEffects::none, "vsinh")->arg("x");
            addExternEx(*this, lib, "cosh", SideEffects::none, "vcosh")->arg("x");
            addExternEx(*this, lib, "cosh", SideEffects::none, "vcosh")->arg("x");
            addExternEx(*this, lib, "cosh", SideEffects::none, "vcosh")->arg("x");
            addExternEx(*this, lib, "tanh", SideEffects::none, "vtanh")->arg("x");
            addExternEx(*this, lib, "tanh", SideEffects::none, "vtanh")->arg("x");
            addExternEx(*this, lib, "tanh", SideEffects::none, "vtanh")->arg("x");
            addExternEx(*this, lib, "asinh", SideEffects::none, "vasinh")->arg("x");
            addExternEx(*this, lib, "asinh", SideEffects::none, "vasinh")->arg("x");
            addExternEx(*this, lib, "asinh", SideEffects::none, "vasinh")->arg("x");
            addExternEx(*this, lib, "acosh", SideEffects::none, "vacosh")->arg("x");
            addExternEx(*this, lib, "acosh", SideEffects::none, "vacosh")->arg("x");
            addExternEx(*this, lib, "acosh", SideEffects::none, "vacosh")->arg("x");
            addExternEx(*this, lib, "atanh", SideEffects::none, "vatanh")->arg("x");
            addExternEx(*this, lib, "atanh", SideEffects::none, "vatanh")->arg("x");
            addExternEx(*this, lib, "atanh", SideEffects::none, "vatanh")->arg("x");
            addExternEx(*this, lib, "log10", SideEffects::none, "vlog10")->arg("x");
            addExternEx(*this, lib, "log10", SideEffects::none, "vlog10")->arg("x");
            addExternEx(*this, lib, "log10", SideEffects::none, "vlog10")->arg("x");
            addExternEx(*this, lib, "log1p", SideEffects::none, "vlog1p")->arg("x");
            addExternEx(*this, lib, "log1p", SideEffects::none, "vlog1p")->arg("x");
            addExternEx(*this, lib, "log1p", SideEffects::none, "vlog1p")->arg("x");
            addExternEx(*this, lib, "expm1", SideEffects::none, "vexpm1")->arg("x");
            addExternEx(*this, lib, "expm1", SideEffects::none, "vexpm1")->arg("x");
            addExternEx(*this, lib, "expm1", SideEffects::none, "vexpm1")->arg("x");
            addExternEx(*this, lib, "cbrt", SideEffects::none, "vcbrt")->arg("x");
            addExternEx(*this, lib, "cbrt", SideEffects::none, "vcbrt")->arg("x");
            addExternEx(*this, lib, "cbrt", SideEffects::none, "vcbrt")->arg("x");
            addExternEx(*this, lib, "trunc", SideEffects::none, "vtrunc")->arg("x");
            addExternEx(*this, lib, "trunc", SideEffects::none, "vtrunc")->arg("x");
            addExternEx(*this, lib, "trunc", SideEffects::none, "vtrunc")->arg("x");
            addExternEx(*this, lib, "hypot", SideEffects::none, "vhypot")->args({"x","y"});
            addExternEx(*this, lib, "hypot", SideEffects::none, "vhypot")->args({"x","y"});
            addExternEx(*this, lib, "hypot", SideEffects::none, "vhypot")->args({"x","y"});
            addExternEx(*this, lib, "fmod", SideEffects::none, "vfmod")->args({"x","y"});
            addExternEx(*this, lib, "fmod", SideEffects::none, "vfmod")->args({"x","y"});
            addExternEx(*this, lib, "fmod", SideEffects::none, "vfmod")->args({"x","y"});
            addExternEx(*this, lib, "remainder", SideEffects::none, "vremainder")->args({"x","y"});
            addExternEx(*this, lib, "remainder", SideEffects::none, "vremainder")->args({"x","y"});
            addExternEx(*this, lib, "remainder", SideEffects::none, "vremainder")->args({"x","y"});

            addExternEx(*this, lib, "reflect",
                SideEffects::none, "reflect")->args({"v","n"});
            addExternEx(*this, lib, "reflect",
                SideEffects::none, "reflect2")->args({"v","n"});
            addExternEx(*this, lib, "refract",
                SideEffects::none, "refract")->args({"v","n","nint"});
            addExternEx(*this, lib, "refract",
                SideEffects::none, "refract2")->args({"v","n","nint"});
            addFunctionCommonConversion  (*this, lib);
            addFunctionCommonConversion  (*this, lib);
            addFunctionCommonConversion(*this,lib);
            addFunctionCommonConversion(*this,lib);
            addFunctionCommonConversion(*this,lib);
            // structure annotations
            addAnnotation(new float4x4_ann(lib));
            addAnnotation(new float3x4_ann(lib));
            addAnnotation(new float3x3_ann(lib));
            // c-tor
            addFunction ( new MatrixCTorFn< SimNode_MatrixCtor,float3x3 >("float3x3",lib) );
            addFunction ( new MatrixCTorFn< SimNode_MatrixCtor,float3x4 >("float3x4",lib) );
            addFunction ( new MatrixCTorFn< SimNode_MatrixCtor,float4x4 >("float4x4",lib) );
            // 4x4
            addExtern(*this, lib, "float4x4",
                SideEffects::none,"float4x4_from_float34");
            addExtern(*this, lib, "identity",
                SideEffects::modifyArgument, "float4x4_identity")->arg("x");
            addExtern(*this, lib, "identity4x4",
                SideEffects::none,"float4x4_identity_m");
            addExtern(*this, lib, "translation",
                 SideEffects::none, "float4x4_translation")->arg("xyz");
            addExtern(*this, lib, "transpose",
                SideEffects::none, "float4x4_transpose")->arg("x");
            addExtern(*this, lib, "persp_forward",
                SideEffects::none, "float4x4_persp_forward")->args({"wk", "hk", "zn", "zf"});
            addExtern(*this, lib, "persp_reverse",
                SideEffects::none, "float4x4_persp_reverse")->args({"wk", "hk", "zn", "zf"});
            addExtern(*this, lib, "look_at",
                SideEffects::none, "float4x4_look_at")->args({"eye", "at", "up"});
            addExtern(*this, lib, "compose",
                SideEffects::none, "float4x4_compose")->args({"pos", "rot", "scale"});
            addExtern(*this, lib, "*",
                SideEffects::none,"float4x4_mul")->args({"x", "y"});
            addExtern(*this, lib, "decompose",
                SideEffects::modifyArgument, "float4x4_decompose")->args({"mat","pos","rot","scale"});
            addExtern(*this, lib, "==",
                SideEffects::none, "float4x4_equ")->args({"x","y"});
            addExtern(*this, lib, "!=",
                SideEffects::none, "float4x4_nequ")->args({"x","y"});
            addExtern(*this, lib, "-",
                SideEffects::none,"float4x4_neg")->arg("x");
            addExtern(*this, lib,
                ".[]", SideEffects::modifyArgument, "floatNxN_ati")->args({"m","i","context","at"});
            addExtern(*this, lib,
                ".[]", SideEffects::none, "floatNxN_atci")->args({"m","i","context","at"});
            addExtern(*this, lib,
                ".[]", SideEffects::modifyArgument, "floatNxN_ati")->args({"m","i","context","at"});
            addExtern(*this, lib,
                ".[]", SideEffects::none, "floatNxN_atci")->args({"m","i","context","at"});
            // 3x4
            addExtern(*this, lib, "float3x4",
                SideEffects::none,"float3x4_from_float44");
            addExtern(*this, lib, "identity",
                SideEffects::modifyArgument,"float3x4_identity")->arg("x");
            addExtern(*this, lib, "identity3x4",
                SideEffects::none,"float3x4_identity_m");
            addExtern(*this, lib, "*",
                SideEffects::none,"float3x4_mul")->args({"x","y"});
            addExtern(*this, lib, "*",
                SideEffects::none,"float3x4_mul_vec3p")->args({"x","y"});
            addExtern(*this, lib, "*",
                SideEffects::none,"float4x4_mul_vec4")->args({"x","y"});
            addExtern(*this, lib, "determinant",
                SideEffects::none,"float4x4_det")->arg("x");
            addExtern(*this, lib,
                "inverse", SideEffects::none, "float3x4_inverse")->arg("x");
            addExtern(*this, lib,
                "inverse", SideEffects::none, "float4x4_inverse")->arg("m");
            addExtern(*this, lib,
                "orthonormal_inverse", SideEffects::none, "float3x3_orthonormal_inverse")->arg("m");
            addExtern(*this, lib,
                "orthonormal_inverse", SideEffects::none, "float3x4_orthonormal_inverse")->arg("m");
            addExtern(*this, lib, "rotate",
                SideEffects::none, "rotate")->args({"x","y"});
            addExtern(*this, lib, "==",
                SideEffects::none, "float3x4_equ")->args({"x","y"});
            addExtern(*this, lib, "!=",
                SideEffects::none, "float3x4_nequ")->args({"x","y"});
            addExtern(*this, lib, "-",
                SideEffects::none,"float3x4_neg")->arg("x");
            addExtern(*this, lib, "determinant",
                SideEffects::none,"float3x4_det")->arg("x");
            addExtern(*this, lib,
                ".[]", SideEffects::modifyArgument, "floatNxN_ati")->args({"m","i","context","at"});
            addExtern(*this, lib,
                ".[]", SideEffects::none, "floatNxN_atci")->args({"m","i","context","at"});
            addExtern(*this, lib,
                ".[]", SideEffects::modifyArgument, "floatNxN_ati")->args({"m","i","context","at"});
            addExtern(*this, lib,
                ".[]", SideEffects::none, "floatNxN_atci")->args({"m","i","context","at"});
            // quat
            addExtern(*this, lib, "quat_from_unit_arc",
                SideEffects::none, "quat_from_unit_arc")->args({"v0","v1"});
            addExtern(*this, lib, "quat_from_unit_vec_ang",
                SideEffects::none, "quat_from_unit_vec_ang")->args({"v","ang"});
            addExtern(*this, lib, "quat_from_euler",
                SideEffects::none, "quat_from_euler_vec")->args({"angles"});
            addExtern(*this, lib, "quat_from_euler",
                SideEffects::none, "quat_from_euler")->args({"x", "y", "z"});
            addExtern(*this, lib, "euler_from_quat",
                SideEffects::none, "euler_from_quat_vec")->args({"angles"});
            addExtern(*this, lib, "quat",
                SideEffects::none, "quat_from_float3x3")->arg("m");
            addExtern(*this, lib, "quat",
                SideEffects::none, "quat_from_float3x4")->arg("m");
            addExtern(*this, lib, "quat",
                SideEffects::none, "quat_from_float4x4")->arg("m");
            addExtern(*this, lib, "quat_mul",
                SideEffects::none, "quat_mul")->args({"q1","q2"});
            addExtern(*this, lib, "quat_mul_vec",
                SideEffects::none, "quat_mul_vec")->args({"q","v"});
            addExtern(*this, lib, "quat_conjugate",
                SideEffects::none, "quat_conjugate")->arg("q");
            addExtern(*this, lib, "quat_slerp",
                SideEffects::none, "quat_slerp")->args({"t", "a", "b"});
            // 3x3
            addExtern(*this, lib, "float3x3",
                SideEffects::none,"float3x3_from_float44");
            addExtern(*this, lib, "float3x3",
                SideEffects::none,"float3x3_from_float34");
            addExtern(*this, lib, "identity",
                SideEffects::modifyArgument,"float3x3_identity")->arg("x");
            addExtern(*this, lib, "identity3x3",
                SideEffects::none,"float3x3_identity_m");
            addExtern(*this, lib, "*",
                SideEffects::none,"float3x3_mul")->args({"x", "y"});
            addExtern(*this, lib, "*",
                SideEffects::none,"float3x3_mul_vec3")->args({"x","y"});
            addExtern(*this, lib, "==",
                SideEffects::none, "float3x3_equ")->args({"x","y"});
            addExtern(*this, lib, "!=",
                SideEffects::none, "float3x3_nequ")->args({"x","y"});
            addExtern(*this, lib, "-",
                SideEffects::none,"float3x3_neg")->arg("x");
            addExtern(*this, lib, "determinant",
                SideEffects::none,"float3x3_det")->arg("x");
            addExtern(*this, lib,
                ".[]", SideEffects::modifyArgument, "floatNxN_ati")->args({"m","i","context","at"});
            addExtern(*this, lib,
                ".[]", SideEffects::none, "floatNxN_atci")->args({"m","i","context","at"});
            addExtern(*this, lib,
                ".[]", SideEffects::modifyArgument, "floatNxN_ati")->args({"m","i","context","at"});
            addExtern(*this, lib,
                ".[]", SideEffects::none, "floatNxN_atci")->args({"m","i","context","at"});
            // packing
            addExtern(*this, lib, "pack_float_to_byte",
                SideEffects::none,"pack_float_to_byte")->arg("x");
            addExtern(*this, lib, "unpack_byte_to_float",
                SideEffects::none,"unpack_byte_to_float")->arg("x");
            // and check everything
            verifyAotReady();
        }
        virtual ModuleAotType aotRequire ( TextWriter & tw ) const override {
            tw 

Web Proxy Viewer  |  New URL  |  Original Page