// ================ // // プライベート関数 // // ================ // // メンバーをコピーする。 void Job::ScanMember(const Job& job) { std::unique_lock<std::mutex> lock(my_mutex_); // ロック。 client_ptr_ = job.client_ptr_; node_type_ = job.node_type_; pos_hash_ = job.pos_hash_; depth_ = job.depth_; level_ = job.level_; alpha_ = job.alpha_; beta_ = job.beta_; delta_ = job.delta_; pv_line_ptr_ = job.pv_line_ptr_; is_null_searching_ = job.is_null_searching_; null_reduction_ = job.null_reduction_; score_type_ = job.score_type_; material_ = job.material_; is_checked_ = job.is_checked_; num_all_moves_ = job.num_all_moves_; has_legal_move_ = job.has_legal_move_; moves_to_search_ptr_ = job.moves_to_search_ptr_; COPY_ARRAY(helpers_table_, job.helpers_table_); end_ = (job.end_ - job.helpers_table_) + helpers_table_; num_helpers_ = job.num_helpers_; maker_ptr_ = job.maker_ptr_; counter_ = job.counter_; }
// ムーブ代入演算子。 PVLine& PVLine::operator=(PVLine&& pv_line) { score_ = pv_line.score_; mate_in_ = pv_line.mate_in_; last_ = pv_line.last_; COPY_ARRAY(line_, pv_line.line_); return *this; }
// ムーブコンストラクタ。 FEN::FEN(FEN&& fen) : to_move_(fen.to_move_), castling_rights_(fen.castling_rights_), en_passant_square_(fen.en_passant_square_), clock_(fen.clock_), ply_(fen.ply_) { // 駒の配置をコピー。 COPY_ARRAY(position_, fen.position_); }
// メンバをコピーする。 void Cache::ScanMember(const Cache& cache) { COPY_ARRAY(material_, cache.material_); enable_quiesce_search_ = cache.enable_quiesce_search_; enable_repetition_check_ = cache.enable_repetition_check_; enable_check_extension_ = cache.enable_check_extension_; ybwc_limit_depth_ = cache.ybwc_limit_depth_; ybwc_invalid_moves_ = cache.ybwc_invalid_moves_; enable_aspiration_windows_ = cache.enable_aspiration_windows_; aspiration_windows_limit_depth_ = cache.aspiration_windows_limit_depth_; aspiration_windows_delta_ = cache.aspiration_windows_delta_; enable_see_ = cache.enable_see_; enable_history_ = cache.enable_history_; enable_killer_ = cache.enable_killer_; enable_ttable_ = cache.enable_ttable_; enable_iid_ = cache.enable_iid_; iid_limit_depth_ = cache.iid_limit_depth_; iid_search_depth_ = cache.iid_search_depth_; enable_nmr_ = cache.enable_nmr_; nmr_limit_depth_ = cache.nmr_limit_depth_; nmr_search_reduction_ = cache.nmr_search_reduction_; nmr_reduction_ = cache.nmr_reduction_; enable_probcut_ = cache.enable_probcut_; probcut_limit_depth_ = cache.probcut_limit_depth_; probcut_margin_ = cache.probcut_margin_; probcut_search_reduction_ = cache.probcut_search_reduction_; enable_history_pruning_ = cache.enable_history_pruning_; history_pruning_limit_depth_ = cache.history_pruning_limit_depth_; COPY_ARRAY(history_pruning_invalid_moves_, cache.history_pruning_invalid_moves_); history_pruning_threshold_ = cache.history_pruning_threshold_; history_pruning_reduction_ = cache.history_pruning_reduction_; enable_lmr_ = cache.enable_lmr_; lmr_limit_depth_ = cache.lmr_limit_depth_; COPY_ARRAY(lmr_invalid_moves_, cache.lmr_invalid_moves_); lmr_search_reduction_ = cache.lmr_search_reduction_; enable_futility_pruning_ = cache.enable_futility_pruning_; futility_pruning_depth_ = cache.futility_pruning_depth_; COPY_ARRAY(futility_pruning_margin_, cache.futility_pruning_margin_); COPY_ARRAY(piece_hash_value_table_, cache.piece_hash_value_table_); COPY_ARRAY(to_move_hash_value_table_, cache.to_move_hash_value_table_); COPY_ARRAY(castling_hash_value_table_, cache.castling_hash_value_table_); COPY_ARRAY(en_passant_hash_value_table_, cache.en_passant_hash_value_table_); max_nodes_ = cache.max_nodes_; max_depth_ = cache.max_depth_; thinking_time_ = cache.thinking_time_; COPY_ARRAY(eval_cache_, cache.eval_cache_); }
// ムーブ代入演算子。 FEN& FEN::operator=(FEN&& fen) { // メンバをコピー。 to_move_ = fen.to_move_; castling_rights_ = fen.castling_rights_; en_passant_square_ = fen.en_passant_square_; clock_ = fen.clock_; ply_ = fen.ply_; COPY_ARRAY(position_, fen.position_); return *this; }
struct attr_check *attr_check_dup(const struct attr_check *check) { struct attr_check *ret; if (!check) return NULL; ret = attr_check_alloc(); ret->nr = check->nr; ret->alloc = check->alloc; ALLOC_ARRAY(ret->items, ret->nr); COPY_ARRAY(ret->items, check->items, ret->nr); return ret; }
/* * This is a least-significant-digit radix sort. * * It sorts each of the "n" items in "entries" by its offset field. The "max" * parameter must be at least as large as the largest offset in the array, * and lets us quit the sort early. */ static void sort_revindex(struct revindex_entry *entries, unsigned n, off_t max) { /* * We use a "digit" size of 16 bits. That keeps our memory * usage reasonable, and we can generally (for a 4G or smaller * packfile) quit after two rounds of radix-sorting. */ #define DIGIT_SIZE (16) #define BUCKETS (1 << DIGIT_SIZE) /* * We want to know the bucket that a[i] will go into when we are using * the digit that is N bits from the (least significant) end. */ #define BUCKET_FOR(a, i, bits) (((a)[(i)].offset >> (bits)) & (BUCKETS-1)) /* * We need O(n) temporary storage. Rather than do an extra copy of the * partial results into "entries", we sort back and forth between the * real array and temporary storage. In each iteration of the loop, we * keep track of them with alias pointers, always sorting from "from" * to "to". */ struct revindex_entry *tmp, *from, *to; int bits; unsigned *pos; ALLOC_ARRAY(pos, BUCKETS); ALLOC_ARRAY(tmp, n); from = entries; to = tmp; /* * If (max >> bits) is zero, then we know that the radix digit we are * on (and any higher) will be zero for all entries, and our loop will * be a no-op, as everybody lands in the same zero-th bucket. */ for (bits = 0; max >> bits; bits += DIGIT_SIZE) { struct revindex_entry *swap; unsigned i; memset(pos, 0, BUCKETS * sizeof(*pos)); /* * We want pos[i] to store the index of the last element that * will go in bucket "i" (actually one past the last element). * To do this, we first count the items that will go in each * bucket, which gives us a relative offset from the last * bucket. We can then cumulatively add the index from the * previous bucket to get the true index. */ for (i = 0; i < n; i++) pos[BUCKET_FOR(from, i, bits)]++; for (i = 1; i < BUCKETS; i++) pos[i] += pos[i-1]; /* * Now we can drop the elements into their correct buckets (in * our temporary array). We iterate the pos counter backwards * to avoid using an extra index to count up. And since we are * going backwards there, we must also go backwards through the * array itself, to keep the sort stable. * * Note that we use an unsigned iterator to make sure we can * handle 2^32-1 objects, even on a 32-bit system. But this * means we cannot use the more obvious "i >= 0" loop condition * for counting backwards, and must instead check for * wrap-around with UINT_MAX. */ for (i = n - 1; i != UINT_MAX; i--) to[--pos[BUCKET_FOR(from, i, bits)]] = from[i]; /* * Now "to" contains the most sorted list, so we swap "from" and * "to" for the next iteration. */ swap = from; from = to; to = swap; } /* * If we ended with our data in the original array, great. If not, * we have to move it back from the temporary storage. */ if (from != entries) COPY_ARRAY(entries, tmp, n); free(tmp); free(pos); #undef BUCKET_FOR #undef BUCKETS #undef DIGIT_SIZE }
/* *************************************************************************** ** Adds dates to a TDateList. ** ** If the original date list and date list to be added are sorted, then ** the resulting date list will be sorted and duplicate dates will be ** removed. Sorting assumes ascending order ([0] < [1] etc). ** ** If either of the inputs are not sorted, then the resulting date list ** will not be sorted, and some duplicates may remain. ** ** For efficiency, we do not automatically try to sort the resulting ** date list for unsorted inputs. Sorting the date list each time appears ** to be a huge performance issue in some algorithms (where the input ** dates would all be sorted anyway). ** ** Note that if dl is NULL, then this will create a new date list from ** the given dates. ** ** Note that if numItems=0, this will copy the given date list. *************************************************************************** */ TDateList* JpmcdsDateListAddDates (TDateList *dl, /* (I) Initial date list */ int numItems, /* (I) Number of dates to add */ TDate *array) /* (I) [numItems] Dates to be added */ { static char routine[] = "JpmcdsDateListAddDates"; int status = FAILURE; TDateList tmp = {0, NULL}; TDateList *result = NULL; REQUIRE (numItems >= 0); REQUIRE (dl == NULL || dl->fNumItems >= 0); if (dl == NULL) { result = JpmcdsNewDateListFromDates (array, numItems); } else if (numItems <= 0) { result = JpmcdsCopyDateList (dl); } else if (dl->fNumItems == 0 && numItems == 0) { result = JpmcdsNewDateListFromDates (NULL, 0); } else { int totalItems = dl->fNumItems + numItems; int i = 0; int j = 0; int k = 0; result = JpmcdsNewEmptyDateList (totalItems); if (result == NULL) goto done; while (i < dl->fNumItems && j < numItems) { if (dl->fArray[i] == array[j]) { /* exclude duplicates */ ++j; --totalItems; } else if (dl->fArray[i] < array[j]) { result->fArray[k] = dl->fArray[i]; ++i; ++k; } else { // assert (dl->fArray[i] > array[j]); result->fArray[k] = array[j]; ++j; ++k; } } if (i < dl->fNumItems) { int n = dl->fNumItems - i; COPY_ARRAY (result->fArray+k, dl->fArray+i, TDate, n); k += n; } if (j < numItems) { int n = numItems - j; COPY_ARRAY (result->fArray+k, array+j, TDate, n); k += n; } // assert (k == totalItems); result->fNumItems = totalItems; } if (result == NULL) goto done; status = SUCCESS; done: if (status != SUCCESS) { JpmcdsErrMsgFailure (routine); JpmcdsFreeDateList (result); result = NULL; } FREE(tmp.fArray); return result; }
// ムーブコンストラクタ。 PVLine::PVLine(PVLine&& pv_line) : last_(pv_line.last_), score_(pv_line.score_), mate_in_(pv_line.mate_in_) { COPY_ARRAY(line_, pv_line.line_); }
// Main function =============================================================== void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *X, *Y, Nd, *Space, UnitSpace = 1.0; mwSize nX, nDX, ndimX, N, Step, nSpace; const mwSize *dimX; int Order2 = 0; // Check number and type of inputs and outputs: ------------------------------ if (nrhs == 0 || nrhs > 4) { mexErrMsgIdAndTxt(ERR_ID "BadNInput", ERR_HEAD "1 or 4 inputs required."); } if (nlhs > 1) { mexErrMsgIdAndTxt(ERR_ID "BadNOutput", ERR_HEAD "1 output allowed."); } if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0])) { mexErrMsgIdAndTxt(ERR_ID "BadTypeInput1", ERR_HEAD "Input must be a full real double array."); } // Pointers and dimension to input array: ------------------------------------ X = mxGetPr(prhs[0]); nX = mxGetNumberOfElements(prhs[0]); ndimX = mxGetNumberOfDimensions(prhs[0]); dimX = mxGetDimensions(prhs[0]); // Return fast on empty input matrix: if (nX == 0) { plhs[0] = COPY_ARRAY(prhs[0]); return; } // Get spacing, if defined: -------------------------------------------------- if (nrhs < 2) { // No 2nd input defined - scalar unit spacing: nSpace = 1; Space = &UnitSpace; } else { // Get pointer to spacing vector: if (!mxIsDouble(prhs[1])) { mexErrMsgIdAndTxt(ERR_ID "BadTypeInput2", ERR_HEAD "2nd input [Spacing] must be a DOUBLE."); } Space = mxGetPr(prhs[1]); nSpace = mxGetNumberOfElements(prhs[1]); if (nSpace == 0) { nSpace = 1; Space = &UnitSpace; } } // Determine dimension to operate on: ---------------------------------------- if (nrhs < 3) { N = FirstNonSingeltonDim(ndimX, dimX); // Zero based Step = 1; nDX = dimX[N]; } else if (mxIsNumeric(prhs[2])) { // 3rd input used: switch (mxGetNumberOfElements(prhs[2])) { case 0: // Use 1st non-singelton dim if 3rd input is []: N = FirstNonSingeltonDim(ndimX, dimX); Step = 1; nDX = dimX[N]; break; case 1: // Numerical scalar: Nd = mxGetScalar(prhs[2]); N = (mwSize) Nd - 1; if (Nd < 1.0 || Nd != floor(Nd)) { mexErrMsgIdAndTxt(ERR_ID "BadValueInput3", ERR_HEAD "Dimension must be a positive integer scalar."); } if (N < ndimX) { Step = GetStep(dimX, N); nDX = dimX[N]; } else { // Treat imaginated trailing dimensions as singelton, as usual in // Matlab: Step = nX; nDX = 1; } break; default: mexErrMsgIdAndTxt(ERR_ID "BadSizeInput3", ERR_HEAD "3rd input [Dim] must be scalar index."); } } else { // 2nd input is not numeric: mexErrMsgIdAndTxt(ERR_ID "BadTypeInput3", ERR_HEAD "3rd input must be scalar index."); } // Check matching sizes of X and Spacing: if (nSpace != 1 && nSpace != nDX) { mexErrMsgIdAndTxt(ERR_ID "BadSizeInput2", ERR_HEAD "2nd input [Spacing] does not match the dimensions."); } // Check 4th input: ---------------------------------------------------------- if (nrhs >= 4) { // "2ndOrder", but accept everything starting with "2": if (mxIsChar(prhs[3]) && !mxIsEmpty(prhs[3])) { Order2 = (*(mxChar *) mxGetData(prhs[3]) == L'2'); } else { mexErrMsgIdAndTxt(ERR_ID "BadTypeInput4", ERR_HEAD "4th input must be a string."); } } // Create output matrix: ----------------------------------------------------- plhs[0] = mxCreateNumericArray(ndimX, dimX, mxDOUBLE_CLASS, mxREAL); Y = mxGetPr(plhs[0]); // Reply ZEROS, if the length of the processed dimension is 1: if (nDX == 1) { return; } // Calculate the gradient: --------------------------------------------------- if (nSpace == 1) { // Scalar spacing if (Step == 1) { // Operate on 1st dimension CoreDim1Space1(X, nX, nDX, *Space, Y); } else { // Step >= 1, operate on any dimension CoreDimNSpace1(X, Step, nX, nDX, *Space, Y); } } else if (Order2) { // Spacing defined as vector, 2nd order method: if (nX == nDX) { // Single vector only - dynamic spacing factors: CoreDim1SpaceNOrder2(X, nX, nDX, Space, Y); } else { WrapSpaceNOrder2(X, Step, nX, nDX, Space, Y); } } else { // Spacing defined as vector, 1st order method: if (nX == nDX) { // Single vector only - dynamic spacing factors: CoreDim1SpaceN(X, nX, nDX, Space, Y); } else { WrapSpaceN(X, Step, nX, nDX, Space, Y); } } return; }
// SearchParamsをキャッシュする。 void Cache::CacheSearchParams(const SearchParams& params) { COPY_ARRAY(material_, params.material()); enable_quiesce_search_ = params.enable_quiesce_search(); enable_repetition_check_ = params.enable_repetition_check(); enable_check_extension_ = params.enable_check_extension(); ybwc_limit_depth_ = params.ybwc_limit_depth(); ybwc_invalid_moves_ = params.ybwc_invalid_moves(); enable_aspiration_windows_ = params.enable_aspiration_windows(); aspiration_windows_limit_depth_ = params.aspiration_windows_limit_depth(); aspiration_windows_delta_ = params.aspiration_windows_delta(); enable_see_ = params.enable_see(); enable_history_ = params.enable_history(); enable_killer_ = params.enable_killer(); enable_ttable_ = params.enable_ttable(); enable_iid_ = params.enable_iid(); iid_limit_depth_ = params.iid_limit_depth(); iid_search_depth_ = params.iid_search_depth(); enable_nmr_ = params.enable_nmr(); nmr_limit_depth_ = params.nmr_limit_depth(); nmr_search_reduction_ = params.nmr_search_reduction(); nmr_reduction_ = params.nmr_reduction(); enable_probcut_ = params.enable_probcut(); probcut_limit_depth_ = params.probcut_limit_depth(); probcut_margin_ = params.probcut_margin(); probcut_search_reduction_ = params.probcut_search_reduction(); if (params.enable_history()) { enable_history_pruning_ = params.enable_history_pruning(); } else { enable_history_pruning_ = false; } history_pruning_limit_depth_ = params.history_pruning_limit_depth(); for (unsigned int num_moves = 0; num_moves < (MAX_CANDIDATES + 1); ++num_moves) { history_pruning_invalid_moves_[num_moves] = Util::GetMax(params.history_pruning_invalid_moves(), static_cast<int>(params.history_pruning_move_threshold() * num_moves)); } history_pruning_threshold_ = params.history_pruning_threshold() * 256.0; history_pruning_reduction_ = params.history_pruning_reduction(); enable_lmr_ = params.enable_lmr(); lmr_limit_depth_ = params.lmr_limit_depth(); for (unsigned int num_moves = 0; num_moves < (MAX_CANDIDATES + 1); ++num_moves) { lmr_invalid_moves_[num_moves] = Util::GetMax(params.lmr_invalid_moves(), static_cast<int>(params.lmr_move_threshold() * num_moves)); } lmr_search_reduction_ = params.lmr_search_reduction(); enable_futility_pruning_ = params.enable_futility_pruning(); futility_pruning_depth_ = params.futility_pruning_depth(); for (int depth = 0; depth < static_cast<int>(MAX_PLYS + 1); ++depth) { if (enable_futility_pruning_) { if (depth <= futility_pruning_depth_) { if (depth <= 0) { futility_pruning_margin_[depth] = params.futility_pruning_margin(); } else { futility_pruning_margin_[depth] = params.futility_pruning_margin() * depth; } } else { futility_pruning_margin_[depth] = 3 * SCORE_WIN; } } else { futility_pruning_margin_[depth] = 3 * SCORE_WIN; } } }