From Lua 5.2: Add math.log(x, base).

This commit is contained in:
Mike Pall 2012-10-07 15:47:11 +02:00
parent 0d62e2e1ab
commit 0561a56938
8 changed files with 129 additions and 11 deletions

View File

@ -33,7 +33,6 @@ LJLIB_ASM(math_sqrt) LJLIB_REC(math_unary IRFPM_SQRT)
lj_lib_checknum(L, 1);
return FFH_RETRY;
}
LJLIB_ASM_(math_log) LJLIB_REC(math_unary IRFPM_LOG)
LJLIB_ASM_(math_log10) LJLIB_REC(math_unary IRFPM_LOG10)
LJLIB_ASM_(math_exp) LJLIB_REC(math_unary IRFPM_EXP)
LJLIB_ASM_(math_sin) LJLIB_REC(math_unary IRFPM_SIN)
@ -48,6 +47,22 @@ LJLIB_ASM_(math_tanh) LJLIB_REC(math_htrig IRCALL_tanh)
LJLIB_ASM_(math_frexp)
LJLIB_ASM_(math_modf) LJLIB_REC(.)
LJLIB_ASM(math_log) LJLIB_REC(math_log)
{
double x = lj_lib_checknum(L, 1);
if (L->base+1 < L->top) {
double y = lj_lib_checknum(L, 2);
#ifdef LUAJIT_NO_LOG2
x = log(x); y = 1.0 / log(y);
#else
x = lj_vm_log2(x); y = 1.0 / lj_vm_log2(y);
#endif
setnumV(L->base-1, x*y); /* Do NOT join the expression to x / y. */
return FFH_RES(1);
}
return FFH_RETRY;
}
LJLIB_PUSH(57.29577951308232)
LJLIB_ASM_(math_deg) LJLIB_REC(math_degrad)

View File

@ -447,6 +447,28 @@ static void LJ_FASTCALL recff_math_unary(jit_State *J, RecordFFData *rd)
J->base[0] = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, J->base[0]), rd->data);
}
/* Record math.log. */
static void LJ_FASTCALL recff_math_log(jit_State *J, RecordFFData *rd)
{
TRef tr = lj_ir_tonum(J, J->base[0]);
if (J->base[1]) {
#ifdef LUAJIT_NO_LOG2
uint32_t fpm = IRFPM_LOG;
#else
uint32_t fpm = IRFPM_LOG2;
#endif
TRef trb = lj_ir_tonum(J, J->base[1]);
tr = emitir(IRTN(IR_FPMATH), tr, fpm);
trb = emitir(IRTN(IR_FPMATH), trb, fpm);
trb = emitir(IRTN(IR_DIV), lj_ir_knum_one(J), trb);
tr = emitir(IRTN(IR_MUL), tr, trb);
} else {
tr = emitir(IRTN(IR_FPMATH), tr, IRFPM_LOG);
}
J->base[0] = tr;
UNUSED(rd);
}
/* Record math.atan2. */
static void LJ_FASTCALL recff_math_atan2(jit_State *J, RecordFFData *rd)
{

View File

@ -60,6 +60,11 @@ LJ_ASMF double lj_vm_floor_hf(double);
LJ_ASMF double lj_vm_ceil_hf(double);
#endif
#endif
#if defined(LUAJIT_NO_LOG2) || LJ_TARGET_X86ORX64
LJ_ASMF double lj_vm_log2(double);
#else
#define lj_vm_log2 log2
#endif
#if LJ_HASJIT
#if LJ_TARGET_X86ORX64
@ -80,11 +85,6 @@ LJ_ASMF double lj_vm_trunc_hf(double);
#endif
#endif
LJ_ASMF double lj_vm_powi(double, int32_t);
#ifdef LUAJIT_NO_LOG2
LJ_ASMF double lj_vm_log2(double);
#else
#define lj_vm_log2 log2
#endif
#ifdef LUAJIT_NO_EXP2
LJ_ASMF double lj_vm_exp2(double);
#else

View File

@ -1468,7 +1468,28 @@ static void build_subroutines(BuildCtx *ctx)
| math_extern sqrt
|.endif
|
| math_extern log
|.ffunc math_log
|.if HFABI
| ldr CARG2, [BASE, #4]
| cmp NARGS8:RC, #8 // Need exactly 1 argument.
| vldr d0, [BASE]
| bne ->fff_fallback
|.else
| ldrd CARG12, [BASE]
| cmp NARGS8:RC, #8 // Need exactly 1 argument.
| bne ->fff_fallback
|.endif
| checktp CARG2, LJ_TISNUM
| bhs ->fff_fallback
| .IOS mov RA, BASE
| bl extern log
| .IOS mov BASE, RA
|.if HFABI
| b ->fff_resd
|.else
| b ->fff_restv
|.endif
|
| math_extern log10
| math_extern exp
| math_extern sin

View File

@ -1486,7 +1486,19 @@ static void build_subroutines(BuildCtx *ctx)
| math_round floor
| math_round ceil
|
| math_extern log
|.ffunc math_log
| lw CARG3, HI(BASE)
| li AT, 8
| bne NARGS8:RC, AT, ->fff_fallback // Exactly 1 argument.
|. load_got log
| sltiu AT, CARG3, LJ_TISNUM
| beqz AT, ->fff_fallback
|. nop
| call_extern
|. ldc1 FARG1, 0(BASE)
| b ->fff_resn
|. nop
|
| math_extern log10
| math_extern exp
| math_extern sin

View File

@ -1804,7 +1804,16 @@ static void build_subroutines(BuildCtx *ctx)
|.else
| math_extern sqrt
|.endif
| math_extern log
|
|.ffunc math_log
| cmplwi NARGS8:RC, 8
| lwz CARG3, 0(BASE)
| lfd FARG1, 0(BASE)
| bne ->fff_fallback // Need exactly 1 argument.
| checknum CARG3; bge ->fff_fallback
| blex log
| b ->fff_resn
|
| math_extern log10
| math_extern exp
| math_extern sin

View File

@ -1426,7 +1426,18 @@ static void build_subroutines(BuildCtx *ctx)
| math_round ceil
|
| math_extern sqrt
| math_extern log
|
|.ffunc math_log
| cmplwi NARGS8:RC, 8
| evldd CARG2, 0(BASE)
| bne ->fff_fallback // Need exactly 1 argument.
| checknum CARG2
| evmergehi CARG1, CARG2, CARG2
| checkfail ->fff_fallback
| bl extern log
| evmergelo CRET1, CRET1, CRET2
| b ->fff_restv
|
| math_extern log10
| math_extern exp
| math_extern sin

View File

@ -2045,7 +2045,12 @@ static void build_subroutines(BuildCtx *ctx)
|.else
|.ffunc_n math_sqrt; fsqrt; jmp ->fff_resn
|.endif
|.ffunc_n math_log, fldln2; fyl2x; jmp ->fff_resn
|
|.ffunc math_log
| cmp NARGS:RD, 1+1; jne ->fff_fallback // Exactly one argument.
| cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback
| fldln2; fld qword [BASE]; fyl2x; jmp ->fff_resn
|
|.ffunc_n math_log10, fldlg2; fyl2x; jmp ->fff_resn
|.ffunc_n math_exp; call ->vm_exp_x87; jmp ->fff_resn
|
@ -3157,6 +3162,29 @@ static void build_subroutines(BuildCtx *ctx)
| ret
|.endif
|
|// FP log2(x). Called by math.log(x, base).
|->vm_log2:
|.if X64WIN
| movsd qword [rsp+8], xmm0 // Use scratch area.
| fld1
| fld qword [rsp+8]
| fyl2x
| fstp qword [rsp+8]
| movsd xmm0, qword [rsp+8]
|.elif X64
| movsd qword [rsp-8], xmm0 // Use red zone.
| fld1
| fld qword [rsp-8]
| fyl2x
| fstp qword [rsp-8]
| movsd xmm0, qword [rsp-8]
|.else
| fld1
| fld qword [esp+4]
| fyl2x
|.endif
| ret
|
|// FP exponentiation e^x and 2^x. Called by math.exp fast function and
|// from JIT code. Arg/ret on x87 stack. No int/xmm regs modified.
|// Caveat: needs 3 slots on x87 stack!