char binetasymptotic(floatnum x, int digits) { floatstruct recsqr; floatstruct sum; floatstruct smd; floatstruct pwr; int i, workprec; if (float_getexponent(x) >= digits) { /* if x is very big, ln(gamma(x)) is dominated by x*ln x and the Binet function does not contribute anything substantial to the final result */ float_setzero(x); return 1; } float_create(&recsqr); float_create(&sum); float_create(&smd); float_create(&pwr); float_copy(&pwr, &c1, EXACT); float_setzero(&sum); float_div(&smd, &c1, &c12, digits+1); workprec = digits - 2*float_getexponent(x)+3; i = 1; if (workprec > 0) { float_mul(&recsqr, x, x, workprec); float_reciprocal(&recsqr, workprec); while (float_getexponent(&smd) > -digits-1 && ++i <= MAXBERNOULLIIDX) { workprec = digits + float_getexponent(&smd) + 3; float_add(&sum, &sum, &smd, digits+1); float_mul(&pwr, &recsqr, &pwr, workprec); float_muli(&smd, &cBernoulliDen[i-1], 2*i*(2*i-1), workprec); float_div(&smd, &pwr, &smd, workprec); float_mul(&smd, &smd, &cBernoulliNum[i-1], workprec); } } else /* sum reduces to the first summand*/ float_move(&sum, &smd); if (i > MAXBERNOULLIIDX) /* x was not big enough for the asymptotic series to converge sufficiently */ float_setnan(x); else float_div(x, &sum, x, digits); float_free(&pwr); float_free(&smd); float_free(&sum); float_free(&recsqr); return i <= MAXBERNOULLIIDX; }
Error pack2floatnum( floatnum x, p_number_desc n) { floatstruct tmp; int digits; int saveerr; int saverange; Error result; signed char base; if ((result = _pack2int(x, &n->intpart)) != Success) return result; if (float_isnan(x)) return Success; saveerr = float_geterror(); saverange = float_setrange(MAXEXP); float_create(&tmp); float_move(&tmp, x); float_setzero(x); digits = DECPRECISION - float_getexponent(&tmp); if (digits <= 0 || (result = _pack2frac(x, &n->fracpart, digits)) == Success) float_add(x, x, &tmp, DECPRECISION); if (result != Success) return result; if ((!float_getlength(x)) == 0) /* no zero, no NaN? */ { base = n->prefix.base; float_setinteger(&tmp, base); if (n->exp >= 0) { _raiseposi_(&tmp, n->exp, DECPRECISION + 2); float_mul(x, x, &tmp, DECPRECISION + 2); } else { _raiseposi_(&tmp, -n->exp, DECPRECISION + 2); float_div(x, x, &tmp, DECPRECISION + 2); } } float_free(&tmp); float_setsign(x, n->prefix.sign == IO_SIGN_COMPLEMENT? -1 : n->prefix.sign); float_geterror(); float_seterror(saveerr); float_setrange(saverange); if (!float_isvalidexp(float_getexponent(x))) float_setnan(x); return float_isnan(x)? IOExpOverflow : Success; }
void ponder_move( int side_to_move, int book, int mid, int exact, int wld ) { EvaluationType eval_info; HashEntry entry; double move_start_time, move_stop_time; int i, j; int this_move, hash_move; int expect_count; int stored_echo; int best_pv_depth; int expect_list[64]; int best_pv[61]; /* Disable all time control mechanisms as it's the opponent's time we're using */ toggle_abort_check( FALSE ); toggle_midgame_abort_check( FALSE ); start_move( 0, 0, disc_count( BLACKSQ ) + disc_count( WHITESQ ) ); clear_ponder_times(); determine_hash_values( side_to_move, board ); reset_counter( &nodes ); /* Find the scores for the moves available to the opponent. */ hash_move = 0; find_hash( &entry, ENDGAME_MODE ); if ( entry.draft != NO_HASH_MOVE ) hash_move = entry.move[0]; else { find_hash( &entry, MIDGAME_MODE ); if ( entry.draft != NO_HASH_MOVE ) hash_move = entry.move[0]; } stored_echo = echo; echo = FALSE; (void) compute_move( side_to_move, FALSE, 0, 0, FALSE, FALSE, MIN( PONDER_DEPTH, mid ), 0, 0, FALSE, &eval_info ); echo = stored_echo; /* Sort the opponents on the score and push the table move (if any) to the front of the list */ if ( force_return ) expect_count = 0; else { sort_moves( move_count[disks_played] ); (void) float_move( hash_move, move_count[disks_played] ); expect_count = move_count[disks_played]; for ( i = 0; i < expect_count; i++ ) expect_list[i] = move_list[disks_played][i]; #if TEXT_BASED printf( "%s=%d\n", HASH_MOVE_TEXT, hash_move ); for ( i = 0; i < expect_count; i++ ) { printf( "%c%c %-6.2f ", TO_SQUARE( move_list[disks_played][i] ), evals[disks_played][move_list[disks_played][i]] / 128.0 ); if ( (i % 7 == 6) || (i == expect_count - 1) ) puts( "" ); } #endif } /* Go through the expected moves in order and prepare responses. */ best_pv_depth = 0; for ( i = 0; !force_return && (i < expect_count); i++ ) { move_start_time = get_real_timer(); set_ponder_move( expect_list[i] ); this_move = expect_list[i]; prefix_move = this_move; (void) make_move( side_to_move, this_move, TRUE ); (void) compute_move( OPP( side_to_move ), FALSE, 0, 0, TRUE, FALSE, mid, exact, wld, FALSE, &eval_info ); unmake_move( side_to_move, this_move ); clear_ponder_move(); move_stop_time = get_real_timer(); add_ponder_time( expect_list[i], move_stop_time - move_start_time ); ponder_depth[expect_list[i]] = MAX( ponder_depth[expect_list[i]], max_depth_reached - 1 ); if ( (i == 0) && !force_return ) { /* Store the PV for the first move */ best_pv_depth = pv_depth[0]; for ( j = 0; j < pv_depth[0]; j++ ) best_pv[j] = pv[0][j]; } } /* Make sure the PV looks reasonable when leaving - either by clearing it altogether or, preferrably, using the stored PV for the first move if it is available. */ max_depth_reached++; prefix_move = 0; if ( best_pv_depth == 0 ) pv_depth[0] = 0; else { pv_depth[0] = best_pv_depth + 1; pv[0][0] = expect_list[0]; for ( i = 0; i < best_pv_depth; i++ ) pv[0][i + 1] = best_pv[i]; } /* Don't forget to enable the time control mechanisms when leaving */ toggle_abort_check( TRUE ); toggle_midgame_abort_check( TRUE ); }
char erfcsum( floatnum x, /* should be the square of the parameter to erfc */ int digits) { int i, workprec; floatstruct sum, smd; floatnum Ei; if (digits > erfcdigits) { /* cannot re-use last evaluation's intermediate results */ for (i = MAXERFCIDX; --i >= 0;) /* clear all exp(-k*k*alpha*alpha) to indicate their absence */ float_free(&erfccoeff[i]); /* current precision */ erfcdigits = digits; /* create new alpha appropriate for the desired precision This alpha need not be high precision, any alpha near the one evaluated here would do */ float_muli(&erfcalpha, &cLn10, digits + 4, 3); float_sqrt(&erfcalpha, 3); float_div(&erfcalpha, &cPi, &erfcalpha, 3); float_mul(&erfcalphasqr, &erfcalpha, &erfcalpha, EXACT); /* the exp(-k*k*alpha*alpha) are later evaluated iteratively. Initiate the iteration here */ float_copy(&erfct2, &erfcalphasqr, EXACT); float_neg(&erfct2); _exp(&erfct2, digits + 3); /* exp(-alpha*alpha) */ float_copy(erfccoeff, &erfct2, EXACT); /* start value */ float_mul(&erfct3, &erfct2, &erfct2, digits + 3); /* exp(-2*alpha*alpha) */ } float_create(&sum); float_create(&smd); float_setzero(&sum); for (i = 0; ++i < MAXERFCIDX;) { Ei = &erfccoeff[i-1]; if (float_isnan(Ei)) { /* if exp(-i*i*alpha*alpha) is not available, evaluate it from the coefficient of the last summand */ float_mul(&erfct2, &erfct2, &erfct3, workprec + 3); float_mul(Ei, &erfct2, &erfccoeff[i-2], workprec + 3); } /* Ei finally decays rapidly. save some time by adjusting the working precision */ workprec = digits + float_getexponent(Ei) + 1; if (workprec <= 0) break; /* evaluate the summand exp(-i*i*alpha*alpha)/(i*i*alpha*alpha+x) */ float_muli(&smd, &erfcalphasqr, i*i, workprec); float_add(&smd, x, &smd, workprec + 2); float_div(&smd, Ei, &smd, workprec + 1); /* add summand to the series */ float_add(&sum, &sum, &smd, digits + 3); } float_move(x, &sum); float_free(&smd); return 1; }