void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { unsigned char *X8, *B8; double *X, *B; int N; int k; double *y; //-- // UINT8 image //-- if (mxIsUint8(prhs[0])) { //-- // INPUT //-- // input image X8 = (unsigned char *) mxGetPr(prhs[0]); N = mxGetM(prhs[0]) * mxGetN(prhs[0]); //-- // OUTPUT //-- // median y = mxGetPr(plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL)); //-- // COMPUTATION //-- // buffer image B8 = mxCalloc(N,sizeof(unsigned char)); for (k = 0; k < N; k++) { *(B8 + k) = *(X8 + k); } // compute median if (N % 2) { *y = (double) median_uint8(B8,N); } else { *y = ((double) kth_smallest_uint8(B8,N,N/2 - 1) + (double) kth_smallest_uint8(B8,N,N/2)) / 2.0; } } else { //-- // INPUT //-- // input image X = mxGetPr(prhs[0]); N = mxGetM(prhs[0]) * mxGetN(prhs[0]); //-- // OUTPUT //-- // median y = mxGetPr(plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL)); //-- // COMPUTATION //-- // buffer image B = mxCalloc(N,sizeof(double)); for (k = 0; k < N; k++) { *(B + k) = *(X + k); } // compute median if (N % 2) { *y = median_double(B,N); } else { *y = (kth_smallest_double(B,N,N/2 - 1) + kth_smallest_double(B,N,N/2)) / 2.0; } } }
/** Look through the routerlist, the Mean Time Between Failure history, and * the Weighted Fractional Uptime history, and use them to set thresholds for * the Stable, Fast, and Guard flags. Update the fields stable_uptime, * stable_mtbf, enough_mtbf_info, guard_wfu, guard_tk, fast_bandwidth, * guard_bandwidth_including_exits, and guard_bandwidth_excluding_exits. * * Also, set the is_exit flag of each router appropriately. */ void dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil) { int n_active, n_active_nonexit, n_familiar; uint32_t *uptimes, *bandwidths_kb, *bandwidths_excluding_exits_kb; long *tks; double *mtbfs, *wfus; smartlist_t *nodelist; time_t now = time(NULL); const or_options_t *options = get_options(); /* Require mbw? */ int require_mbw = (dirserv_get_last_n_measured_bws() > options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0; /* initialize these all here, in case there are no routers */ stable_uptime = 0; stable_mtbf = 0; fast_bandwidth_kb = 0; guard_bandwidth_including_exits_kb = 0; guard_bandwidth_excluding_exits_kb = 0; guard_tk = 0; guard_wfu = 0; nodelist_assert_ok(); nodelist = nodelist_get_list(); /* Initialize arrays that will hold values for each router. We'll * sort them and use that to compute thresholds. */ n_active = n_active_nonexit = 0; /* Uptime for every active router. */ uptimes = tor_calloc(smartlist_len(nodelist), sizeof(uint32_t)); /* Bandwidth for every active router. */ bandwidths_kb = tor_calloc(smartlist_len(nodelist), sizeof(uint32_t)); /* Bandwidth for every active non-exit router. */ bandwidths_excluding_exits_kb = tor_calloc(smartlist_len(nodelist), sizeof(uint32_t)); /* Weighted mean time between failure for each active router. */ mtbfs = tor_calloc(smartlist_len(nodelist), sizeof(double)); /* Time-known for each active router. */ tks = tor_calloc(smartlist_len(nodelist), sizeof(long)); /* Weighted fractional uptime for each active router. */ wfus = tor_calloc(smartlist_len(nodelist), sizeof(double)); /* Now, fill in the arrays. */ SMARTLIST_FOREACH_BEGIN(nodelist, node_t *, node) { if (options->BridgeAuthoritativeDir && node->ri && node->ri->purpose != ROUTER_PURPOSE_BRIDGE) continue; routerinfo_t *ri = node->ri; if (ri) { node->is_exit = (!router_exit_policy_rejects_all(ri) && exit_policy_is_general_exit(ri->exit_policy)); } if (router_counts_toward_thresholds(node, now, omit_as_sybil, require_mbw)) { const char *id = node->identity; uint32_t bw_kb; /* resolve spurious clang shallow analysis null pointer errors */ tor_assert(ri); uptimes[n_active] = (uint32_t)real_uptime(ri, now); mtbfs[n_active] = rep_hist_get_stability(id, now); tks [n_active] = rep_hist_get_weighted_time_known(id, now); bandwidths_kb[n_active] = bw_kb = dirserv_get_credible_bandwidth_kb(ri); if (!node->is_exit || node->is_bad_exit) { bandwidths_excluding_exits_kb[n_active_nonexit] = bw_kb; ++n_active_nonexit; } ++n_active; } } SMARTLIST_FOREACH_END(node); /* Now, compute thresholds. */ if (n_active) { /* The median uptime is stable. */ stable_uptime = median_uint32(uptimes, n_active); /* The median mtbf is stable, if we have enough mtbf info */ stable_mtbf = median_double(mtbfs, n_active); /* The 12.5th percentile bandwidth is fast. */ fast_bandwidth_kb = find_nth_uint32(bandwidths_kb, n_active, n_active/8); /* (Now bandwidths is sorted.) */ if (fast_bandwidth_kb < RELAY_REQUIRED_MIN_BANDWIDTH/(2 * 1000)) fast_bandwidth_kb = bandwidths_kb[n_active/4]; guard_bandwidth_including_exits_kb = third_quartile_uint32(bandwidths_kb, n_active); guard_tk = find_nth_long(tks, n_active, n_active/8); } if (guard_tk > TIME_KNOWN_TO_GUARANTEE_FAMILIAR) guard_tk = TIME_KNOWN_TO_GUARANTEE_FAMILIAR; { /* We can vote on a parameter for the minimum and maximum. */ #define ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG 4 int32_t min_fast_kb, max_fast_kb, min_fast, max_fast; min_fast = networkstatus_get_param(NULL, "FastFlagMinThreshold", ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG, ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG, INT32_MAX); if (options->TestingTorNetwork) { min_fast = (int32_t)options->TestingMinFastFlagThreshold; } max_fast = networkstatus_get_param(NULL, "FastFlagMaxThreshold", INT32_MAX, min_fast, INT32_MAX); min_fast_kb = min_fast / 1000; max_fast_kb = max_fast / 1000; if (fast_bandwidth_kb < (uint32_t)min_fast_kb) fast_bandwidth_kb = min_fast_kb; if (fast_bandwidth_kb > (uint32_t)max_fast_kb) fast_bandwidth_kb = max_fast_kb; } /* Protect sufficiently fast nodes from being pushed out of the set * of Fast nodes. */ if (options->AuthDirFastGuarantee && fast_bandwidth_kb > options->AuthDirFastGuarantee/1000) fast_bandwidth_kb = (uint32_t)options->AuthDirFastGuarantee/1000; /* Now that we have a time-known that 7/8 routers are known longer than, * fill wfus with the wfu of every such "familiar" router. */ n_familiar = 0; SMARTLIST_FOREACH_BEGIN(nodelist, node_t *, node) { if (router_counts_toward_thresholds(node, now, omit_as_sybil, require_mbw)) { routerinfo_t *ri = node->ri; const char *id = ri->cache_info.identity_digest; long tk = rep_hist_get_weighted_time_known(id, now); if (tk < guard_tk) continue; wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now); } } SMARTLIST_FOREACH_END(node); if (n_familiar) guard_wfu = median_double(wfus, n_familiar); if (guard_wfu > WFU_TO_GUARANTEE_GUARD) guard_wfu = WFU_TO_GUARANTEE_GUARD; enough_mtbf_info = rep_hist_have_measured_enough_stability(); if (n_active_nonexit) { guard_bandwidth_excluding_exits_kb = find_nth_uint32(bandwidths_excluding_exits_kb, n_active_nonexit, n_active_nonexit*3/4); } log_info(LD_DIRSERV, "Cutoffs: For Stable, %lu sec uptime, %lu sec MTBF. " "For Fast: %lu kilobytes/sec. " "For Guard: WFU %.03f%%, time-known %lu sec, " "and bandwidth %lu or %lu kilobytes/sec. " "We%s have enough stability data.", (unsigned long)stable_uptime, (unsigned long)stable_mtbf, (unsigned long)fast_bandwidth_kb, guard_wfu*100, (unsigned long)guard_tk, (unsigned long)guard_bandwidth_including_exits_kb, (unsigned long)guard_bandwidth_excluding_exits_kb, enough_mtbf_info ? "" : " don't"); tor_free(uptimes); tor_free(mtbfs); tor_free(bandwidths_kb); tor_free(bandwidths_excluding_exits_kb); tor_free(tks); tor_free(wfus); }
/** Run unit tests for getting the median of a list. */ static void test_container_order_functions(void *arg) { int lst[25], n = 0; uint32_t lst_2[25]; // int a=12,b=24,c=25,d=60,e=77; #define median() median_int(lst, n) (void)arg; lst[n++] = 12; tt_int_op(12,OP_EQ, median()); /* 12 */ lst[n++] = 77; //smartlist_shuffle(sl); tt_int_op(12,OP_EQ, median()); /* 12, 77 */ lst[n++] = 77; //smartlist_shuffle(sl); tt_int_op(77,OP_EQ, median()); /* 12, 77, 77 */ lst[n++] = 24; tt_int_op(24,OP_EQ, median()); /* 12,24,77,77 */ lst[n++] = 60; lst[n++] = 12; lst[n++] = 25; //smartlist_shuffle(sl); tt_int_op(25,OP_EQ, median()); /* 12,12,24,25,60,77,77 */ #undef median #define third_quartile() third_quartile_uint32(lst_2, n) n = 0; lst_2[n++] = 1; tt_int_op(1,OP_EQ, third_quartile()); /* ~1~ */ lst_2[n++] = 2; tt_int_op(2,OP_EQ, third_quartile()); /* 1, ~2~ */ lst_2[n++] = 3; lst_2[n++] = 4; lst_2[n++] = 5; tt_int_op(4,OP_EQ, third_quartile()); /* 1, 2, 3, ~4~, 5 */ lst_2[n++] = 6; lst_2[n++] = 7; lst_2[n++] = 8; lst_2[n++] = 9; tt_int_op(7,OP_EQ, third_quartile()); /* 1, 2, 3, 4, 5, 6, ~7~, 8, 9 */ lst_2[n++] = 10; lst_2[n++] = 11; /* 1, 2, 3, 4, 5, 6, 7, 8, ~9~, 10, 11 */ tt_int_op(9,OP_EQ, third_quartile()); #undef third_quartile double dbls[] = { 1.0, 10.0, 100.0, 1e4, 1e5, 1e6 }; tt_double_eq(1.0, median_double(dbls, 1)); tt_double_eq(1.0, median_double(dbls, 2)); tt_double_eq(10.0, median_double(dbls, 3)); tt_double_eq(10.0, median_double(dbls, 4)); tt_double_eq(100.0, median_double(dbls, 5)); tt_double_eq(100.0, median_double(dbls, 6)); time_t times[] = { 5, 10, 20, 25, 15 }; tt_assert(5 == median_time(times, 1)); tt_assert(5 == median_time(times, 2)); tt_assert(10 == median_time(times, 3)); tt_assert(10 == median_time(times, 4)); tt_assert(15 == median_time(times, 5)); int32_t int32s[] = { -5, -10, -50, 100 }; tt_int_op(-5, ==, median_int32(int32s, 1)); tt_int_op(-10, ==, median_int32(int32s, 2)); tt_int_op(-10, ==, median_int32(int32s, 3)); tt_int_op(-10, ==, median_int32(int32s, 4)); long longs[] = { -30, 30, 100, -100, 7 }; tt_int_op(7, ==, find_nth_long(longs, 5, 2)); done: ; }
double median(int n, double *data) { return median_double(n, data); }