Example #1
0
 LocalAddressSpace(findPCRange_t findPCRange_)
     : findPCRange(findPCRange_), needsReload(true) {
   static const rb_tree_ops_t segmentTreeOps = {
     rangeCmp, rangeCmpKey, offsetof(Range, range_link), NULL
   };
   static const rb_tree_ops_t dsoTreeOps = {
     dsoTableCmp, dsoTableCmpKey, offsetof(Range, dso_link), NULL
   };
   rb_tree_init(&segmentTree, &segmentTreeOps);
   rb_tree_init(&dsoTree, &dsoTreeOps);
   pthread_rwlock_init(&fdeTreeLock, NULL);
 }
Example #2
0
/** 初始化LCUI的内存管理模块 */
void LCUIMM_Init(void)
{
	mem_data_t first_data;

	/* 初始化默认类别的数据 */
	first_data.mem_info.class_id = 0;
	first_data.mem_info.class_name[0] = 0;
	first_data.mem_info.total_size = 0;

	rb_tree_init( &global_mem_class_info );
	rb_tree_init( &global_mem_data );

	/* 插入默认类别的记录 */
	rb_insert( &global_mem_class_info, &first_data, RB_DATA_TYLE_INFO );
}
Example #3
0
nlopt_result cdirect_hybrid_unscaled(int n, nlopt_func f, void *f_data,
				     const double *lb, const double *ub,
				     double *x,
				     double *minf,
				     nlopt_stopping *stop,
				     nlopt_algorithm local_alg,
				     int local_maxeval,
				     int randomized_div)
{
     params p;
     int i;
     double *rnew;
     nlopt_result ret = NLOPT_OUT_OF_MEMORY;

     p.n = n;
     p.L = 3*n+3;
     p.lb = lb; p.ub = ub;
     p.stop = stop;
     p.f = f;
     p.f_data = f_data;
     p.minf = HUGE_VAL;
     p.xmin = x;
     p.age = 0;
     p.work = 0;
     p.local_alg = local_alg;
     p.local_maxeval = local_maxeval;
     p.randomized_div = randomized_div;

     rb_tree_init(&p.rtree, cdirect_hyperrect_compare);
     p.work = (double *) malloc(sizeof(double) * (2*n));
     if (!p.work) goto done;
     
     if (!(rnew = (double *) malloc(sizeof(double) * p.L))) goto done;
     for (i = 0; i < n; ++i) {
          rnew[3+i] = rnew[3+n+i] = 0.5 * (lb[i] + ub[i]);
          rnew[3+2*n+i] = ub[i] - lb[i];
     }
     rnew[0] = longest(n, rnew+2*n);
     rnew[2] = p.age--;
     ret = optimize_rect(rnew, &p);
     if (ret != NLOPT_SUCCESS) { free(rnew); goto done; }
     if (!rb_tree_insert(&p.rtree, rnew)) { free(rnew); goto done; }

     do {
	  ret = divide_largest(&p);
     } while (ret == NLOPT_SUCCESS);

 done:
     rb_tree_destroy_with_keys(&p.rtree);
     free(p.work);
	      
     *minf = p.minf;
     return ret;
}
Example #4
0
File: vmap.c Project: glguida/mh
static void vmap_init(void)
{
	rb_tree_init(&vmap_rbtree, &vmap_tree_ops);
	vmapzone_init(&vmap_zone);
	vmap_size = 0;

	printf("Freeing from %lx to %lx\n",
	       VM_MINMMAP_ADDRESS, VM_MAXMMAP_ADDRESS);
	vmapzone_free(&vmap_zone, VM_MINMMAP_ADDRESS,
		      VM_MAXMMAP_ADDRESS - VM_MINMMAP_ADDRESS);
}
Example #5
0
File: vmm.c Project: korepwx/pcore
// ---- ProcVM & ProcVMA basic interfaces ----
ProcVM* vm_create_proc(void)
{
  ProcVM *proc = kmalloc(sizeof(ProcVM));
  
  if (proc != NULL) {
    rb_tree_init(&(proc->mmap_root), vma_compare);
    proc->mmap_cache = NULL;
    proc->pgdir = NULL;
    proc->map_count.counter = 0;
    
    vm_set_proc_count(proc, 0);
    proc->locked_by = 0;
  }
  
  return proc;
}
static rb_tree_t *
_reach_requests_rbt()
{
	static dispatch_once_t		once;
	static const rb_tree_ops_t	ops = {
		.rbto_compare_nodes	= _rbt_compare_transaction_nodes,
		.rbto_compare_key	= _rbt_compare_transaction_key,
		.rbto_node_offset	= offsetof(reach_request_t, rbn),
		.rbto_context		= NULL
	};
	static rb_tree_t		rbt;

	dispatch_once(&once, ^{
		rb_tree_init(&rbt, &ops);
	});

	return &rbt;
}
Example #7
0
nlopt_result cdirect_unscaled(int n, nlopt_func f, void *f_data,
			      const double *lb, const double *ub,
			      double *x,
			      double *minf,
			      nlopt_stopping *stop,
			      double magic_eps, int which_alg)
{
     params p;
     int i;
     double *rnew;
     nlopt_result ret = NLOPT_OUT_OF_MEMORY;

     p.magic_eps = magic_eps;
     p.which_diam = which_alg % 3;
     p.which_div = (which_alg / 3) % 3;
     p.which_opt = (which_alg / (3*3)) % 3;
     p.lb = lb; p.ub = ub;
     p.stop = stop;
     p.n = n;
     p.L = 2*n+3;
     p.f = f;
     p.f_data = f_data;
     p.xmin = x;
     p.minf = HUGE_VAL;
     p.work = 0;
     p.iwork = 0;
     p.hull = 0;
     p.age = 0;

     rb_tree_init(&p.rtree, cdirect_hyperrect_compare);

     p.work = (double *) malloc(sizeof(double) * (2*n));
     if (!p.work) goto done;
     p.iwork = (int *) malloc(sizeof(int) * n);
     if (!p.iwork) goto done;
     p.hull_len = 128; /* start with a reasonable number */
     p.hull = (double **) malloc(sizeof(double *) * p.hull_len);
     if (!p.hull) goto done;

     if (!(rnew = (double *) malloc(sizeof(double) * p.L))) goto done;
     for (i = 0; i < n; ++i) {
	  rnew[3+i] = 0.5 * (lb[i] + ub[i]);
	  rnew[3+n+i] = ub[i] - lb[i];
     }
     rnew[0] = rect_diameter(n, rnew+3+n, &p);
     rnew[1] = function_eval(rnew+3, &p);
     rnew[2] = p.age++;
     if (!rb_tree_insert(&p.rtree, rnew)) {
	  free(rnew);
	  goto done;
     }

     ret = divide_rect(rnew, &p);
     if (ret != NLOPT_SUCCESS) goto done;

     while (1) {
	  double minf0 = p.minf;
	  ret = divide_good_rects(&p);
	  if (ret != NLOPT_SUCCESS) goto done;
	  if (p.minf < minf0 && nlopt_stop_f(p.stop, p.minf, minf0)) {
	       ret = NLOPT_FTOL_REACHED;
	       goto done;
	  }
     }

 done:
     rb_tree_destroy_with_keys(&p.rtree);
     free(p.hull);
     free(p.iwork);
     free(p.work);
	      
     *minf = p.minf;
     return ret;
}
Example #8
0
void
nfs_rbtinit(struct nfsmount *nmp)
{
	rb_tree_init(&nmp->nm_rbtree, &nfs_node_rbtree_ops);
}
Example #9
0
int main(int argc, char *argv[])
{
    irb_tree_t irb_tree;
    irb_node_t *node;
    unsigned int key;
    #if 0
    for (int i = 0; i < KEY_POOL_CAPS; ++i) {
add_key:
        key = arc4random();
        for (int j = i - 1; j >= 0; j--) {
            if (key == key_pool[j]) {
                goto add_key;
            }
        }
        key_pool[i] = key;
    }
#else
    unsigned int j = 0;
    for (int i = 0; i < KEY_POOL_CAPS; ++i, ++j) {
add_key:
        if (arc4random() % 10 == 0) {
            ++j;
        }
        key_pool[i] = j;
    }
    unsigned int a, b;
    for (int i = 0; i < 30000; ++i) {
        do {
            a = arc4random() % KEY_POOL_CAPS;
            b = arc4random() % KEY_POOL_CAPS;
        } while (a == b);
        unsigned int tmp = key_pool[a];
        key_pool[a] = key_pool[b];
        key_pool[b] = tmp;
    }
#endif
    printf("Key pool init.\n");

    struct timeval rb1,rb2,rb3;

    irb_tree_init(&irb_tree, data_compare, data_destroy);
    gettimeofday(&rb1, NULL);
    for (int i = 0; i < KEY_POOL_CAPS; ++i) {
        data_node_t *data = (data_node_t *)malloc(sizeof(*data));
        data->key = key_pool[i];
        irb_insert(&(data->irb_node), &irb_tree);
    }
    gettimeofday(&rb2, NULL);
    timersub(&rb2, &rb1, &rb3);
    printf("IRBT INSERT %ld secs, %ld msecs.\n", rb3.tv_sec, rb3.tv_usec);
    printf("Min:%u\n", 
        irb_entry(irb_first(&irb_tree), data_node_t, irb_node)->key);
    printf("Max:%u\n", 
        irb_entry(irb_last(&irb_tree), data_node_t, irb_node)->key);
    
    gettimeofday(&rb1, NULL);
    irb_clear(&irb_tree);
    gettimeofday(&rb2, NULL);
    timersub(&rb2, &rb1, &rb3);
    printf("IRBT CLEAR %ld secs, %ld msecs.\n", rb3.tv_sec, rb3.tv_usec);

    rb_tree_t rb_tree;
    rb_tree_init(&rb_tree, data_compare2, data_destroy2);
    gettimeofday(&rb1, NULL);
    for (int i = 0; i < KEY_POOL_CAPS; ++i) {
        unsigned int *data = (unsigned int *)malloc(sizeof(unsigned int));
        *data = key_pool[i];
        rb_insert(data, &rb_tree);
    }
    gettimeofday(&rb2, NULL);
    timersub(&rb2, &rb1, &rb3);
    printf("RBT INSERT %ld secs, %ld msecs.\n", rb3.tv_sec, rb3.tv_usec);
    printf("Min:%u\n", 
        *(static_cast<unsigned int *>(rb_first(&rb_tree)->data)));
    printf("Max:%u\n", 
        *(static_cast<unsigned int *>(rb_last(&rb_tree)->data)));
    
    gettimeofday(&rb1, NULL);
    rb_clear(&rb_tree);
    gettimeofday(&rb2, NULL);
    timersub(&rb2, &rb1, &rb3);
    printf("RBT CLEAR %ld secs, %ld msecs.\n", rb3.tv_sec, rb3.tv_usec);


    std::set<unsigned int> rb_set;
    gettimeofday(&rb1, NULL);
    for (int i = 0; i < KEY_POOL_CAPS; ++i) {
        rb_set.insert(key_pool[i]);
    }
    gettimeofday(&rb2, NULL);
    timersub(&rb2, &rb1, &rb3);
    printf("RBSET INSERT %ld secs, %ld msecs.\n", rb3.tv_sec, rb3.tv_usec);
    gettimeofday(&rb1, NULL);
    rb_set.clear();
    gettimeofday(&rb2, NULL);
    timersub(&rb2, &rb1, &rb3);
    printf("RBSET CLEAR %ld secs, %ld msecs.\n", rb3.tv_sec, rb3.tv_usec);

    return 0;
}
Example #10
0
int main(int argc, char *argv[])
{
    rb_tree_t rb_tree;
    rb_node_t *node;
    unsigned int key_pool[KEY_POOL_CAPS];
    unsigned int key;
    for (int i = 0; i < KEY_POOL_CAPS; ++i) {
add_key:
        key = arc4random() % 3000;
        for (int j = i - 1; j >= 0; j--) {
            if (key == key_pool[j]) {
                goto add_key;
            }
        }
        key_pool[i] = key;
        printf("Add %u into key pool.\n", key_pool[i]);
    }
    
    rb_tree_init(&rb_tree, data_compare, data_destroy);
redo:
    for (int i = 0; i < KEY_POOL_CAPS; ++i) {
        data_node_t *data = (data_node_t *)malloc(sizeof(*data));
        data->key = key_pool[i];
        if (rb_insert(&(data->rb_node), &rb_tree)) {
            printf("Key %u already exist.\n", data->key);
        } else {
            printf("Add %u into tree.\n", data->key);
        }
    }
    printf("INIT: ************\n");
    printf("Min:%u\n", 
        rb_entry(rb_first(&rb_tree), data_node_t, rb_node)->key);
    printf("Max:%u\n", 
        rb_entry(rb_last(&rb_tree), data_node_t, rb_node)->key);
    printf("Trav with rb_next:\n");
    node = rb_first(&rb_tree);
    while (node) {
        printf("%u, ",rb_entry(node, data_node_t, rb_node)->key); 
        node = rb_next(node);
    }
    printf("\n");
    printf("Trav with rb_prev:\n");
    node = rb_last(&rb_tree);
    while (node) {
        printf("%u, ",rb_entry(node, data_node_t, rb_node)->key); 
        node = rb_prev(node);
    }
    printf("\n");

    printf("ERASE: ************\n");
    data_node_t search_node;
    for (int i = 0; i < 5; i++) {
        unsigned int j = arc4random() % KEY_POOL_CAPS;
        search_node.key = key_pool[j];
        rb_node_t *to_remove = rb_find(&(search_node.rb_node), &rb_tree);
        if (to_remove) {
            printf("Remove %u from tree.\n", search_node.key);
            rb_remove(to_remove, &rb_tree);
            free(rb_entry(to_remove, data_node_t, rb_node));
        } else {
            printf("Key %u not in tree.\n", search_node.key);
        }
    }
    printf("PRINT: ************\n");
    printf("Min:%u\n", 
        rb_entry(rb_first(&rb_tree), data_node_t, rb_node)->key);
    printf("Max:%u\n", 
        rb_entry(rb_last(&rb_tree), data_node_t, rb_node)->key);
    printf("Trav with rb_next:\n");
    node = rb_first(&rb_tree);
    while (node) {
        printf("%u, ",rb_entry(node, data_node_t, rb_node)->key); 
        node = rb_next(node);
    }
    printf("\n");
    printf("Trav with rb_prev:\n");
    node = rb_last(&rb_tree);
    while (node) {
        printf("%u, ",rb_entry(node, data_node_t, rb_node)->key); 
        node = rb_prev(node);
    }
    printf("\n");
    rb_clear(&rb_tree);
    printf("PRINT2: ************\n");
    node = rb_first(&rb_tree);
    if (node) {
        printf("Min:%u\n", 
        rb_entry(node, data_node_t, rb_node)->key);
    }

    node = rb_last(&rb_tree);
    if (node) {
        printf("Max:%u\n", 
        rb_entry(node, data_node_t, rb_node)->key);
    }
    printf("Trav with rb_next:\n");
    node = rb_first(&rb_tree);
    while (node) {
        printf("%u, ",rb_entry(node, data_node_t, rb_node)->key); 
        node = rb_next(node);
    }
    printf("\n");
    printf("Trav with rb_prev:\n");
    node = rb_last(&rb_tree);
    while (node) {
        printf("%u, ",rb_entry(node, data_node_t, rb_node)->key); 
        node = rb_prev(node);
    }
    printf("\n");
    goto redo;
    return 0;
}
Example #11
0
struct rb_tree *
rb_tree_create (rb_tree_node_cmp_f node_cb) {
    return rb_tree_init(rb_tree_alloc(), node_cb);
}
Example #12
0
static int
chfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
{
	struct chfs_mount *chmp;
	struct chfs_inode *ip;
	struct ufsmount *ump;
	struct vnode *vp;
	dev_t dev;
	int error;
	struct chfs_vnode_cache* chvc = NULL;
	struct chfs_node_ref* nref = NULL;
	struct buf *bp;

	dbg("vget() | ino: %llu\n", (unsigned long long)ino);

	ump = VFSTOUFS(mp);
	dev = ump->um_dev;
retry:
	if (!vpp) {
		vpp = kmem_alloc(sizeof(struct vnode*), KM_SLEEP);
	}

	/* Get node from inode hash. */
	if ((*vpp = chfs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) {
		return 0;
	}

	/* Allocate a new vnode/inode. */
	if ((error = getnewvnode(VT_CHFS,
		    mp, chfs_vnodeop_p, NULL, &vp)) != 0) {
		*vpp = NULL;
		return (error);
	}
	ip = pool_get(&chfs_inode_pool, PR_WAITOK);

	mutex_enter(&chfs_hashlock);
	if ((*vpp = chfs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) {
		mutex_exit(&chfs_hashlock);
		ungetnewvnode(vp);
		pool_put(&chfs_inode_pool, ip);
		goto retry;
	}

	vp->v_vflag |= VV_LOCKSWORK;

	/* Initialize vnode/inode. */
	memset(ip, 0, sizeof(*ip));
	vp->v_data = ip;
	ip->vp = vp;
	ip->ch_type = VTTOCHT(vp->v_type);
	ip->ump = ump;
	ip->chmp = chmp = ump->um_chfs;
	ip->dev = dev;
	ip->ino = ino;
	vp->v_mount = mp;
	genfs_node_init(vp, &chfs_genfsops);

	rb_tree_init(&ip->fragtree, &frag_rbtree_ops);

	chfs_ihashins(ip);
	mutex_exit(&chfs_hashlock);

	/* Set root inode. */
	if (ino == CHFS_ROOTINO) {
		dbg("SETROOT\n");
		vp->v_vflag |= VV_ROOT;
		vp->v_type = VDIR;
		ip->ch_type = CHT_DIR;
		ip->mode = IFMT | IEXEC | IWRITE | IREAD;
		ip->iflag |= (IN_ACCESS | IN_CHANGE | IN_UPDATE);
		chfs_update(vp, NULL, NULL, UPDATE_WAIT);
		TAILQ_INIT(&ip->dents);
		chfs_set_vnode_size(vp, 512);
	}

	mutex_enter(&chmp->chm_lock_vnocache);
	chvc = chfs_vnode_cache_get(chmp, ino);
	mutex_exit(&chmp->chm_lock_vnocache);
	if (!chvc) {
		dbg("!chvc\n");
		/* Initialize the corresponding vnode cache. */
		/* XXX, we cant alloc under a lock, refactor this! */
		chvc = chfs_vnode_cache_alloc(ino);
		mutex_enter(&chmp->chm_lock_vnocache);
		if (ino == CHFS_ROOTINO) {
			chvc->nlink = 2;
			chvc->pvno = CHFS_ROOTINO;
			chvc->state = VNO_STATE_CHECKEDABSENT;
		}
		chfs_vnode_cache_add(chmp, chvc);
		mutex_exit(&chmp->chm_lock_vnocache);

		ip->chvc = chvc;
		TAILQ_INIT(&ip->dents);
	} else {
		dbg("chvc\n");
		ip->chvc = chvc;
		/* We had a vnode cache, the node is already on flash, so read it */
		if (ino == CHFS_ROOTINO) {
			chvc->pvno = CHFS_ROOTINO;
			TAILQ_INIT(&chvc->scan_dirents);
		} else {
			chfs_readvnode(mp, ino, &vp);
		}

		mutex_enter(&chmp->chm_lock_mountfields);
		/* Initialize type specific things. */
		switch (ip->ch_type) {
		case CHT_DIR:
			/* Read every dirent. */
			nref = chvc->dirents;
			while (nref &&
			    (struct chfs_vnode_cache *)nref != chvc) {
				chfs_readdirent(mp, nref, ip);
				nref = nref->nref_next;
			}
			chfs_set_vnode_size(vp, 512);
			break;
		case CHT_REG:
			/* FALLTHROUGH */
		case CHT_SOCK:
			/* Collect data. */
			dbg("read_inode_internal | ino: %llu\n",
				(unsigned long long)ip->ino);
			error = chfs_read_inode(chmp, ip);
			if (error) {
				vput(vp);
				*vpp = NULL;
				mutex_exit(&chmp->chm_lock_mountfields);
				return (error);
			}
			break;
		case CHT_LNK:
			/* Collect data. */
			dbg("read_inode_internal | ino: %llu\n",
				(unsigned long long)ip->ino);
			error = chfs_read_inode_internal(chmp, ip);
			if (error) {
				vput(vp);
				*vpp = NULL;
				mutex_exit(&chmp->chm_lock_mountfields);
				return (error);
			}

			/* Set link. */
			dbg("size: %llu\n", (unsigned long long)ip->size);
			bp = getiobuf(vp, true);
			bp->b_blkno = 0;
			bp->b_bufsize = bp->b_resid =
			    bp->b_bcount = ip->size;
			bp->b_data = kmem_alloc(ip->size, KM_SLEEP);
			chfs_read_data(chmp, vp, bp);
			if (!ip->target)
				ip->target = kmem_alloc(ip->size,
				    KM_SLEEP);
			memcpy(ip->target, bp->b_data, ip->size);
			kmem_free(bp->b_data, ip->size);
			putiobuf(bp);

			break;
		case CHT_CHR:
			/* FALLTHROUGH */
		case CHT_BLK:
			/* FALLTHROUGH */
		case CHT_FIFO:
			/* Collect data. */
			dbg("read_inode_internal | ino: %llu\n",
				(unsigned long long)ip->ino);
			error = chfs_read_inode_internal(chmp, ip);
			if (error) {
				vput(vp);
				*vpp = NULL;
				mutex_exit(&chmp->chm_lock_mountfields);
				return (error);
			}

			/* Set device. */
			bp = getiobuf(vp, true);
			bp->b_blkno = 0;
			bp->b_bufsize = bp->b_resid =
			    bp->b_bcount = sizeof(dev_t);
			bp->b_data = kmem_alloc(sizeof(dev_t), KM_SLEEP);
			chfs_read_data(chmp, vp, bp);
			memcpy(&ip->rdev,
			    bp->b_data, sizeof(dev_t));
			kmem_free(bp->b_data, sizeof(dev_t));
			putiobuf(bp);
			/* Set specific operations. */
			if (ip->ch_type == CHT_FIFO) {
				vp->v_op = chfs_fifoop_p;
			} else {
				vp->v_op = chfs_specop_p;
				spec_node_init(vp, ip->rdev);
			}

		    break;
		case CHT_BLANK:
			/* FALLTHROUGH */
		case CHT_BAD:
			break;
		}
		mutex_exit(&chmp->chm_lock_mountfields);

	}

	/* Finish inode initalization. */
	ip->devvp = ump->um_devvp;
	vref(ip->devvp);

	uvm_vnp_setsize(vp, ip->size);
	*vpp = vp;

	return 0;
}
Example #13
0
void main()
{

	rb_root = (rb_node *)malloc(sizeof(rb_node));
	double start,finish;
	result = fopen("result.txt","w");
	
	
	rb_tree *TREE;
	FILE *fp;

   unsigned int list[100000];
	int j=0;
	if (!(fp=fopen("read.txt","r")))
	{
		printf("Cannot open the file. \n");
		return;
	}
    while (j<100000)
	{
		fscanf(fp,"%u",&list[j]);
		j++;
	}
	fclose(fp);



	TREE = rb_tree_init(list,100000);
	int height;
	height = getHeight(TREE);
	printf("The height of the tree is %d\n",height);
	fprintf(result,"The height of the tree is: %d\n",height);
	printf("The rbtree is : \n");
	fprintf(result,"The initial tree is:\n");
	rbtree_output(TREE);
	int size1=getSize(TREE);
	fprintf(result,"The size of the initial tree is: %d \n",size1);
    //select the node according to the rank
	rb_tree *select_node;
	fprintf(result,"EXPERIMENT1: OS_select Operation\n");
	int r;
	for (int k=0; k<10; k++)
	{
	    printf("Please input the rank of the element to find the data:\n");
	    scanf("%d", &r);
	    select_node=OS_select(TREE,r);
        fprintf(result,"The element of rank %d is: %u\n",r,select_node->data);
	}
	
	//search
	fprintf(result,"EXPERIMENT2: Search Operation\n");
	rb_tree* search_node;
	fprintf(result,"We try to find the first ten elements in the input file\n");
	for (int k=0; k<10; k++)
	{
		search_node=rbtree_search(TREE,list[k]);
		if(search_node != rb_root)
			fprintf(result,"The %dth element is FOUND!\n",k+1);
	}
    //rank
	fprintf(result,"EXPERIMENT3: Find the rank of the element\n");
	int rank,rank_p;
	for(int k=0; k<10; k++)
	{
		fprintf(result,"We try to find the rank of the %dth element of the input file: \n",k);
		rank=os_key_rank(TREE,list[k]);
		fprintf(result,"The rank of the %dth element is: %d\n",k,rank);
	}
	
	unsigned int insert_list[100];
	unsigned int del_list[100];
	if (!(fp=fopen("insert.txt","r")))
	{
		printf("Cannot open the file. \n");
		return;
	}
	j=0;
	while(j<100)
	{
		fscanf(fp, "%u", &insert_list[j]);
		j++;
	}
	fclose(fp);
	if (!(fp=fopen("remove.txt","r")))
	{
		printf("Cannot open the file. \n");
		return;
	}
	j=0;
	while(j<100)
	{
		fscanf(fp, "%u", &del_list[j]);
		j++;
	}
	
	fclose(fp);
	//insert
	fprintf(result,"EXPERIMENT4:Insert Operation\n");
	for (j=0; j<100; j++)
	{
		rb_node *insert_node=(rb_node *)malloc(sizeof(rb_node));
		insert_node->data=insert_list[j];
		insert_node->left=rb_root;
		insert_node->right=rb_root;
		insert_node->color='W';
		int flag=rb_tree_insert(TREE,insert_node);
		if (flag == 0)
		{
               rb_tree_fixup(TREE,insert_node);
			   fprintf(result,"The insertion of %dth element has successed!\n",j);
			   height = getHeight(TREE);
			   fprintf(result,"After insertion of %dth element the height of the tree is: %d\n",j,height);
		}
		else
			fprintf(result,"The insertion of %dth element has failed!\n",j);
		
	}
	int size2=getSize(TREE);
	fprintf(result,"The size of the tree after insertion is: %d\n",size2);
	
	//remove
	fprintf(result,"EXPERIMENT5:Deletion Operation\n");
	for(j=0; j<100; j++)
	{
		int flag_del=rb_tree_delete(TREE,del_list[j]);
		if (flag_del == 0)
		{
			fprintf(result,"The deletion of %dth element has successed!\n",j);
			height = getHeight(TREE);
			fprintf(result,"After deletion of %dth element the height of the tree is: %d\n",j,height);
		}
		else
			fprintf(result,"The deletion of %dth element has failed!\n",j);
	}
	int size3=getSize(TREE);
    fprintf(result,"The size of the tree after deletion is: %d\n",size3);
	fprintf(result,"Successful! \n");
	



free_rbtree (TREE);


}
Example #14
0
/* Internal version of nldrmd_minimize, intended to be used as
   a subroutine for the subplex method.  Three differences compared
   to nldrmd_minimize:

   *minf should contain the value of f(x)  (so that we don't have to
   re-evaluate f at the starting x).

   if psi > 0, then it *replaces* xtol and ftol in stop with the condition
   that the simplex diameter |xl - xh| must be reduced by a factor of psi 
   ... this is for when nldrmd is used within the subplex method; for
   ordinary termination tests, set psi = 0. 

   scratch should contain an array of length >= (n+1)*(n+1) + 2*n,
   used as scratch workspace. 

   On output, *fdiff will contain the difference between the high
   and low function values of the last simplex. */
nlopt_result nldrmd_minimize_(int n, nlopt_func f, void *f_data,
			     const double *lb, const double *ub, /* bounds */
			     double *x, /* in: initial guess, out: minimizer */
			     double *minf,
			     const double *xstep, /* initial step sizes */
			     nlopt_stopping *stop,
			     double psi, double *scratch,
			     double *fdiff)
{
     double *pts; /* (n+1) x (n+1) array of n+1 points plus function val [0] */
     double *c; /* centroid * n */
     double *xcur; /* current point */
     rb_tree t; /* red-black tree of simplex, sorted by f(x) */
     int i, j;
     double ninv = 1.0 / n;
     nlopt_result ret = NLOPT_SUCCESS;
     double init_diam = 0;

     pts = scratch;
     c = scratch + (n+1)*(n+1);
     xcur = c + n;

     rb_tree_init(&t, simplex_compare);

     *fdiff = HUGE_VAL;

     /* initialize the simplex based on the starting xstep */
     memcpy(pts+1, x, sizeof(double)*n);
     pts[0] = *minf;
     if (*minf < stop->minf_max) { ret=NLOPT_MINF_MAX_REACHED; goto done; }
     for (i = 0; i < n; ++i) {
	  double *pt = pts + (i+1)*(n+1);
	  memcpy(pt+1, x, sizeof(double)*n);
	  pt[1+i] += xstep[i];
	  if (pt[1+i] > ub[i]) {
	       if (ub[i] - x[i] > fabs(xstep[i]) * 0.1)
		    pt[1+i] = ub[i];
	       else /* ub is too close to pt, go in other direction */
		    pt[1+i] = x[i] - fabs(xstep[i]);
	  }
	  if (pt[1+i] < lb[i]) {
	       if (x[i] - lb[i] > fabs(xstep[i]) * 0.1)
		    pt[1+i] = lb[i];
	       else {/* lb is too close to pt, go in other direction */
		    pt[1+i] = x[i] + fabs(xstep[i]);
		    if (pt[1+i] > ub[i]) /* go towards further of lb, ub */
			 pt[1+i] = 0.5 * ((ub[i] - x[i] > x[i] - lb[i] ?
					   ub[i] : lb[i]) + x[i]);
	       }
	  }
	  if (close(pt[1+i], x[i])) { ret=NLOPT_FAILURE; goto done; }
	  pt[0] = f(n, pt+1, NULL, f_data);
	  CHECK_EVAL(pt+1, pt[0]);
     }

 restart:
     for (i = 0; i < n + 1; ++i)
	  if (!rb_tree_insert(&t, pts + i*(n+1))) {
	       ret = NLOPT_OUT_OF_MEMORY;
	       goto done;
	  }

     while (1) {
	  rb_node *low = rb_tree_min(&t);
	  rb_node *high = rb_tree_max(&t);
	  double fl = low->k[0], *xl = low->k + 1;
	  double fh = high->k[0], *xh = high->k + 1;
	  double fr;

	  *fdiff = fh - fl;

	  if (init_diam == 0) /* initialize diam. for psi convergence test */
	       for (i = 0; i < n; ++i) init_diam += fabs(xl[i] - xh[i]);

	  if (psi <= 0 && nlopt_stop_ftol(stop, fl, fh)) {
	       ret = NLOPT_FTOL_REACHED;
	       goto done;
	  }

	  /* compute centroid ... if we cared about the perfomance of this,
	     we could do it iteratively by updating the centroid on
	     each step, but then we would have to be more careful about
	     accumulation of rounding errors... anyway n is unlikely to
	     be very large for Nelder-Mead in practical cases */
	  memset(c, 0, sizeof(double)*n);
	  for (i = 0; i < n + 1; ++i) {
	       double *xi = pts + i*(n+1) + 1;
	       if (xi != xh)
		    for (j = 0; j < n; ++j)
			 c[j] += xi[j];
	  }
	  for (i = 0; i < n; ++i) c[i] *= ninv;

	  /* x convergence check: find xcur = max radius from centroid */
	  memset(xcur, 0, sizeof(double)*n);
	  for (i = 0; i < n + 1; ++i) {
               double *xi = pts + i*(n+1) + 1;
	       for (j = 0; j < n; ++j) {
		    double dx = fabs(xi[j] - c[j]);
		    if (dx > xcur[j]) xcur[j] = dx;
	       }
	  }
	  for (i = 0; i < n; ++i) xcur[i] += c[i];
	  if (psi > 0) {
	       double diam = 0;
	       for (i = 0; i < n; ++i) diam += fabs(xl[i] - xh[i]);
	       if (diam < psi * init_diam) {
		    ret = NLOPT_XTOL_REACHED;
		    goto done;
	       }
	  }
	  else if (nlopt_stop_x(stop, c, xcur)) {
	       ret = NLOPT_XTOL_REACHED;
	       goto done;
	  }

	  /* reflection */
	  if (!reflectpt(n, xcur, c, alpha, xh, lb, ub)) { 
	       ret=NLOPT_XTOL_REACHED; goto done; 
	  }
	  fr = f(n, xcur, NULL, f_data);
	  CHECK_EVAL(xcur, fr);

	  if (fr < fl) { /* new best point, expand simplex */
	       if (!reflectpt(n, xh, c, gamm, xh, lb, ub)) {
		    ret=NLOPT_XTOL_REACHED; goto done; 
	       }
	       fh = f(n, xh, NULL, f_data);
	       CHECK_EVAL(xh, fh);
	       if (fh >= fr) { /* expanding didn't improve */
		    fh = fr;
		    memcpy(xh, xcur, sizeof(double)*n);
	       }
	  }
	  else if (fr < rb_tree_pred(high)->k[0]) { /* accept new point */
	       memcpy(xh, xcur, sizeof(double)*n);
	       fh = fr;
	  }
	  else { /* new worst point, contract */
	       double fc;
	       if (!reflectpt(n,xcur,c, fh <= fr ? -beta : beta, xh, lb,ub)) {
		    ret=NLOPT_XTOL_REACHED; goto done; 
	       }
	       fc = f(n, xcur, NULL, f_data);
	       CHECK_EVAL(xcur, fc);
	       if (fc < fr && fc < fh) { /* successful contraction */
		    memcpy(xh, xcur, sizeof(double)*n);
		    fh = fc;
	       }
	       else { /* failed contraction, shrink simplex */
		    rb_tree_destroy(&t);
		    rb_tree_init(&t, simplex_compare);
		    for (i = 0; i < n+1; ++i) {
			 double *pt = pts + i * (n+1);
			 if (pt+1 != xl) {
			      if (!reflectpt(n,pt+1, xl,-delta,pt+1, lb,ub)) {
				   ret = NLOPT_XTOL_REACHED;
				   goto done;
			      }
			      pt[0] = f(n, pt+1, NULL, f_data);
			      CHECK_EVAL(pt+1, pt[0]);
			 }
		    }
		    goto restart;
	       }
	  }

	  high->k[0] = fh;
	  rb_tree_resort(&t, high);
     }
     
done:
     rb_tree_destroy(&t);
     return ret;
}
nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data,
			   const double *lb, const double *ub, /* bounds */
			   double *x, /* in: initial guess, out: minimizer */
			   double *minf,
			   nlopt_stopping *stop,
			   nlopt_opt local_opt,
			   int Nsamples, /* #samples/iteration (0=default) */
			   int lds) /* random or low-discrepancy seq. (lds) */
{
     nlopt_result ret = NLOPT_SUCCESS;
     mlsl_data d;
     int i;
     pt *p;

     if (!Nsamples)
	  d.N = 4; /* FIXME: what is good number of samples per iteration? */
     else
	  d.N = Nsamples;
     if (d.N < 1) return NLOPT_INVALID_ARGS;

     d.n = n;
     d.lb = lb; d.ub = ub;
     d.stop = stop;
     d.f = f; d.f_data = f_data;
     rb_tree_init(&d.pts, pt_compare);
     rb_tree_init(&d.lms, lm_compare);
     d.s = lds ? nlopt_sobol_create((unsigned) n) : NULL;

     nlopt_set_min_objective(local_opt, fcount, &d);
     nlopt_set_lower_bounds(local_opt, lb);
     nlopt_set_upper_bounds(local_opt, ub);
     nlopt_set_stopval(local_opt, stop->minf_max);

     d.gamma = MLSL_GAMMA;

     d.R_prefactor = sqrt(2./K2PI) * pow(gam(n) * MLSL_SIGMA, 1.0/n);
     for (i = 0; i < n; ++i)
	  d.R_prefactor *= pow(ub[i] - lb[i], 1.0/n);

     /* MLSL also suggests setting some minimum distance from points
	to previous local minimiza and to the boundaries; I don't know
	how to choose this as a fixed number, so I set it proportional
	to R; see also the comments at top.  dlm and dbound are the
	proportionality constants. */
     d.dlm = 1.0; /* min distance/R to local minima (FIXME: good value?) */
     d.dbound = 1e-6; /* min distance/R to ub/lb boundaries (good value?) */
     

     p = alloc_pt(n);
     if (!p) { ret = NLOPT_OUT_OF_MEMORY; goto done; }

     /* FIXME: how many sobol points to skip, if any? */
     nlopt_sobol_skip(d.s, (unsigned) (10*n+d.N), p->x);

     memcpy(p->x, x, n * sizeof(double));
     p->f = f(n, x, NULL, f_data);
     stop->nevals++;
     if (!rb_tree_insert(&d.pts, (rb_key) p)) { 
	  free(p); ret = NLOPT_OUT_OF_MEMORY; 
     }
     if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP;
     else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED;
     else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED;
     else if (p->f < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED;

     while (ret == NLOPT_SUCCESS) {
	  rb_node *node;
	  double R;

	  get_minf(&d, minf, x);

	  /* sampling phase: add random/quasi-random points */
	  for (i = 0; i < d.N && ret == NLOPT_SUCCESS; ++i) {
	       p = alloc_pt(n);
	       if (!p) { ret = NLOPT_OUT_OF_MEMORY; goto done; }
	       if (d.s) nlopt_sobol_next(d.s, p->x, lb, ub);
	       else { /* use random points instead of LDS */
		    int j;
		    for (j = 0; j < n; ++j) p->x[j] = nlopt_urand(lb[j],ub[j]);
	       }
	       p->f = f(n, p->x, NULL, f_data);
	       stop->nevals++;
	       if (!rb_tree_insert(&d.pts, (rb_key) p)) { 
		    free(p); ret = NLOPT_OUT_OF_MEMORY;
	       }
	       if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP;
	       else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED;
	       else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED;
	       else if (p->f < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED;
	       else {
		    find_closest_pt(n, &d.pts, p);
		    find_closest_lm(n, &d.lms, p);
		    pts_update_newpt(n, &d.pts, p);
	       }
	  }

	  /* distance threshhold parameter R in MLSL */
	  R = d.R_prefactor 
	       * pow(log((double) d.pts.N) / d.pts.N, 1.0 / n);

	  /* local search phase: do local opt. for promising points */
	  node = rb_tree_min(&d.pts);
	  for (i = (int) (ceil(d.gamma * d.pts.N) + 0.5); 
	       node && i > 0 && ret == NLOPT_SUCCESS; --i) {
	       p = (pt *) node->k;
	       if (is_potential_minimizer(&d, p, 
					  R, d.dlm*R, d.dbound*R)) {
		    nlopt_result lret;
		    double *lm;
		    double t = nlopt_seconds();

		    if (nlopt_stop_forced(stop)) {
			 ret = NLOPT_FORCED_STOP; break;
		    }
		    if (nlopt_stop_evals(stop)) {
                         ret = NLOPT_MAXEVAL_REACHED; break;
		    }
		    if (stop->maxtime > 0 &&
			t - stop->start >= stop->maxtime) {
			 ret = NLOPT_MAXTIME_REACHED; break;
		    }
		    lm = (double *) malloc(sizeof(double) * (n+1));
		    if (!lm) { ret = NLOPT_OUT_OF_MEMORY; goto done; }
		    memcpy(lm+1, p->x, sizeof(double) * n);
		    lret = nlopt_optimize_limited(local_opt, lm+1, lm,
						  stop->maxeval - stop->nevals,
						  stop->maxtime -
						  (t - stop->start));
		    p->minimized = 1;
		    if (lret < 0) { free(lm); ret = lret; goto done; }
		    if (!rb_tree_insert(&d.lms, lm)) { 
			 free(lm); ret = NLOPT_OUT_OF_MEMORY;
		    }
		    else if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP;
		    else if (*lm < stop->minf_max) 
			 ret = NLOPT_MINF_MAX_REACHED;
		    else if (nlopt_stop_evals(stop))
			 ret = NLOPT_MAXEVAL_REACHED;
		    else if (nlopt_stop_time(stop))
			 ret = NLOPT_MAXTIME_REACHED;
		    else
			 pts_update_newlm(n, &d.pts, lm);
	       }

	       /* TODO: additional stopping criteria based
		  e.g. on improvement in function values, etc? */
	       
	       node = rb_tree_succ(node);
	  }
     }

     get_minf(&d, minf, x);

 done:
     nlopt_sobol_destroy(d.s);
     rb_tree_destroy_with_keys(&d.lms);
     rb_tree_destroy_with_keys(&d.pts);
     return ret;
}
Example #16
0
static nlopt_result crs_init(crs_data *d, int n, const double *x,
			     const double *lb, const double *ub,
			     nlopt_stopping *stop, nlopt_func f, void *f_data,
			     int population, int lds)
{
     int i;

     if (!population) {
	  /* TODO: how should we set the default population size? 
	     the Kaelo and Ali paper suggests 10*(n+1), but should
	     we add more random points if maxeval is large, or... ? */
	  d->N = 10 * (n + 1); /* heuristic initial population size */
     }
     else
	  d->N = population;
     if (d->N < n + 1) /* population must be big enough for a simplex */
	  return NLOPT_INVALID_ARGS;

     d->n = n;
     d->stop = stop;
     d->f = f; d->f_data = f_data;
     d->ub = ub; d->lb = lb;
     d->ps = (double *) malloc(sizeof(double) * (n + 1) * (d->N + 1));
     if (!d->ps) return NLOPT_OUT_OF_MEMORY;
     d->p = d->ps + d->N * (n+1);
     rb_tree_init(&d->t, crs_compare);

     /* we can either use pseudorandom points, as in the original CRS
	algorithm, or use a low-discrepancy Sobol' sequence ... I tried
	the latter, however, and it doesn't seem to help, probably
	because we are only generating a small number of random points
	to start with */
     d->s = lds ? nlopt_sobol_create((unsigned) n) : NULL;
     nlopt_sobol_skip(d->s, (unsigned) d->N, d->ps + 1);

     /* generate initial points randomly, plus starting guess x */
     memcpy(d->ps + 1, x, sizeof(double) * n);
     d->ps[0] = f(n, x, NULL, f_data);
     stop->nevals++;
     if (!rb_tree_insert(&d->t, d->ps)) return NLOPT_OUT_OF_MEMORY;
     if (d->ps[0] < stop->minf_max) return NLOPT_MINF_MAX_REACHED;
     if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
     if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;
     for (i = 1; i < d->N; ++i) {
	  double *k = d->ps + i*(n+1);
	  if (d->s) 
	       nlopt_sobol_next(d->s, k + 1, lb, ub);
	  else {
	       int j;
	       for (j = 0; j < n; ++j) 
		    k[1 + j] = nlopt_urand(lb[j], ub[j]);
	  }
	  k[0] = f(n, k + 1, NULL, f_data);
	  stop->nevals++;
	  if (!rb_tree_insert(&d->t, k)) return NLOPT_OUT_OF_MEMORY;
	  if (k[0] < stop->minf_max) return NLOPT_MINF_MAX_REACHED;
	  if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
	  if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;	  
     }

     return NLOPT_SUCCESS;;
}
Example #17
0
int main(int argc, char **argv)
{
    int N, M;
    int *k;
    double kd;
    rb_tree t;
    rb_node *n;
    int i, j;

    if (argc < 2) {
        fprintf(stderr, "Usage: redblack_test Ntest [rand seed]\n");
        return 1;
    }

    N = atoi(argv[1]);
    k = (int *) malloc(N * sizeof(int));
    rb_tree_init(&t, comp);

    srand((unsigned) (argc > 2 ? atoi(argv[2]) : time(NULL)));
    for (i = 0; i < N; ++i) {
        double *newk = (double *) malloc(sizeof(double));
        *newk = (k[i] = rand() % N);
        if (!rb_tree_insert(&t, newk)) {
            fprintf(stderr, "error in rb_tree_insert\n");
            return 1;
        }
        if (!rb_tree_check(&t)) {
            fprintf(stderr, "rb_tree_check_failed after insert!\n");
            return 1;
        }
    }

    if (t.N != N) {
        fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N);
        return 1;
    }

    for (i = 0; i < N; ++i) {
        kd = k[i];
        if (!rb_tree_find(&t, &kd)) {
            fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
            return 1;
        }
    }

    n = rb_tree_min(&t);
    for (i = 0; i < N; ++i) {
        if (!n) {
            fprintf(stderr, "not enough successors %d\n!", i);
            return 1;
        }
        printf("%d: %g\n", i, n->k[0]);
        n = rb_tree_succ(n);
    }
    if (n) {
        fprintf(stderr, "too many successors!\n");
        return 1;
    }

    n = rb_tree_max(&t);
    for (i = 0; i < N; ++i) {
        if (!n) {
            fprintf(stderr, "not enough predecessors %d\n!", i);
            return 1;
        }
        printf("%d: %g\n", i, n->k[0]);
        n = rb_tree_pred(n);
    }
    if (n) {
        fprintf(stderr, "too many predecessors!\n");
        return 1;
    }

    for (M = N; M > 0; --M) {
        int knew = rand() % N;  /* random new key */
        j = rand() % M;         /* random original key to replace */
        for (i = 0; i < N; ++i)
            if (k[i] >= 0)
                if (j-- == 0)
                    break;
        if (i >= N)
            abort();
        kd = k[i];
        if (!(n = rb_tree_find(&t, &kd))) {
            fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
            return 1;
        }
        n->k[0] = knew;
        if (!rb_tree_resort(&t, n)) {
            fprintf(stderr, "error in rb_tree_resort\n");
            return 1;
        }
        if (!rb_tree_check(&t)) {
            fprintf(stderr, "rb_tree_check_failed after change %d!\n", N - M + 1);
            return 1;
        }
        k[i] = -1 - knew;
    }

    if (t.N != N) {
        fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N);
        return 1;
    }

    for (i = 0; i < N; ++i)
        k[i] = -1 - k[i];       /* undo negation above */

    for (i = 0; i < N; ++i) {
        rb_node *le, *gt;
        double lek, gtk;
        kd = 0.01 * (rand() % (N * 150) - N * 25);
        le = rb_tree_find_le(&t, &kd);
        gt = rb_tree_find_gt(&t, &kd);
        n = rb_tree_min(&t);
        lek = le ? le->k[0] : -HUGE_VAL;
        gtk = gt ? gt->k[0] : +HUGE_VAL;
        printf("%g <= %g < %g\n", lek, kd, gtk);
        if (n->k[0] > kd) {
            if (le) {
                fprintf(stderr, "found invalid le %g for %g\n", lek, kd);
                return 1;
            }
            if (gt != n) {
                fprintf(stderr, "gt is not first node for k=%g\n", kd);
                return 1;
            }
        } else {
            rb_node *succ = n;
            do {
                n = succ;
                succ = rb_tree_succ(n);
            } while (succ && succ->k[0] <= kd);
            if (n != le) {
                fprintf(stderr, "rb_tree_find_le gave wrong result for k=%g\n", kd);
                return 1;
            }
            if (succ != gt) {
                fprintf(stderr, "rb_tree_find_gt gave wrong result for k=%g\n", kd);
                return 1;
            }
        }
    }

    for (M = N; M > 0; --M) {
        j = rand() % M;
        for (i = 0; i < N; ++i)
            if (k[i] >= 0)
                if (j-- == 0)
                    break;
        if (i >= N)
            abort();
        kd = k[i];
        if (!(n = rb_tree_find(&t, &kd))) {
            fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
            return 1;
        }
        n = rb_tree_remove(&t, n);
        free(n->k);
        free(n);
        if (!rb_tree_check(&t)) {
            fprintf(stderr, "rb_tree_check_failed after remove!\n");
            return 1;
        }
        k[i] = -1 - k[i];
    }

    if (t.N != 0) {
        fprintf(stderr, "nonzero N (%d) in tree at end\n", t.N);
        return 1;
    }

    rb_tree_destroy(&t);
    free(k);

    printf("SUCCESS.\n");
    return 0;
}