From: lucasart Date: Mon, 3 Nov 2014 16:35:02 +0000 (+0800) Subject: Do not assume that enum are signed X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=d12378497cb24f40d3510cdcfaecd1335f523196 Do not assume that enum are signed Clang 3.5 issues warning on constructs like: abs(f1 - f2). The thing is that f1 and f2 are enum types, and the range given (all positive) allows the compiler to choose an unsigned type (efficiency being one reason to prefer unsigned arithmetic). If f1 < f2 are unsigned, then f1 - f2 wraps around zero and the abs() becomes a no-op. It's the reinterpretation of the unsigned result (large value) as a signed int that happens to give the correct result, thanks to 2's complement. This is all tricky and dangerous! In the spirit of the standard, we assume nothing on the signedness of enums, and simply calculate the rank and file distances as: - rank_dist(r1, r2) = r1 < r2 ? r2 - r1 : r1 - r2 - file_dist(f1, f2) = f1 < f2 ? f2 - f1 : f1 - f2 this logic can in fact be applied to any enum we may use, so for better generality and to avoid code duplication, we use a template function diff() here. No functional change. Resolves #95 --- diff --git a/src/bitboard.h b/src/bitboard.h index 6a1755b6..0cf0cd0a 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -119,11 +119,11 @@ inline int square_distance(Square s1, Square s2) { } inline int file_distance(Square s1, Square s2) { - return abs(file_of(s1) - file_of(s2)); + return dist(file_of(s1), file_of(s2)); } inline int rank_distance(Square s1, Square s2) { - return abs(rank_of(s1) - rank_of(s2)); + return dist(rank_of(s1), rank_of(s2)); } diff --git a/src/endgame.cpp b/src/endgame.cpp index 311443ec..2a1614af 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -479,7 +479,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { if ( r == RANK_6 && square_distance(bksq, queeningSq) <= 1 && rank_of(wksq) + tempo <= RANK_6 - && (rank_of(brsq) == RANK_1 || (!tempo && abs(file_of(brsq) - f) >= 3))) + && (rank_of(brsq) == RANK_1 || (!tempo && dist(file_of(brsq), f) >= 3))) return SCALE_FACTOR_DRAW; if ( r >= RANK_6 @@ -535,7 +535,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { { if (file_of(bksq) == file_of(wpsq)) return ScaleFactor(10); - if ( abs(file_of(bksq) - file_of(wpsq)) == 1 + if ( dist(file_of(bksq), file_of(wpsq)) == 1 && square_distance(wksq, bksq) > 2) return ScaleFactor(24 - 2 * square_distance(wksq, bksq)); } @@ -749,7 +749,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { && opposite_colors(ksq, wbsq) && ( bbsq == blockSq2 || (pos.attacks_from(blockSq2) & pos.pieces(weakSide, BISHOP)) - || abs(r1 - r2) >= 2)) + || dist(r1, r2) >= 2)) return SCALE_FACTOR_DRAW; else if ( ksq == blockSq2 diff --git a/src/types.h b/src/types.h index cbef89b7..543b38a8 100644 --- a/src/types.h +++ b/src/types.h @@ -254,6 +254,7 @@ enum Rank { RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NB }; +template inline T dist(T x, T y) { return x < y ? y - x : x - y; } /// The Score enum stores a middlegame and an endgame value in a single integer /// (enum). The least significant 16 bits are used to store the endgame value