value_t quadlstep(const FUNC & f, const input_t & a, const input_t & b, const value_t &fa, const value_t& fb) { // recursive core routine for function quadl. // Evaluate integrand five times in interior of subinterval [a,b]. input_t d = b-a; input_t c = nt2::average(a, b); input_t h = d*Half<real_t>(); if (abs(h) < hmin_ || c == a || c == b ) //Minimum step size reached; singularity possible. { setwarn(1); return h*(fa+fb); } itab_t x = h*c1(); x = c+x; vtab_t y = f(x); fcnt_ += 5; if (fcnt_ > maxfcnt_){ setwarn(2); return h*(fa+fb); } // Maximum function count exceeded; singularity likely. itab_t x1 = nt2::cath(nt2::cath(a, x), b); x = x1; vtab_t y1 = nt2::cath(nt2::cath(fa, y), fb);y = y1; value_t Q1 = h*nt2::globalsum(lobatto()*y(_(1, 2, 7)))*c245_; // Four point Lobatto quadrature times 1470. value_t Q = h*nt2::globalsum(kronrod()*y); // Seven point Kronrod refinement times 1470. if (nt2::is_invalid(Q)) { setwarn(3); return Q; } // Infinite or Not-a-Number function value encountered. // Check accuracy of integral over this subinterval. real_t curerr = nt2::abs(Q1 - Q); if (curerr <= tol_*nt2::abs(h)) { err_+= curerr; setwarn(0); return Q; } else // % Subdivide into six subintervals. { setwarn(0); Q = Zero<value_t>(); for(size_t k = 1; k <= 6; ++k) { Q += quadlstep(f, x(k), x(k+1), y(k), y(k+1)); } return Q; } };
bool assembler::compile_call(asmgen & asg, const func_binary & fb, command cmd) { int calltype = COMMAND_CODE(GET_CMD(fb, m_pos)); m_pos++; if (calltype == CALL_FAKE) { setwarn(m_fk, "assembler not supprt fake call, change to normal call"); calltype = CALL_NORMAL; } if (calltype == CALL_NORMAL) { int callpos = 0; GET_VARIANT_POS(fb, callpos, m_pos); m_pos++; int retnum = COMMAND_CODE(GET_CMD(fb, m_pos)); m_pos++; std::vector<int> retvec; for (int i = 0; i < retnum; i++) { int ret = 0; GET_VARIANT_POS(fb, ret, m_pos); m_pos++; retvec.push_back(ret); } int argnum = COMMAND_CODE(GET_CMD(fb, m_pos)); m_pos++; // 1.塞参数 asg.variant_ps_clear(); for (int i = 0; i < argnum; i++) { int arg = 0; GET_VARIANT_POS(fb, arg, m_pos); m_pos++; asg.variant_push(arg); } // 2.准备调用函数 // 3.调用 asg.call_func_param2((void *)&machine::static_call, m_fk, callpos); // 4.处理返回值 for (int i = (int)retvec.size() - 1; i >= 0; i--) { int ret = retvec[i]; asg.variant_pop(ret); } // 5.清理不需要的 asg.variant_ps_clear(); } else if (calltype == CALL_CLASSMEM) { int callpos = 0; GET_VARIANT_POS(fb, callpos, m_pos); m_pos++; int retnum = COMMAND_CODE(GET_CMD(fb, m_pos)); m_pos++; std::vector<int> retvec; for (int i = 0; i < retnum; i++) { int ret = 0; GET_VARIANT_POS(fb, ret, m_pos); m_pos++; retvec.push_back(ret); } int argnum = COMMAND_CODE(GET_CMD(fb, m_pos)); m_pos++; // 0.取出实际的函数名 int classpos = 0; GET_VARIANT_POS(fb, classpos, m_pos + argnum - 1); int tmppos = 0; GET_TMP_POS(fb, tmppos); asg.call_func_param3((void*)&assembler_get_classmem_call, m_fk, classpos, callpos); asg.variant_from_rax(tmppos); // 1.塞参数 asg.variant_ps_clear(); for (int i = 0; i < argnum; i++) { int arg = 0; GET_VARIANT_POS(fb, arg, m_pos); m_pos++; asg.variant_push(arg); } // 2.准备调用函数 // 3.调用 asg.call_func_param2((void *)&machine::static_call, m_fk, tmppos); // 4.处理返回值 for (int i = (int)retvec.size() - 1; i >= 0; i--) { int ret = retvec[i]; asg.variant_pop(ret); } // 5.清理不需要的 asg.variant_ps_clear(); } return true; }
bool assembler::compile_next(asmgen & asg, const func_binary & fb) { command cmd = GET_CMD(fb, m_pos); int type = COMMAND_TYPE(cmd); int code = COMMAND_CODE(cmd); USE(type); FKLOG("[assembler] compile_next cmd %d %d %s", type, code, OpCodeStr(code)); assert (type == COMMAND_OPCODE); m_pos++; m_conposnum = 0; memset(m_conpos, 0, sizeof(m_conpos)); bool ret = false; USE(ret); // 执行对应命令,放一起switch效率更高,cpu有缓存 switch (code) { case OPCODE_ASSIGN: { ret = compile_assign(asg, fb, cmd); } break; case OPCODE_RETURN: { ret = compile_return(asg, fb, cmd); } break; case OPCODE_PLUS: case OPCODE_MINUS: case OPCODE_MULTIPLY: case OPCODE_DIVIDE: case OPCODE_DIVIDE_MOD: { ret = compile_math(asg, fb, cmd); } break; case OPCODE_PLUS_ASSIGN: case OPCODE_MINUS_ASSIGN: case OPCODE_MULTIPLY_ASSIGN: case OPCODE_DIVIDE_ASSIGN: case OPCODE_DIVIDE_MOD_ASSIGN: { ret = compile_math_assign(asg, fb, cmd); } break; case OPCODE_AND: case OPCODE_OR: case OPCODE_LESS: case OPCODE_MORE: case OPCODE_EQUAL: case OPCODE_MOREEQUAL: case OPCODE_LESSEQUAL: case OPCODE_NOTEQUAL: { ret = compile_cmp(asg, fb, cmd); } break; case OPCODE_AND_JNE: case OPCODE_OR_JNE: case OPCODE_LESS_JNE: case OPCODE_MORE_JNE: case OPCODE_EQUAL_JNE: case OPCODE_MOREEQUAL_JNE: case OPCODE_LESSEQUAL_JNE: case OPCODE_NOTEQUAL_JNE: { ret = compile_cmp_jne(asg, fb, cmd); } break; case OPCODE_NOT: { ret = compile_single(asg, fb, cmd); } break; case OPCODE_NOT_JNE: { ret = compile_single_jne(asg, fb, cmd); } break; case OPCODE_JNE: { ret = compile_jne(asg, fb, cmd); } break; case OPCODE_JMP: { ret = compile_jmp(asg, fb, cmd); } break; case OPCODE_CALL: { ret = compile_call(asg, fb, cmd); } break; case OPCODE_SLEEP: case OPCODE_YIELD: { setwarn(m_fk, "assembler only support SLEEP or YIELD, skip code"); ret = true; m_pos++; } break; case OPCODE_FORBEGIN: case OPCODE_FORLOOP: { FKERR("assembler dont support for i -> n, j"); compile_seterror(fb, cmd, efk_jit_error, "assembler dont support for i -> n, j"); return false; } break; default: assert(0); FKERR("[assembler] compile_next err code %d %s", code, OpCodeStr(code)); compile_seterror(fb, cmd, efk_jit_error, "compile_next err code %d %s", code, OpCodeStr(code)); return false; } return ret; }
/* * Sys call to allow users to find out * their current position wrt quota's * and to allow super users to alter it. */ qquota() { register struct a { int cmd; int uid; int arg; caddr_t addr; } *uap = (struct a *)u.u_ap; register struct quota *q; #ifndef QUOTA u.u_error = EINVAL; return; #else if (uap->uid < 0) uap->uid = u.u_ruid; if (uap->uid != u.u_ruid && uap->uid != u.u_quota->q_uid && !suser()) return; if (uap->cmd != Q_SYNC && uap->cmd != Q_SETUID) { q = getquota((uid_t)uap->uid, uap->cmd == Q_DOWARN, 0); if (q == NOQUOTA) { u.u_error = ESRCH; return; } if (u.u_error) goto bad; } switch (uap->cmd) { case Q_SETDLIM: u.u_error = setdlim(q, (dev_t)uap->arg, uap->addr); break; case Q_GETDLIM: u.u_error = getdlim(q, (dev_t)uap->arg, uap->addr); break; case Q_SETDUSE: u.u_error = setduse(q, (dev_t)uap->arg, uap->addr); break; case Q_SETWARN: u.u_error = setwarn(q, (dev_t)uap->arg, uap->addr); break; case Q_DOWARN: u.u_error = dowarn(q, (dev_t)uap->arg); break; case Q_SYNC: u.u_error = qsync((dev_t)uap->arg); return; case Q_SETUID: u.u_error = qsetuid((uid_t)uap->uid, uap->arg); return; default: u.u_error = EINVAL; break; } bad: delquota(q); #endif }