Browse Source

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

Mike Pall 13 years ago
parent
commit
0561a56938
8 changed files with 129 additions and 11 deletions
  1. 16 1
      src/lib_math.c
  2. 22 0
      src/lj_ffrecord.c
  3. 5 5
      src/lj_vm.h
  4. 22 1
      src/vm_arm.dasc
  5. 13 1
      src/vm_mips.dasc
  6. 10 1
      src/vm_ppc.dasc
  7. 12 1
      src/vm_ppcspe.dasc
  8. 29 1
      src/vm_x86.dasc

+ 16 - 1
src/lib_math.c

@@ -33,7 +33,6 @@ LJLIB_ASM(math_sqrt)		LJLIB_REC(math_unary IRFPM_SQRT)
   lj_lib_checknum(L, 1);
   lj_lib_checknum(L, 1);
   return FFH_RETRY;
   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_log10)		LJLIB_REC(math_unary IRFPM_LOG10)
 LJLIB_ASM_(math_exp)		LJLIB_REC(math_unary IRFPM_EXP)
 LJLIB_ASM_(math_exp)		LJLIB_REC(math_unary IRFPM_EXP)
 LJLIB_ASM_(math_sin)		LJLIB_REC(math_unary IRFPM_SIN)
 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_frexp)
 LJLIB_ASM_(math_modf)		LJLIB_REC(.)
 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_PUSH(57.29577951308232)
 LJLIB_ASM_(math_deg)		LJLIB_REC(math_degrad)
 LJLIB_ASM_(math_deg)		LJLIB_REC(math_degrad)
 
 

+ 22 - 0
src/lj_ffrecord.c

@@ -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);
   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. */
 /* Record math.atan2. */
 static void LJ_FASTCALL recff_math_atan2(jit_State *J, RecordFFData *rd)
 static void LJ_FASTCALL recff_math_atan2(jit_State *J, RecordFFData *rd)
 {
 {

+ 5 - 5
src/lj_vm.h

@@ -60,6 +60,11 @@ LJ_ASMF double lj_vm_floor_hf(double);
 LJ_ASMF double lj_vm_ceil_hf(double);
 LJ_ASMF double lj_vm_ceil_hf(double);
 #endif
 #endif
 #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_HASJIT
 #if LJ_TARGET_X86ORX64
 #if LJ_TARGET_X86ORX64
@@ -80,11 +85,6 @@ LJ_ASMF double lj_vm_trunc_hf(double);
 #endif
 #endif
 #endif
 #endif
 LJ_ASMF double lj_vm_powi(double, int32_t);
 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
 #ifdef LUAJIT_NO_EXP2
 LJ_ASMF double lj_vm_exp2(double);
 LJ_ASMF double lj_vm_exp2(double);
 #else
 #else

+ 22 - 1
src/vm_arm.dasc

@@ -1468,7 +1468,28 @@ static void build_subroutines(BuildCtx *ctx)
   |  math_extern sqrt
   |  math_extern sqrt
   |.endif
   |.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 log10
   |  math_extern exp
   |  math_extern exp
   |  math_extern sin
   |  math_extern sin

+ 13 - 1
src/vm_mips.dasc

@@ -1486,7 +1486,19 @@ static void build_subroutines(BuildCtx *ctx)
   |  math_round floor
   |  math_round floor
   |  math_round ceil
   |  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 log10
   |  math_extern exp
   |  math_extern exp
   |  math_extern sin
   |  math_extern sin

+ 10 - 1
src/vm_ppc.dasc

@@ -1804,7 +1804,16 @@ static void build_subroutines(BuildCtx *ctx)
   |.else
   |.else
   |  math_extern sqrt
   |  math_extern sqrt
   |.endif
   |.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 log10
   |  math_extern exp
   |  math_extern exp
   |  math_extern sin
   |  math_extern sin

+ 12 - 1
src/vm_ppcspe.dasc

@@ -1426,7 +1426,18 @@ static void build_subroutines(BuildCtx *ctx)
   |  math_round ceil
   |  math_round ceil
   |
   |
   |  math_extern sqrt
   |  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 log10
   |  math_extern exp
   |  math_extern exp
   |  math_extern sin
   |  math_extern sin

+ 29 - 1
src/vm_x86.dasc

@@ -2045,7 +2045,12 @@ static void build_subroutines(BuildCtx *ctx)
   |.else
   |.else
   |.ffunc_n math_sqrt; fsqrt; jmp ->fff_resn
   |.ffunc_n math_sqrt; fsqrt; jmp ->fff_resn
   |.endif
   |.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_log10, fldlg2;	fyl2x;		jmp ->fff_resn
   |.ffunc_n math_exp;	call ->vm_exp_x87;	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
   |  ret
   |.endif
   |.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
   |// 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.
   |// from JIT code. Arg/ret on x87 stack. No int/xmm regs modified.
   |// Caveat: needs 3 slots on x87 stack!
   |// Caveat: needs 3 slots on x87 stack!