コード例 #1
0
ファイル: opcode_chain.c プロジェクト: bl0b/tinyaml
void opcode_chain_serialize(opcode_chain_t oc, opcode_dict_t od, program_t p, void* dl_handle) {
	slist_node_t sn;
	opcode_chain_node_t ocn;
	word_t ofs = program_get_code_size(p), backup=ofs, code_sz=0, data_sz=0;

	/*
	 * 1st pass : compute labels addresses and init data segment
	 */
	sn = list_head(oc);
	while(sn!=NULL) {
		ocn = node_value(opcode_chain_node_t,sn);
		switch(ocn->type) {
		case NodeLabel:
			ocn->lofs=ofs;
			program_add_label(p,ofs,ocn->name);
			break;
		case NodeData:
			data_sz+= 2*atoi(ocn->arg);
			/*vm_printf("data rep %i\n",atoi(ocn->arg));*/
			break;
		case NodeOpcode:
			ofs+=2;	/* two words per instruction */
			code_sz+=2;
			break;
		case NodeLangPlug:
		case NodeLangDef:
		default:;
		};
		sn=sn->next;
	}

	/* reserve segments sizes */

	program_reserve_code(p, code_sz);
	program_reserve_data(p, data_sz?2+data_sz:0);

	/*
	 * 2nd pass : serialize opcodes
	 */
	ofs=backup;
	sn = list_head(oc);
	while(sn!=NULL) {
		ocn = node_value(opcode_chain_node_t,sn);
		if(ocn->type==NodeOpcode) {
			opcode_serialize(od,oc,ofs,ocn,p,dl_handle);
			ofs+=2;
		} else if(ocn->type==NodeData) {
			long rep = atoi(ocn->arg);
			word_t dat = str2data(p,(vm_data_type_t)ocn->arg_type,ocn->name);
			dynarray_t data_seg = &p->data;
			while(rep>0) {
				dynarray_set(data_seg,dynarray_size(data_seg), ocn->arg_type);
				dynarray_set(data_seg,dynarray_size(data_seg), dat);
				rep-=1;
			}
		}
		sn=sn->next;
	}
}
コード例 #2
0
ファイル: thread.c プロジェクト: bl0b/tinyaml
long mutex_unlock(vm_t vm, mutex_t m, thread_t t) {
	/*vm_printf("MUTEX UNLOCK :: thread %p attempts to unlock mutex %p owned by %p\n",t,m,m->owner);*/
	if(m->owner!=t) {
		if(!m->owner) {
			_vm_assert_fail("Trying to unlock a mutex owned by nobody.\n", __FILE__, __LINE__, __func__);
		} else {
			static char err_msg[80];
			sprintf(err_msg, "[VM::ERR] : trying to unlock a mutex that is owned by another thread (%p).\n",m->owner);
			_vm_assert_fail(err_msg, __FILE__, __LINE__, __func__);
		}
	} else if(m->count>0) {
		m->count-=1;
	}
	if(!(m->owner&&m->count)) {
		thread_t pending;
		dlist_node_t dn;
		m->owner=NULL;
		while(m->pending.head) {
			dn = m->pending.head;
			m->pending.head=dn->next;
			pending = node_value(thread_t,dn);
			if(dn->next) {
				dn->next->prev=NULL;
			} else {
				m->pending.tail=NULL;
			}
			/*vm_printf("mutex unlock : unblocking thread %p\n",t);*/
			thread_set_state(vm, pending, ThreadReady);
			if(pending->prio>=t->prio) {
				t->remaining=0;
			}
		}
	}
	return m->count;
}
コード例 #3
0
ファイル: builtins.c プロジェクト: 74AC153/paren
static
eval_err_t do_mathop(memory_state_t *ms, node_t **args, node_t **out, void *p)
{
	mathop_t fn = (mathop_t) p;

	if(node_type(args[0]) != NODE_VALUE) {
		*out = args[0];
		return eval_err(EVAL_ERR_EXPECTED_VALUE);
	}
	if(node_type(args[1]) != NODE_VALUE) {
		*out = args[1];
		return eval_err(EVAL_ERR_EXPECTED_VALUE);
	}
	fn(ms, node_value(args[0]), node_value(args[1]), out);
	return EVAL_OK;

}
コード例 #4
0
ファイル: player.c プロジェクト: bsurmanski/bigheadAdventure
static void draw_particles()
{
    Particle *p;
    Node *current_node = list_first_node(particles);
    int OFFSETX, OFFSETY;

    while(current_node){
        p = (Particle*) node_value(current_node);
        p->draw(p);
        current_node = node_next(current_node);
    }
}
コード例 #5
0
ファイル: opcode_chain.c プロジェクト: bl0b/tinyaml
word_t opcode_label_to_ofs(opcode_chain_t oc, const char* label) {
	slist_node_t sn;
	opcode_chain_node_t ocn;

	sn = list_head(oc);
	while(sn!=NULL) {
		ocn = node_value(opcode_chain_node_t,sn);
		if(ocn->type==NodeLabel&&!strcmp(ocn->name,label)) {
			return ocn->lofs;
		}
		sn=sn->next;
	}
	return 0;
}
コード例 #6
0
ファイル: node_test.c プロジェクト: maxenglander/algo1
int main() {
  int a = 5;
  int b = 10;

  Node* node_a = node_create(&a);
  Node* node_b = node_create(&b);
  
  assert(&a == node_value(node_a));
  assert(&b == node_value(node_b));

  assert(NULL == node_next(node_a));
  assert(NULL == node_next(node_b));

  node_set_next(node_a, node_b);

  assert(node_b == node_next(node_a));
  assert(NULL == node_next(node_b));

  node_destroy(node_a);
  node_destroy(node_b);

  return 0;
}
コード例 #7
0
ファイル: symtab.c プロジェクト: Starlink/starlink
/******************************************************************************
 *
 *	PUT_VALUE (symtab *symb, char *name, int type, value val)
 *
 * Stores a given value under the given name, with the given symbol type in
 * the given symbol table.
 *
 * If the symbol already exists, the same node object is used,  so that
 * pointers to the symbol table entry will point at the new value. I don't
 * believe anything relies on this currently.
 * put_value() exists because it is common to change a value in a variable.
 * This avoids creating and freeing a node object on every assignment.
 * If a node value is changed, the interpreter function is changed so that,
 * if the node is interpreted, the correct thing happens.
 *
 * Returns the value assigned (or exception if failed to assign).
 *
 ******************************************************************************
 */
static value
put_value(symtab * symb, char *name, int type, value val)
{
    node *found;
    char buf[512];

    if ((found = get_symbol(symb, name, type)) != NODENIL) {
	found->val = val;
	switch (thetypeof(val)) {
	  case TYPE_INTEGER:
	    found->interpret = integer_interpret;
	    return (val);
	  case TYPE_REAL:
	    found->interpret = real_interpret;
	    return (val);
	  case TYPE_LOGICAL:
	    found->interpret = logical_interpret;
	    return (val);
	  case TYPE_STRING:
	    found->interpret = string_interpret;
	    return (val);
	  case TYPE_FUNCTION:
	    found->interpret = builtin_interpret;
	    return (val);
	  case TYPE_FILE:
	    found->interpret = 0;
	    return (val);
	  default:
	    sprintf(buf,
		"put_value: assigning an unknown value type %d\n",
		thetypeof(found->val));
	    systemfail(buf);
	    return (val); /* for lint */
	}
    } else {
	node *valuenode = node_value(val);
	symtab *sym = new_symtab(name, type, valuenode);

	if (valuenode == NODENIL || sym == SYMBNIL)
	    return (exception("SYSERR  memory exhausted in put_value()"));
	else {
	    sym->next = symb->next;
	    sym->prev = symb;
	    symb->next->prev = sym;
	    symb->next = sym;
	    return (val);
	}
    }
}
コード例 #8
0
ファイル: xml.c プロジェクト: imp/slist
tgt_node_t *
tgt_node_alloc(char *name, xml_val_type_t type, void *value)
{
	tgt_node_t	*d		= node_alloc();
	int		value_len	= 0;
	char		*value_str	= NULL;

	if (d == NULL)
		return (NULL);
	switch (type) {
	case String:
		if (value)
			value_len = strlen((char *)value) + 1;
		break;
	case Int:
		value_len = sizeof (int) * 2 + 3;
		break;
	case Uint64:
		value_len = sizeof (uint64_t) * 2 + 3;
		break;
	}
	if (value_len &&
	    (value_str = (char *)calloc(sizeof (char), value_len)) == NULL)
		return (NULL);
	if (node_name(d, (xmlChar *)name) == False) {
		free(value_str);
		return (NULL);
	}
	if (value_str) {
		switch (type) {
		case String:
			(void) snprintf(value_str, value_len, "%s",
			    (char *)value);
			break;
		case Int:
			(void) snprintf(value_str, value_len, "%d",
			    *(int *)value);
			break;
		case Uint64:
			(void) snprintf(value_str, value_len, "0x%llx",
			    *(uint64_t *)value);
			break;
		}
	}
	(void) node_value(d, (xmlChar *)value_str, True);
	free(value_str);

	return (d);
}
コード例 #9
0
ファイル: builtins.c プロジェクト: 74AC153/paren
static
eval_err_t do_makesym(memory_state_t *ms, node_t **args, node_t **out, void *p)
{
	char name[MAX_SYM_LEN], *cursor;;
	node_t *val, *val_iter;

	(void) p;
	val = args[0];
	if(node_type(val) != NODE_CONS) {
		*out = val;
		return eval_err(EVAL_ERR_EXPECTED_CONS);
	}
	
	val_iter = val;
	cursor = name;
	for(val_iter = val; val_iter; val_iter = node_cons_cdr(val_iter)) {
		val = node_cons_car(val_iter);
		if(node_type(val) != NODE_VALUE) {
			*out = val;
			return eval_err(EVAL_ERR_EXPECTED_VALUE);
		}
		if(node_value(val) > 255 ) {
			*out = val;
			return eval_err(EVAL_ERR_VALUE_BOUNDS);
		}
		*cursor++ = node_value(val);
		if(cursor - &(name[0]) >= (ssize_t) sizeof(name)) {
			break;
		}
		val_iter = node_cons_cdr(val_iter);
	}
	*cursor = 0;
	*out = node_symbol_new(ms, name);

	return EVAL_OK;
}
コード例 #10
0
/**
 * Updates a particle array (eg blood). will move the particles according to
 * the particles velocity, and if a particle hits a solid block, will stop
 * the particle.
 */
static void update_particles()
{
    Particle *p;
    Node *current_node = list_first_node(particles);
    while(current_node){
        p = node_value(current_node);
        if(p->update(p)){
            Node *next = node_next(current_node);
            list_remove(particles, current_node);
            current_node = next;
        } else {
            current_node = node_next(current_node);
        }
    }
}
コード例 #11
0
ファイル: player.c プロジェクト: bsurmanski/bigheadAdventure
/**
 * Updates a particle array (eg blood). will move the particles according to
 * the particles velocity, and if a particle hits a solid block, will stop
 * the particle.
 */
static void update_particles()
{
    Particle *p;
    Node *current_node = list_first_node(particles);
    if (SDL_MUSTLOCK(map_buffer)) SDL_LockSurface(map_buffer);
    while(current_node){
        p = node_value(current_node);
        if(p->update(p)){
            Node *next = node_next(current_node);
            list_remove(particles, current_node);
            current_node = next;
        } else {
            current_node = node_next(current_node);
        }
    }
    if (SDL_MUSTLOCK(map_buffer)) SDL_UnlockSurface(map_buffer);
}
コード例 #12
0
ファイル: NeuronNetwork.hpp プロジェクト: lstavr/BridgewellML
 void predict(Matrix<IndexType, ItorType>* m, double* y) {
   if (m->getNFeature() != nnode[nlayer - 1]) throw std::invalid_argument("Inconsistent nfeature");
   typedef std::vector<double> NumVec;
   typedef std::vector<NumVec> NumVecVec;
   #pragma omp parallel
   {
     NumVecVec node_value(nlayer - 1, NumVec());
     for(IndexType i = 0;i + 1 < nlayer;i++) {
       node_value[i].resize(nnode[i], 0.0);
     }
     #pragma omp for
     for(IndexType instance_id = 0;instance_id < m->getNInstance();instance_id++) {
       for(IndexType l = nlayer - 1;l > 0;l--) { // l \in [1, nlayer - 1]
         for(IndexType ll = 0;ll < nnode[l - 1];ll++) {
           // ll \in [0, nnode[l - 1]]
           node_value[l - 1][ll] = 0;
         }
         IndexType ln = nnode[l];
         if (l == nlayer - 1) {
           // last layer
           for(ItorType iter = m->getFeatureItorBegin(instance_id);iter < m->getFeatureItorEnd(instance_id);iter++) {
             IndexType feature_id = m->getFeatureId(iter);
             double value = m->getValue(iter);
             for(IndexType ll = 0;ll < nnode[l - 1];ll++) {
               double w = ftprl->get_w(z[l - 1][ll * ln + feature_id], n[l - 1][ll * ln + feature_id]);
               // ll \in [0, nnode[l - 1]]
               node_value[l - 1][ll] += value * w;
             }
           }
         } else { // l < nlayer - 1
           for(IndexType feature_id = 0;feature_id < nnode[l];feature_id++) {
             double value = node_value[l][feature_id];
             for(IndexType ll = 0;ll < nnode[l - 1];ll++) {
               double w = ftprl->get_w(z[l - 1][ll * ln + feature_id], n[l - 1][ll * ln + feature_id]);
               node_value[l - 1][ll] += value * w;
             }
           }
         } // l < nlayer - 1
         for(IndexType ll = 0;ll < nnode[l - 1];ll++) {
           node_value[l - 1][ll] = sigma(node_value[l - 1][ll]);
         }
       } // l
       y[instance_id] = node_value[0][0];
     }
   }
 }
コード例 #13
0
ファイル: xml.c プロジェクト: imp/slist
tgt_node_t *
tgt_node_dup(tgt_node_t *n)
{
	tgt_node_t	*d = node_alloc();
	tgt_node_t	*c;

	if (d == NULL)
		return (NULL);
	if (node_name(d, (xmlChar *)n->x_name) == False)
		return (NULL);
	if (n->x_value && (node_value(d, (xmlChar *)n->x_value, True) == False))
		return (NULL);
	for (c = n->x_child; c; c = c->x_sibling)
		(void) tgt_node_add(d, tgt_node_dup(c));
	for (c = n->x_attr; c; c = c->x_sibling)
		(void) tgt_node_add_attr(d, tgt_node_dup(c));
	return (d);
}
コード例 #14
0
ファイル: xml.c プロジェクト: imp/slist
Boolean_t
tgt_node_process(xmlTextReaderPtr r, tgt_node_t **node)
{
	const xmlChar	*name;
	const xmlChar	*value;
	char		**ap;
	xmlElementType	node_type;
	tgt_node_t	*n;
	tgt_node_t	*an;

	n = *node;
	if (n == NULL) {
		n = node_alloc();
		if (n == NULL)
			return (False);
		*node = n;
	}

	name = (xmlChar *)xmlTextReaderConstName(r);
	if (name == NULL) {
		node_free(n);
		*node = NULL;
		return (False);
	}

	node_type = (xmlElementType)xmlTextReaderNodeType(r);

	value = (xmlChar *)xmlTextReaderConstValue(r);

	if (node_type == XML_ELEMENT_NODE) {
		if (n->x_state != NodeAlloc) {
			n = node_child(n);
			*node = n;
			if (n == NULL)
				return (False);
		}
		if (xmlTextReaderAttributeCount(r) > 0) {

			for (ap = common_attr_list; *ap; ap++) {
				value = xmlTextReaderGetAttribute(r,
				    (xmlChar *)*ap);

				if (value != NULL) {
					if ((an = node_alloc_attr(n)) == NULL)
						return (False);
					if (node_name(an, (xmlChar *)*ap) ==
					    False) {
						node_free(an);
						return (False);
					}
					if (node_value(an, value, True) ==
					    False) {
						node_free(an);
						return (False);
					}
					free((char *)value);
				}
			}
		}

		if (node_name(n, name) == False) {
			node_free(n);
			*node = NULL;
			return (False);
		}
	} else if ((value != NULL) && (node_type == XML_TEXT_NODE)) {
		if (node_value(n, value, True) == False) {
			node_free(n);
			*node = NULL;
			return (False);
		}
	} else if (node_type == XML_ELEMENT_DECL) {
		n = node_parent(n);
		if (n == NULL)
			return (False);
		*node = n;
	} else if (node_type == XML_COMMENT_NODE) {
		n = node_child(n);
		if (node_name(n, (xmlChar *)XML_COMMENT_STR) == False) {
			node_free(n);
			*node = NULL;
			return (False);
		}
		if (node_value(n, (xmlChar *)value, False) == False) {
			node_free(n);
			*node = NULL;
			return (False);
		}
	} else if (node_type != XML_DTD_NODE) {
		node_free(n);
		*node = NULL;
		return (False);
	}
	return (True);
}
コード例 #15
0
ファイル: bstree.c プロジェクト: gidj/cStructures
void node_delete(Node *node)
{
  if (*node)
  {
    if (!node_left(*node) && !node_right(*node))
    {
      Node tmp = *node;
      *node = NULL;
      free(node_value(tmp));
      free(tmp);
      return;
    }
    else if (!node_left(*node))
    {
      Node tmp = *node;
      *node = node_right(*node);
      free(tmp->value);
      free(tmp);
      return;
    }
    else if (!node_right(*node))
    {
      Node tmp = *node;
      *node = node_left(*node);
      free(tmp->value);
      free(tmp);
      return;
    }
    else
    {
      Node successor = node_right((*node));
      Node successorParent = (*node);

      while(successor->left) {
        successorParent = successor;
        successor = node_left(successor);
      }

      if (node_right(*node) == successor)
      {
        Node temp = *node;
        set_left(successor, node_left(*node));
        *node = successor;

        free(temp->value);
        free(temp);
        return;
      }
      else
      {
        set_left(successorParent, node_right(successor));
        set_left(successor, node_left(*node));
        set_right(successor, node_right(*node));

        Node temp = *node;
        *node = successor;
        
        free(temp->value);
        free(temp);

        return;
      }
    }
  }
}
コード例 #16
0
ファイル: obstacles.cpp プロジェクト: maxberk/gsl
	// main operator that is used according to GSL specification
	// it is used as a callback from a traverser code
	// list<node_value> &e - list of child nodes - this list is used as an output - the follwoing code
	// pushes node values to this list
	// list<cost_value>& ce - output list for costs of child nodes - costs should have the same
	// positions at the list as corresponding nodes in a previous list
	// node_value n - this is a node to be expanded
	// node_value - this is a parent of a previous node
	// cost_value c - the cost of a node to be expanded
	void operator()(list<node_value> &e, list<cost_value>& ce, node_value n, node_value, cost_value c) {

		// x and y coordinates of a lag start waypoint
		float xs = waypoints[n.waypointid].x;
		float ys = waypoints[n.waypointid].y;

		// iterator over all waypoints on a routes' map
		waypoints_const_iter_t i = waypoints.begin();
		for(;i != waypoints.end();++ i) {
			waypoint wp = *i;

			// find if a waypoint is already examined in a current route - to avoid cycles
			vector<long>::iterator i = find(
				n.previds.begin(),n.previds.end(),wp.id);
			if( (i == n.previds.end()) && (wp.id != n.waypointid) ) {

				// x and y coordinates of a lag end waypoint
				float xf = wp.x;
				float yf = wp.y;

				// lag length
				float LagLen = sqrt( SQR(xf - xs) + SQR(yf - ys) );

				// waypoint is added if the lag length does not exceed predefined value
				if(LagLen < _MaxLagLen) {
					bool crosses = false;
					// iterating over all obstacles
					for(obstacles_const_iter_t j = obstacles.begin(); j != obstacles.end(); ++j) {
						obstacle ob = *j;
						float xo = ob.x;
						float yo = ob.y;
						float ro = ob.r;
						
						float a = SQR( (xf - xs)/(yf - ys) ) + 1.0;
						float b = 2.0 * (xf - xs)/(yf - ys) * ( (xs - xo) - (xf - xs)/(yf - ys) * ys ) - 2.0 * yo;
					        float c = SQR( (xs - xo) - (xf - xs)/(yf - ys) * ys ) + SQR(yo) - SQR(ro);
						float D = SQR(b) - 4.0 * a * c;
						// if a line connecting two waypoints crosses an obstacle area
						if(D > 0.0) {
							// find whether the area is crossed between waypoints
							float y1 = ( - b + sqrt(D) ) / (2.0 * a);
							float y2 = ( - b - sqrt(D) ) / (2.0 * a);
							float ymin = ys > yf? yf: ys;
							float ymax = ys > yf? ys: yf;
							if ( (y1 <= ymax) && (y1 >= ymin) || (y2 <= ymax) && (y2 >= ymin) ) {
								crosses = true;
								break;
							}
						}

					}

					if(!crosses) {
						// adding node value to a result list
						e.push_back(node_value(wp.id, n));
	
						// calculation of heuristics
						// x and y coordinates of a final route waypoint
						float xg = waypoints[19].x;
						float yg = waypoints[19].y;

						// euclidean distance for a child node waypoint to final route waypoint
						float h = sqrt( SQR(xf - xg) + SQR(yf - yg) );
						// adding cost value to a result list
						// one should put 0.0 instead of h as a constrcutor parameter here
						// if no heuristics is used
						ce.push_back(cost_value(c.g + LagLen, h));
					}
				}
			}
		}
	}
コード例 #17
0
ファイル: NeuronNetwork.hpp プロジェクト: lstavr/BridgewellML
 void update(Matrix<IndexType, ItorType>* m, LabelType* y) {
   if (m->getNFeature() != nnode[nlayer - 1]) throw std::invalid_argument("Inconsistent nfeature");
   typedef std::vector<double> NumVec;
   typedef std::vector<NumVec> NumVecVec;
   NumVecVec node_value(nlayer - 1, NumVec()), g0(nlayer - 1, NumVec());
   for(IndexType i = 0;i + 1 < nlayer;i++) {
     node_value[i].resize(nnode[i], 0.0);
     g0[i].resize(nnode[i], 0.0);
   }
   #pragma omp parallel
   for(IndexType instance_id = 0;instance_id < m->getNInstance();instance_id++) {
     for(IndexType l = nlayer - 1;l > 0;l--) { // l \in [1, nlayer - 1]
       #pragma omp for
       for(IndexType ll = 0;ll < nnode[l - 1];ll++) {
         // ll \in [0, nnode[l - 1]]
         node_value[l - 1][ll] = 0;
       }
       IndexType ln = nnode[l];
       if (l == nlayer - 1) {
         // last layer
         #pragma omp for
         for(ItorType iter = m->getFeatureItorBegin(instance_id);iter < m->getFeatureItorEnd(instance_id);iter++) {
           IndexType feature_id = m->getFeatureId(iter);
           double value = m->getValue(iter);
           for(IndexType ll = 0;ll < nnode[l - 1];ll++) {
             double w = ftprl->get_w(z[l - 1][ll * ln + feature_id], n[l - 1][ll * ln + feature_id]);
             // ll \in [0, nnode[l - 1]]
             node_value[l - 1][ll] += value * w;
           }
         }
       } else { // l < nlayer - 1
         #pragma omp for
         for(IndexType feature_id = 0;feature_id < nnode[l];feature_id++) {
           double value = node_value[l][feature_id];
           for(IndexType ll = 0;ll < nnode[l - 1];ll++) {
             double w = ftprl->get_w(z[l - 1][ll * ln + feature_id], n[l - 1][ll * ln + feature_id]);
             node_value[l - 1][ll] += value * w;
           }
         }
       } // l < nlayer - 1
       #pragma omp for
       for(IndexType ll = 0;ll < nnode[l - 1];ll++) {
         node_value[l - 1][ll] = sigma(node_value[l - 1][ll]);
       }
     } // l
     double yt = y[instance_id];
     for(IndexType l = 0;l + 1 < nlayer;l++) {
       IndexType ln = nnode[l];
       if (l == 0) {
         #pragma omp for
         for(IndexType ll = 0;ll < nnode[l];ll++) {
           g0[l][ll] = (1 - yt) / (1 - node_value[l][ll]) - yt / node_value[l][ll];
         }
       } else {
         #pragma omp for
         for(IndexType ll = 0;ll < nnode[l];ll++) {
           g0[l][ll] = 0;
           for(IndexType llp = 0;llp < nnode[l - 1];llp++) {
             double w = ftprl->get_w(z[l - 1][llp * ln + ll], n[l - 1][llp * ln + ll]);
             g0[l][ll] += g0[l-1][llp] * node_value[l - 1][llp] * (1 - node_value[l - 1][llp]) * w;
           }
         }
       }
       for(IndexType l = 0; l + 1 < nlayer;l++) {
         IndexType ln = nnode[l + 1];
         #pragma omp for
         for(IndexType ll = 0;ll < nnode[l];ll++) {
           if (l + 2 == nlayer) {
             for(ItorType iter = m->getFeatureItorBegin(instance_id);iter < m->getFeatureItorEnd(instance_id);iter++) {
               IndexType feature_id = m->getFeatureId(iter);
               double value = m->getValue(iter);
               double g = g0[l][ll] * (1 - node_value[l][ll]) * value;
               ftprl->update_zn(g, z[l] + ll * ln + feature_id, n[l] + ll * ln + feature_id);
             }
           } else {
             for(IndexType feature_id = 0;feature_id < nnode[l + 1];feature_id++) {
               double value = node_value[l + 1][feature_id];
               double g = g0[l][ll] * (1 - node_value[l][ll]) * value;
               ftprl->update_zn(g, z[l] + ll * ln + feature_id, n[l] + ll * ln + feature_id);
             }
           } // l + 2 < nlayer
         }
       }
     }
   }
 }