コード例 #1
0
unsigned LyricsMatchGrader::catagoryGrader(const std::multiset<std::string>& lyrics,
										   const std::string& queryWord) const
{
	unsigned int grade = DEFAULT_GRADE;
	size_t wordOccourences = lyrics.count(queryWord);

	if(QUERY_WORD_NOT_FOUND_FLAG != lyrics.count(queryWord))
	{
		grade = (this->getGradingCatagoryWeight()) * (wordOccourences);
	}

	return grade;
}
コード例 #2
0
ファイル: tptp.cpp プロジェクト: dddejan/CVC4
void Tptp::checkLetBinding(const std::vector<Expr>& bvlist, Expr lhs, Expr rhs,
                           bool formula) {
  if (lhs.getKind() != CVC4::kind::APPLY_UF) {
    parseError("malformed let: LHS must be a flat function application");
  }
  const std::multiset<CVC4::Expr> vars{lhs.begin(), lhs.end()};
  if(formula && !lhs.getType().isBoolean()) {
    parseError("malformed let: LHS must be formula");
  }
  for (const CVC4::Expr& var : vars) {
    if (var.hasOperator()) {
      parseError("malformed let: LHS must be flat, illegal child: " +
                 var.toString());
    }
  }

  // ensure all let-bound variables appear on the LHS, and appear only once
  for (const Expr& bound_var : bvlist) {
    const size_t count = vars.count(bound_var);
    if (count == 0) {
      parseError(
          "malformed let: LHS must make use of all quantified variables, "
          "missing `" +
          bound_var.toString() + "'");
    } else if (count >= 2) {
      parseError("malformed let: LHS cannot use same bound variable twice: " +
                 bound_var.toString());
    }
  }
}
コード例 #3
0
ファイル: Exercise 15.30.cpp プロジェクト: zpiao1/CPP-Primer
double Basket::total_receipt(ostream &os) const
{
    double sum = 0.0;
    for (auto iter = items.cbegin();
              iter != items.cend();
              iter = items.upper_bound(*iter)) {
        sum += print_total(os, **iter, items.count(*iter));
    }
    os << "Total Sale: " << sum << endl;
    return sum;
}
コード例 #4
0
ファイル: daemon.cpp プロジェクト: roastduck/YAUJ
		virtual bool cancel(int key)
		{
#ifdef DEBUG
			std::clog << "cancel" << std::endl;
#endif
			bool ret = false;
			pthread_mutex_lock(&cntLock);
			if (boardingPass.count(key))
				ret = true, boardingPass.erase(boardingPass.find(key));
			preserveCnt--;
			pthread_mutex_unlock(&cntLock);
			return ret;
		}
コード例 #5
0
double Basket::total() const
{
    double sum = 0.0;

    for(const_iter i = items.begin() ;  i != items.end() ; i = items.upper_bound(*i))
    {
        sum += (*i)->net_price(items.count(*i));
    }


    return sum;

}
コード例 #6
0
ファイル: converter_impl.hpp プロジェクト: 4og/guacamole
inline void converter<point_t>::knot_insertion(
    point_container_t& P,
    std::multiset<typename point_t::value_type>& knots,
    std::size_t order) const {
  //typedef typename point_t::value_type value_type;
  std::set<value_type> unique(knots.begin(), knots.end());

  for (typename std::set<value_type>::const_iterator i = unique.begin();
       i != unique.end();
       ++i) {
    if (knots.count(*i) < order - 1) {
      knot_insertion(P, knots, order, *i);
    }
  }
}
コード例 #7
0
ファイル: delua.cpp プロジェクト: Botje/residualvm-tools
void Decompiler::decompileRange(Byte *start, Byte *end) {
  // First, scan for IFFUPJMP, which is used for repeat/until, so
  // we can recognize the start of such loops.  We only keep the
  // last value to match each address, which represents the outermost
  // repeat/until loop starting at that point.
  std::map<Byte *, Byte *> rev_iffupjmp_map;

  for (Byte *scan = start; end == NULL || scan < end;
       scan += get_instr_len(*scan)) {
    if (*scan == IFFUPJMP)
      rev_iffupjmp_map[scan + 2 - scan[1]] = scan;
    else if (*scan == IFFUPJMPW)
      rev_iffupjmp_map[scan + 3 - (scan[1] | (scan[2] << 8))] = scan;
    else if (*scan == ENDCODE)
      break;
  }

  while (end == NULL || start < end) {
    int locs_here = local_var_defs->count(start);
    if (locs_here > 0) {
      // There were local variable slots just pushed onto the stack
      // Print them out (in the second pass)

      // First, if there are multiple defined, it must be from
      // local x, y, z = f() or local a, b.  So just ignore the extra
      // entries.
      for (int i = 1; i < locs_here; i++) {
	delete stk->top(); stk->pop();
      }
      Expression *def = stk->top(); stk->pop();

      // Print the local variable names, and at the same time push
      // fake values onto the stack
      *os << indent_str << "local ";
      for (int i = 0; i < locs_here; i++) {
	std::string locname = localname(tf, tf->code[1] + stk->size());
	*os << locname;
	if (i + 1 < locs_here)
	  *os << ", ";
	stk->push(new VarExpr(start, "<" + locname + " stack slot>"));
      }

      // Print the definition, unless it's nil
      VarExpr *v = dynamic_cast<VarExpr *>(def);
      if (v == NULL || v->name != "nil")
	*os << " = " << *def;
      *os << std::endl;
	  delete def;

      local_var_defs->erase(start);
    }

    if (rev_iffupjmp_map.find(start) != rev_iffupjmp_map.end()) {
      // aha, do a repeat/until loop
      *os << indent_str << "repeat\n";
      Decompiler indented_dc = *this;
      indented_dc.indent_str += std::string(4, ' ');
      indented_dc.break_pos = rev_iffupjmp_map[start];
      indented_dc.break_pos += get_instr_len(*indented_dc.break_pos);
      indented_dc.decompileRange(start, rev_iffupjmp_map[start]);

      Expression *e = stk->top(); stk->pop();
      *os << indent_str << "until " << *e << std::endl;
      delete e;

      start = indented_dc.break_pos;
      continue;
    }

    Byte opc = *start++;
    int aux;

    switch (opc) {
    case ENDCODE:
      return;

    case PUSHNIL:
      aux = *start++;
      goto pushnil;

    case PUSHNIL0:
      aux = 0;
    pushnil:
      for (int i = 0; i <= aux; i++)
	stk->push(new VarExpr(start, "nil")); // Cheat a little :)
      break;

    case PUSHNUMBER:
      aux = *start++;
      goto pushnumber;

    case PUSHNUMBER0:
    case PUSHNUMBER1:
    case PUSHNUMBER2:
      aux = opc - PUSHNUMBER0;
      goto pushnumber;

    case PUSHNUMBERW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    pushnumber:
      stk->push(new NumberExpr(start, aux));
      break;

    case PUSHCONSTANT:
      aux = *start++;
      goto pushconst;

    case PUSHCONSTANT0:
    case PUSHCONSTANT1:
    case PUSHCONSTANT2:
    case PUSHCONSTANT3:
    case PUSHCONSTANT4:
    case PUSHCONSTANT5:
    case PUSHCONSTANT6:
    case PUSHCONSTANT7:
      aux = opc - PUSHCONSTANT0;
      goto pushconst;

    case PUSHCONSTANTW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    pushconst:
      switch (ttype(tf->consts + aux)) {
      case LUA_T_STRING:
	stk->push(new StringExpr(start, tsvalue(tf->consts + aux)));
	break;
      case LUA_T_NUMBER:
	stk->push(new NumberExpr(start, nvalue(tf->consts + aux)));
	break;
      case LUA_T_PROTO:
	stk->push(new FuncExpr(start, tfvalue(tf->consts + aux), indent_str));
	break;
      default:
	*os << indent_str << "error: invalid constant type "
	    << int(ttype(tf->consts + aux)) << std::endl;
      }
      break;

    case PUSHUPVALUE:
      aux = *start++;
      goto pushupvalue;

    case PUSHUPVALUE0:
    case PUSHUPVALUE1:
      aux = opc - PUSHUPVALUE0;
    pushupvalue:
      {
	if (aux >= num_upvals) {
	  *os << indent_str << "error: invalid upvalue #"
	      << aux << std::endl;
	}

	std::ostringstream s;
	s << "%" << *upvals[aux];
	stk->push(new VarExpr(start, s.str()));
      }
      break;

    case PUSHLOCAL:
      aux = *start++;
      goto pushlocal;

    case PUSHLOCAL0:
    case PUSHLOCAL1:
    case PUSHLOCAL2:
    case PUSHLOCAL3:
    case PUSHLOCAL4:
    case PUSHLOCAL5:
    case PUSHLOCAL6:
    case PUSHLOCAL7:
      aux = opc - PUSHLOCAL0;
    pushlocal:
      stk->push(new VarExpr(start, localname(tf, aux)));
      break;

    case GETGLOBAL:
      aux = *start++;
      goto getglobal;

    case GETGLOBAL0:
    case GETGLOBAL1:
    case GETGLOBAL2:
    case GETGLOBAL3:
    case GETGLOBAL4:
    case GETGLOBAL5:
    case GETGLOBAL6:
    case GETGLOBAL7:
      aux = opc - GETGLOBAL0;
      goto getglobal;

    case GETGLOBALW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    getglobal:
      stk->push(new VarExpr(start, svalue(tf->consts + aux)));
      break;

    case GETTABLE:
      {
	Expression *index = stk->top(); stk->pop();
	Expression *table = stk->top(); stk->pop();

	stk->push(new BracketsIndexExpr(start, table, index));
      }
      break;

    case GETDOTTED:
      aux = *start++;
      goto getdotted;

    case GETDOTTED0:
    case GETDOTTED1:
    case GETDOTTED2:
    case GETDOTTED3:
    case GETDOTTED4:
    case GETDOTTED5:
    case GETDOTTED6:
    case GETDOTTED7:
      aux = opc - GETDOTTED0;
      goto getdotted;

    case GETDOTTEDW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    getdotted:
      {
	Expression *tbl = stk->top(); stk->pop();
	stk->push(new DotIndexExpr(start, tbl, new StringExpr
				(start, tsvalue(tf->consts + aux))));
      }
      break;

    case PUSHSELF:
      aux = *start++;
      goto pushself;

    case PUSHSELF0:
    case PUSHSELF1:
    case PUSHSELF2:
    case PUSHSELF3:
    case PUSHSELF4:
    case PUSHSELF5:
    case PUSHSELF6:
    case PUSHSELF7:
      aux = opc - PUSHSELF0;
      goto pushself;

    case PUSHSELFW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    pushself:
      {
	Expression *tbl = stk->top(); stk->pop();
	stk->push(new SelfExpr(start, tbl, new StringExpr
			       (start, tsvalue(tf->consts + aux))));
	stk->push(new VarExpr(start, "<self>"));
	// Fake value, FuncCallExpr will handle it
      }
      break;

    case CREATEARRAY:
      start++;
      goto createarray;

    case CREATEARRAY0:
    case CREATEARRAY1:
      goto createarray;

    case CREATEARRAYW:
      start += 2;
    createarray:
      stk->push(new ArrayExpr(start));
      break;

    case SETLOCAL:
    case SETLOCAL0:
    case SETLOCAL1:
    case SETLOCAL2:
    case SETLOCAL3:
    case SETLOCAL4:
    case SETLOCAL5:
    case SETLOCAL6:
    case SETLOCAL7:
    case SETGLOBAL:
    case SETGLOBAL0:
    case SETGLOBAL1:
    case SETGLOBAL2:
    case SETGLOBAL3:
    case SETGLOBAL4:
    case SETGLOBAL5:
    case SETGLOBAL6:
    case SETGLOBAL7:
    case SETGLOBALW:
    case SETTABLE0:
    case SETTABLE:
      start--;
      do_multi_assign(start);
      break;

    case SETLIST:
      start++;			// assume offset is correct
      goto setlist;

    case SETLISTW:
      start += 2;

    case SETLIST0:
    setlist:
      aux = *start++;
      {
	ArrayExpr::mapping_list new_mappings;
	for (int i = 0; i < aux; i++) {
	  Expression *val = stk->top(); stk->pop();
	  new_mappings.push_front(std::make_pair((Expression *) NULL, val));
	}
	ArrayExpr *a = dynamic_cast<ArrayExpr *>(stk->top());
	if (a == NULL) {
	  *os << indent_str
	      << "error: attempt to setlist a non-array object\n";
	}
	// Append the new list
	a->mappings.splice(a->mappings.end(), new_mappings);
	a->pos = start;
      }
      break;

    case SETMAP:
      aux = *start++;
      goto setmap;

    case SETMAP0:
      aux = 0;
    setmap:
      {
	ArrayExpr::mapping_list new_mappings;
	for (int i = 0; i <= aux; i++) {
	  Expression *val = stk->top(); stk->pop();
	  Expression *key = stk->top(); stk->pop();
	  new_mappings.push_front(std::make_pair(key, val));
	}
	ArrayExpr *a = dynamic_cast<ArrayExpr *>(stk->top());
	if (a == NULL) {
	  *os << indent_str
	      << "error: attempt to setmap a non-array object\n";
	}
	// Append the new list
	a->mappings.splice(a->mappings.end(), new_mappings);
	a->pos = start;
      }
      break;

    case EQOP:
      do_binary_op(start, 1, false, " == ");
      break;

    case NEQOP:
      do_binary_op(start, 1, false, " ~= ");
      break;

    case LTOP:
      do_binary_op(start, 1, false, " < ");
      break;

    case LEOP:
      do_binary_op(start, 1, false, " <= ");
      break;

    case GTOP:
      do_binary_op(start, 1, false, " > ");
      break;

    case GEOP:
      do_binary_op(start, 1, false, " >= ");
      break;

    case ADDOP:
      do_binary_op(start, 3, false, " + ");
      break;

    case SUBOP:
      do_binary_op(start, 3, false, " - ");
      break;

    case MULTOP:
      do_binary_op(start, 4, false, " * ");
      break;

    case DIVOP:
      do_binary_op(start, 4, false, " / ");
      break;

    case POWOP:
      do_binary_op(start, 6, true, " ^ ");
      break;

    case CONCOP:
      do_binary_op(start, 2, false, " .. ");
      break;

    case MINUSOP:
      do_unary_op(start, 5, "-");
      break;

    case NOTOP:
      do_unary_op(start, 5, "not ");
      break;

    case ONTJMP:
      aux = *start++;
      goto ontjmp;

    case ONTJMPW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    ontjmp:
      // push_expr_1 ontjmp(label) push_expr_2 label:  -> expr_1 || expr_2
      decompileRange(start, start + aux);
      do_binary_op(start + aux, 0, false, " or ");
      start = start + aux;
      break;

    case ONFJMP:
      aux = *start++;
      goto onfjmp;

    case ONFJMPW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    onfjmp:
      // push_expr_1 onfjmp(label) push_expr_2 label:  -> expr_2 && expr_2
      decompileRange(start, start + aux);
      do_binary_op(start + aux, 0, false, " and ");
      start = start + aux;
      break;

    case JMP:
      aux = *start++;
      goto jmp;

    case JMPW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    jmp:
      {
	Byte *dest = start + aux;
	if (dest == break_pos) {
	  *os << indent_str << "break\n";
	  break;
	}

	// otherwise, must be the start of a while statement
	Byte *while_cond_end;
	for (while_cond_end = dest; end == NULL || while_cond_end < end;
	     while_cond_end += get_instr_len(*while_cond_end))
	  if (*while_cond_end == IFTUPJMP || *while_cond_end == IFTUPJMPW)
	    break;
	if (end != NULL && while_cond_end >= end) {
	  *os << indent_str
	      << "error: JMP not in break, while, if/else\n";
	}

	// push the while condition onto the stack
	decompileRange(dest, while_cond_end);

	*os << indent_str << "while " << *stk->top()
	    << " do\n";
	delete stk->top();
	stk->pop();

	// decompile the while body
	Decompiler indented_dc = *this;
	indented_dc.indent_str += std::string(4, ' ');
	indented_dc.break_pos = while_cond_end + get_instr_len(*while_cond_end);
	indented_dc.decompileRange(start, dest);

	*os << indent_str << "end\n";
	start = indented_dc.break_pos;
      }
      break;

    case IFFJMP:
      aux = *start++;
      goto iffjmp;

    case IFFJMPW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    iffjmp:
      {
	// Output an if/end, if/else/end, if/elseif/else/end, ... statement
	Byte *if_part_end = start + aux;
	Decompiler indented_dc = *this;
	indented_dc.indent_str += std::string(4, ' ');

	*os << indent_str << "if " << *stk->top();
	delete stk->top();
	stk->pop();
	*os << " then\n";

	bool has_else;
	Byte *else_part_end;
	get_else_part(start, if_part_end, has_else, else_part_end);

	// Output the if part
      output_if:
	indented_dc.decompileRange(start, if_part_end);
	start = start + aux;

	if (has_else) {
	  // Check whether the entire else part is a single
	  // if or if/else statement
	  Byte *instr_scan = start;
	  while (is_expr_opc(*instr_scan) &&
		 (end == NULL || instr_scan < else_part_end))
	    instr_scan += get_instr_len(*instr_scan);
	  if ((end == NULL || instr_scan < else_part_end) &&
	      (*instr_scan == IFFJMP || *instr_scan == IFFJMPW)) {
	    // OK, first line will be if, check if it will go all
	    // the way through
	    Byte *new_start, *new_if_part_end, *new_else_part_end;
	    bool new_has_else;
	    if (*instr_scan == IFFJMP) {
	      aux = instr_scan[1];
	      new_start = instr_scan + 2;
	    }
	    else {
	      aux = instr_scan[1] | (instr_scan[2] << 8);
	      new_start = instr_scan + 3;
	    }
	    new_if_part_end = new_start + aux;
	    get_else_part(new_start, new_if_part_end, new_has_else,
			  new_else_part_end);
	    if (new_if_part_end == else_part_end ||
		(new_has_else && new_else_part_end == else_part_end)) {
	      // Yes, output an elseif
	      decompileRange(start, instr_scan); // push condition
	      *os << indent_str << "elseif " << *stk->top() << " then\n";
	      delete stk->top();
	      stk->pop();

	      start = new_start;
	      if_part_end = new_if_part_end;
	      has_else = new_has_else;
	      else_part_end = new_else_part_end;
	      goto output_if;
	    }
	  }
	  *os << indent_str << "else\n";
	  indented_dc.decompileRange(start, else_part_end);
	  start = else_part_end;
	}
	*os << indent_str << "end\n";
      }
      break;

    case CLOSURE:
      aux = *start++;
      goto closure;

    case CLOSURE0:
    case CLOSURE1:
      aux = opc - CLOSURE0;
    closure:
      {
	FuncExpr *f = dynamic_cast<FuncExpr *>(stk->top());
	if (f == NULL) {
	  *os << indent_str
	      << "error: closure requires a function\n";
	}
	stk->pop();
	f->num_upvals = aux;
	f->upvals = new Expression*[aux];
	for (int i = aux - 1; i >= 0; i--) {
	  f->upvals[i] = stk->top(); stk->pop();
	}
	stk->push(f);
      }
      break;

    case CALLFUNC:
      aux = *start++;
      goto callfunc;

    case CALLFUNC0:
    case CALLFUNC1:
      aux = opc - CALLFUNC0;
    callfunc:
      {
	int num_args = *start++;
	FuncCallExpr *e = new FuncCallExpr(start);
	e->num_args = num_args;
	e->args = new Expression*[num_args];
	for (int i = num_args - 1; i >= 0; i--) {
	  e->args[i] = stk->top();
	  stk->pop();
	}
	e->func = stk->top();
	stk->pop();
	if (aux == 0) {
	  *os << indent_str << *e << std::endl;
	  delete e;
	}
	else if (aux == 1 || aux == 255) // 255 for return f()
	  stk->push(e);
	else {
	  stk->push(e);
	  for (int i = 1; i < aux; i++)
	    stk->push(new VarExpr(start, "<extra result>"));
	}
      }
      break;

    case RETCODE:
      {
	int num_rets = stk->size() + tf->code[1] - *start++;
	ExprStack rets;

	for (int i = 0; i < num_rets; i++) {
	  rets.push(stk->top());
	  stk->pop();
	}
	*os << indent_str << "return";
	for (int i = 0; i < num_rets; i++) {
	  *os << " " << *rets.top();
	  delete rets.top();
	  rets.pop();
	  if (i + 1 < num_rets)
	    *os << ",";
	}
	*os << std::endl;
      }
      break;

    case SETLINE:
      aux = *start++;
      goto setline;

    case SETLINEW:
      aux = start[0] | (start[1] << 8);
      start += 2;
    setline:
      break;			// ignore line info

    case POP:
      aux = *start++;
      goto pop;

    case POP0:
    case POP1:
      aux = opc - POP0;
    pop:
      for (int i = 0; i <= aux; i++) {
	local_var_defs->insert(stk->top()->pos);
	delete stk->top(); stk->pop();
      }
      break;

    //Nop
    default:
      break;
    }
  }
}
コード例 #8
0
ファイル: daemon.cpp プロジェクト: roastduck/YAUJ
		virtual Json::Value run(int key, int pid, int sid, const Json::Value &submission)
		{
#ifdef DEBUG
			std::clog << "run" << std::endl;
			std::clog << " pid=" << pid << " sid=" << sid << " key=" << key << std::endl;
#endif
			pthread_mutex_lock(&cntLock);
			if (!boardingPass.count(key))
			{
				pthread_mutex_unlock(&cntLock);
				Json::Value ret;
				ret["error"] = "not preserved";
				return ret;
			}
			boardingPass.erase(boardingPass.find(key));
			runningCnt++, totCnt++;
			const int _totCnt_ = totCnt;
			pthread_mutex_unlock(&cntLock);
			
			Json::Value ret;
			std::ostringstream ss;
			ss << runPath << "/" << _totCnt_;
			std::string runDir = ss.str();
			pthread_mutex_lock(&cmdLock);
#ifdef DEBUG
			std::clog << "mkdir -p "+runDir << std::endl;
#endif
			system(("mkdir -p "+runDir).c_str());
#ifdef DEBUG
			std::clog << "rm -r "+runDir+"/*" << std::endl;
#endif
			system(("rm -r "+runDir+"/*").c_str());
			pthread_mutex_unlock(&cmdLock);
			try
			{
				ss.str("");
				ss << "cp " + dataPath + "/" << pid << "/* " << runDir;
				pthread_mutex_lock(&syncLock);
				if (syncing.count(pid)) pthread_mutex_unlock(&syncLock), throw std::string("data updated when copying files.");
#ifdef DEBUG
				std::clog << ss.str() << std::endl;
#endif
				pthread_mutex_lock(&cmdLock), system(ss.str().c_str()), pthread_mutex_unlock(&cmdLock);
				pthread_mutex_unlock(&syncLock);
				ss.str("");
				ss << "cp " + sourcePath + "/" << sid/10000 << '/' << sid%10000 << "/* " << runDir;
#ifdef DEBUG
				std::clog << ss.str() << std::endl;
#endif
				pthread_mutex_lock(&cmdLock), system((ss.str()).c_str()), pthread_mutex_unlock(&cmdLock);
				ss.str("");
				ss << "./yauj_judge run";
				for (Json::Value::const_iterator i=submission.begin(); i!=submission.end(); i++)
					ss << " " << (*i)["language"].asString() << " " << (*i)["source"].asString();
				ret=dumpCmd(ss.str(),runDir);
#ifndef NCLEAN
				pthread_mutex_lock(&cmdLock), system(("rm -r "+runDir).c_str()), pthread_mutex_unlock(&cmdLock);
#endif
			} catch (std::string &e)
			{
#ifdef DEBUG
				std::clog << " run: catched " << e << std::endl;
#endif
				pthread_mutex_lock(&cntLock);
				runningCnt--, preserveCnt--;
				pthread_mutex_unlock(&cntLock);
				ret["error"] = e;
				return ret;
			}
			pthread_mutex_lock(&cntLock);
			runningCnt--, preserveCnt--;
			pthread_mutex_unlock(&cntLock);
			return ret;
		}
コード例 #9
0
ファイル: converter_impl.hpp プロジェクト: 4og/guacamole
inline void converter<point_t>::knot_insertion(point_container_t& P,
                                               std::multiset<value_type>& knots,
                                               std::size_t order,
                                               value_type t) const {
  typedef typename point_t::value_type value_type;

  // copy knotvector for subscript [] access
  std::vector<value_type> kv_cpy(knots.begin(), knots.end());
  // get parameter
  std::size_t p = order - 1;                        // degree
  std::size_t s = knots.count(t);                   // multiplicity
  std::size_t r = std::max(std::size_t(0), p - s);  // number of insertions

  // get knotspan
  std::size_t k = std::distance(knots.begin(), knots.upper_bound(t));
  std::size_t np = P.size();  // number of control points

  // start computation
  std::size_t nq = np + r;

  // helper arrays
  std::vector<point_t> Qw(nq);
  std::vector<point_t> Rw(p - s + 1);

  // copy unaffected points and transform into homogenous coords
  for (size_t i = 0; i <= k - p; ++i) {
    Qw[i] = P[i].as_homogenous();
  }
  for (size_t i = k - s - 1; i <= np - 1; ++i) {
    Qw[i + r] = P[i].as_homogenous();
  }

  // helper points
  for (size_t i = 0; i <= p - s; ++i) {
    Rw[i] = P[k - p + i - 1].as_homogenous();
  }

  // do knot insertion itself
  std::size_t L = 0;
  for (std::size_t j = 1; j <= r; ++j) {
    L = k - p + j;
    for (std::size_t i = 0; i <= p - j - s; ++i) {
      value_type alpha =
          (t - kv_cpy[L + i - 1]) / (kv_cpy[i + k] - kv_cpy[L + i - 1]);
      Rw[i] = alpha * Rw[i + 1] + value_type(1.0 - alpha) * Rw[i];
    }
    Qw[L - 1] = Rw[0];
    Qw[k + r - j - s - 1] = Rw[p - j - s];
  }

  // insert knots
  for (std::size_t i = 0; i < r; ++i) {
    knots.insert(t);
  }

  // copy new control points
  P.clear();

  // transform back to euclidian space
  for (typename std::vector<point_t>::iterator i = Qw.begin(); i != Qw.end();
       ++i) {
    P.push_back((*i).as_euclidian());
  }
}