]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
RootMoveList sorting: be compatible with std::sort
[stockfish] / src / search.cpp
index 2069315db8d8e1f2b673228bed57d786304b07dd..9cc8d4feb6ac048eebc108d1941f2bf3179f057a 100644 (file)
@@ -6,12 +6,12 @@
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
-  
+
   Glaurung is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
-  
+
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -51,10 +51,11 @@ namespace {
   // root move, we store a score, a node count, and a PV (really a refutation
   // in the case of moves which fail low).
 
-  class RootMove {
+  struct RootMove {
 
-  public:
     RootMove();
+    bool operator<(const RootMove&); // used to sort
+
     Move move;
     Value score;
     int64_t nodes, cumulativeNodes;
@@ -78,11 +79,10 @@ namespace {
     int64_t get_move_cumulative_nodes(int moveNum);
     int move_count() const;
     Move scan_for_easy_move() const;
-    void sort();
+    inline void sort();
     void sort_multipv(int n);
 
   private:
-    static int compare_root_moves(const RootMove &rm1, const RootMove &rm2);
     static const int MaxRootMoves = 500;
     RootMove moves[MaxRootMoves];
     int count;
@@ -266,7 +266,7 @@ namespace {
 #else
   DWORD WINAPI init_thread(LPVOID threadID);
 #endif
-  
+
 }
 
 
@@ -353,7 +353,7 @@ void think(const Position &pos, bool infinite, bool ponder, int time,
     Depth(get_option_value_int("Pawn Push to 7th Extension (non-PV nodes)"));
   PassedPawnExtension[1] =
     Depth(get_option_value_int("Passed Pawn Extension (PV nodes)"));
-  PassedPawnExtension[0] = 
+  PassedPawnExtension[0] =
     Depth(get_option_value_int("Passed Pawn Extension (non-PV nodes)"));
   PawnEndgameExtension[1] =
     Depth(get_option_value_int("Pawn Endgame Extension (PV nodes)"));
@@ -396,7 +396,7 @@ void think(const Position &pos, bool infinite, bool ponder, int time,
     get_option_value_int("Maximum Number of Threads per Split Point");
 
   read_weights(pos.side_to_move());
-  
+
   int newActiveThreads = get_option_value_int("Threads");
   if(newActiveThreads != ActiveThreads) {
     ActiveThreads = newActiveThreads;
@@ -462,7 +462,7 @@ void think(const Position &pos, bool infinite, bool ponder, int time,
 
   if(UseLogFile)
     LogFile.close();
-  
+
   if(Quit) {
     OpeningBook.close();
     stop_threads();
@@ -492,7 +492,7 @@ void init_threads() {
   lock_init(&IOLock, NULL);
 
   init_split_point_stack();
-  
+
 #if !defined(_MSC_VER)
   pthread_mutex_init(&WaitLock, NULL);
   pthread_cond_init(&WaitCond, NULL);
@@ -562,9 +562,11 @@ namespace {
 
   void id_loop(const Position &pos, Move searchMoves[]) {
     Position p(pos);
-    RootMoveList rml(p, searchMoves);
     SearchStack ss[PLY_MAX_PLUS_2];
 
+    // searchMoves are verified, copied, scored and sorted
+    RootMoveList rml(p, searchMoves);
+
     // Initialize
     TT.new_search();
     H.clear();
@@ -643,7 +645,7 @@ namespace {
         }
       }
 
-      // Write PV to transposition table, in case the relevant entries have 
+      // Write PV to transposition table, in case the relevant entries have
       // been overwritten during the search:
       TT.insert_pv(p, ss[0].pv);
 
@@ -710,7 +712,7 @@ namespace {
       if(current_search_time() >= 1000)
         std::cout << "info currmove " << move
                   << " currmovenumber " << i + 1 << std::endl;
-      
+
       // Decide search depth for this move:
       ext = extension(pos, move, true, pos.move_is_check(move), false, false);
       newDepth = (Iteration-2)*OnePly + ext + InitialDepth;
@@ -732,7 +734,7 @@ namespace {
       else {
         value = -search(pos, ss, -alpha, newDepth, 1, true, 0);
         if(value > alpha) {
-          // Fail high!  Set the boolean variable FailHigh to true, and 
+          // Fail high!  Set the boolean variable FailHigh to true, and
           // re-search the move with a big window.  The variable FailHigh is
           // used for time managment:  We try to avoid aborting the search
           // prematurely during a fail high research.
@@ -751,7 +753,7 @@ namespace {
       if(AbortSearch)
         break;
 
-      // Remember the node count for this move.  The node counts are used to 
+      // Remember the node count for this move.  The node counts are used to
       // sort the root moves at the next iteration.
       rml.set_move_nodes(i, nodes_searched() - nodes);
 
@@ -768,7 +770,7 @@ namespace {
         rml.set_move_pv(i, ss[0].pv);
 
         if(MultiPV == 1) {
-          // We record how often the best move has been changed in each 
+          // We record how often the best move has been changed in each
           // iteration.  This information is used for time managment:  When
           // the best move changes frequently, we allocate some more time.
           if(i > 0)
@@ -856,7 +858,7 @@ namespace {
       return alpha;
 
     // Transposition table lookup.  At PV nodes, we don't use the TT for
-    // pruning, but only for move ordering.  
+    // pruning, but only for move ordering.
     Value ttValue;
     Depth ttDepth;
     Move ttMove = MOVE_NONE;
@@ -892,7 +894,7 @@ namespace {
       bool moveIsCheck = pos.move_is_check(move, dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
       bool moveIsPassedPawnPush = pos.move_is_passed_pawn_push(move);
-      
+
       assert(move_is_ok(move));
       movesSearched[moveCount++] = ss[ply].currentMove = move;
 
@@ -905,8 +907,8 @@ namespace {
 
       // Make and search the move.
       pos.do_move(move, u, dcCandidates);
-      
-      if(moveCount == 1) 
+
+      if(moveCount == 1)
         value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1, threadID);
       else {
         if(depth >= 2*OnePly && ext == Depth(0) && moveCount >= LMRPVMoves
@@ -914,7 +916,7 @@ namespace {
            && !moveIsPassedPawnPush && !move_is_castle(move)
            && move != ss[ply].killer1 && move != ss[ply].killer2) {
           ss[ply].reduction = OnePly;
-          value = -search(pos, ss, -alpha, newDepth-OnePly, ply+1, true, 
+          value = -search(pos, ss, -alpha, newDepth-OnePly, ply+1, true,
                           threadID);
         }
         else value = alpha + 1;
@@ -929,7 +931,7 @@ namespace {
               // such cases, because resolving the fail high at ply 1 could
               // result in a big drop in score at the root.
               Threads[threadID].failHighPly1 = true;
-            value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1, 
+            value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1,
                                threadID);
             Threads[threadID].failHighPly1 = false;
           }
@@ -938,7 +940,7 @@ namespace {
       pos.undo_move(move, u);
 
       assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
-      
+
       // New best move?
       if(value > bestValue) {
         bestValue = value;
@@ -974,7 +976,7 @@ namespace {
         return VALUE_DRAW;
     }
 
-    // If the search is not aborted, update the transposition table, 
+    // If the search is not aborted, update the transposition table,
     // history counters, and killer moves.  This code is somewhat messy,
     // and definitely needs to be cleaned up.  FIXME
     if(!AbortSearch && !thread_should_stop(threadID)) {
@@ -993,7 +995,7 @@ namespace {
                         movesSearched[i]);
 
           H.success(pos.piece_on(move_from(m)), m, depth);
-          
+
           if(m != ss[ply].killer1) {
             ss[ply].killer2 = ss[ply].killer1;
             ss[ply].killer1 = m;
@@ -1008,7 +1010,7 @@ namespace {
 
     return bestValue;
   }
-  
+
 
   // search() is the search function for zero-width nodes.
 
@@ -1150,7 +1152,7 @@ namespace {
       // Futility pruning
       if(useFutilityPruning && ext == Depth(0) && !moveIsCapture &&
          !moveIsPassedPawnPush && !move_promotion(move)) {
-        
+
         if(moveCount >= 2 + int(depth)
            && ok_to_prune(pos, move, ss[ply].threatMove, depth))
           continue;
@@ -1169,7 +1171,7 @@ namespace {
 
       // Make and search the move.
       pos.do_move(move, u, dcCandidates);
-      
+
       if(depth >= 2*OnePly && ext == Depth(0) && moveCount >= LMRNonPVMoves
          && !moveIsCapture && !move_promotion(move) && !moveIsPassedPawnPush
          && !move_is_castle(move)
@@ -1187,7 +1189,7 @@ namespace {
       pos.undo_move(move, u);
 
       assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
-      
+
       // New best move?
       if(value > bestValue) {
         bestValue = value;
@@ -1224,7 +1226,7 @@ namespace {
                  VALUE_TYPE_UPPER);
       else {
         Move m = ss[ply].pv[ply];
-                                                       
+
         if(pos.square_is_empty(move_to(m)) && !move_promotion(m) &&
            !move_is_ep(m)) {
           for(int i = 0; i < moveCount - 1; i++)
@@ -1234,7 +1236,7 @@ namespace {
               H.failure(pos.piece_on(move_from(movesSearched[i])),
                         movesSearched[i]);
           H.success(pos.piece_on(move_from(m)), m, depth);
-          
+
           if(m != ss[ply].killer1) {
             ss[ply].killer2 = ss[ply].killer1;
             ss[ply].killer1 = m;
@@ -1246,7 +1248,7 @@ namespace {
 
     return bestValue;
   }
-  
+
 
   // qsearch() is the quiescence search function, which is called by the main
   // search function when the remaining depth is zero (or, to be more precise,
@@ -1263,7 +1265,7 @@ namespace {
     assert(ply >= 0 && ply < PLY_MAX);
     assert(threadID >= 0 && threadID < ActiveThreads);
 
-    // Initialize, and make an early exit in case of an aborted search, 
+    // Initialize, and make an early exit in case of an aborted search,
     // an instant draw, maximum ply reached, etc.
     if(AbortSearch || thread_should_stop(threadID))
       return Value(0);
@@ -1300,7 +1302,7 @@ namespace {
     Bitboard dcCandidates = mp.discovered_check_candidates();
     bool isCheck = pos.is_check();
 
-    // Loop through the moves until no moves remain or a beta cutoff 
+    // Loop through the moves until no moves remain or a beta cutoff
     // occurs.
     while(alpha < beta && ((move = mp.get_next_move()) != MOVE_NONE)) {
       UndoInfo u;
@@ -1313,18 +1315,18 @@ namespace {
       ss[ply].currentMove = move;
 
       // Futility pruning
-      if(UseQSearchFutilityPruning && !isCheck && !moveIsCheck && 
-         !move_promotion(move) && !moveIsPassedPawnPush && 
+      if(UseQSearchFutilityPruning && !isCheck && !moveIsCheck &&
+         !move_promotion(move) && !moveIsPassedPawnPush &&
          beta - alpha == 1 &&
          pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame) {
         Value futilityValue =
-          staticValue 
+          staticValue
           + Max(pos.midgame_value_of_piece_on(move_to(move)),
                 pos.endgame_value_of_piece_on(move_to(move)))
           + FutilityMargin0
           + ei.futilityMargin;
         if(futilityValue < alpha) {
-          if(futilityValue > bestValue) 
+          if(futilityValue > bestValue)
             bestValue = futilityValue;
           continue;
         }
@@ -1355,7 +1357,7 @@ namespace {
     }
 
     // All legal moves have been searched.  A special case: If we're in check
-    // and no legal moves were found, it is checkmate: 
+    // and no legal moves were found, it is checkmate:
     if(pos.is_check() && moveCount == 0) // Mate!
       return value_mated_in(ply);
 
@@ -1372,11 +1374,11 @@ namespace {
   // splitting, we don't have to repeat all this work in sp_search().  We
   // also don't need to store anything to the hash table here:  This is taken
   // care of after we return from the split point.
-  
+
   void sp_search(SplitPoint *sp, int threadID) {
     assert(threadID >= 0 && threadID < ActiveThreads);
     assert(ActiveThreads > 1);
-    
+
     Position pos = Position(sp->pos);
     SearchStack *ss = sp->sstack[threadID];
     Value value;
@@ -1437,7 +1439,7 @@ namespace {
 
       if(thread_should_stop(threadID))
         break;
-      
+
       // New best move?
       lock_grab(&(sp->lock));
       if(value > sp->bestValue && !thread_should_stop(threadID)) {
@@ -1476,11 +1478,11 @@ namespace {
   // don't have to repeat all this work in sp_search_pv().  We also don't
   // need to store anything to the hash table here:  This is taken care of
   // after we return from the split point.
-  
+
   void sp_search_pv(SplitPoint *sp, int threadID) {
     assert(threadID >= 0 && threadID < ActiveThreads);
     assert(ActiveThreads > 1);
-    
+
     Position pos = Position(sp->pos);
     SearchStack *ss = sp->sstack[threadID];
     Value value;
@@ -1506,7 +1508,7 @@ namespace {
       lock_release(&(sp->lock));
 
       ss[sp->ply].currentMove = move;
-      
+
       // Decide the new search depth.
       ext = extension(pos, move, true, moveIsCheck, false, false);
       newDepth = sp->depth - OnePly + ext;
@@ -1546,7 +1548,7 @@ namespace {
 
       if(thread_should_stop(threadID))
         break;
-      
+
       // New best move?
       lock_grab(&(sp->lock));
       if(value > sp->bestValue && !thread_should_stop(threadID)) {
@@ -1586,7 +1588,7 @@ namespace {
     sp->slaves[threadID] = 0;
 
     lock_release(&(sp->lock));
-  }  
+  }
 
 
   /// The RootMove class
@@ -1596,51 +1598,58 @@ namespace {
   RootMove::RootMove() {
     nodes = cumulativeNodes = 0ULL;
   }
-  
+
+  // RootMove::operator<() is the comparison function used when
+  // sorting the moves.  A move m1 is considered to be better
+  // than a move m2 if it has a higher score, or if the moves
+  // have equal score but m1 has the higher node count.
+
+  bool RootMove::operator<(const RootMove& m) {
+
+    if (score != m.score)
+        return (score < m.score);
+
+    return nodes <= m.nodes;
+  }
 
   /// The RootMoveList class
 
   // Constructor
 
-  RootMoveList::RootMoveList(Position &pos, Move searchMoves[]) {
+  RootMoveList::RootMoveList(Position& pos, Move searchMoves[]) : count(0) {
+
     MoveStack mlist[MaxRootMoves];
     bool includeAllMoves = (searchMoves[0] == MOVE_NONE);
-    int i, j = 0, k;
 
     // Generate all legal moves
-    count = generate_legal_moves(pos, mlist);
+    int lm_count = generate_legal_moves(pos, mlist);
 
     // Add each move to the moves[] array
-    for(i = 0; i < count; i++) {
-      UndoInfo u;
-      SearchStack ss[PLY_MAX_PLUS_2];
-      bool includeMove;
-
-      if(includeAllMoves)
-        includeMove = true;
-      else {
-        includeMove = false;
-        for(k = 0; searchMoves[k] != MOVE_NONE; k++)
-          if(searchMoves[k] == mlist[i].move) {
-            includeMove = true;
-            break;
-          }
-      }
-
-      if(includeMove) {
-        moves[j].move = mlist[i].move;
-        moves[j].nodes = 0ULL;
-        pos.do_move(moves[j].move, u);
-        moves[j].score = -qsearch(pos, ss, -VALUE_INFINITE, VALUE_INFINITE,
-                                  Depth(0), 1, 0);
-        pos.undo_move(moves[j].move, u);
-        moves[j].pv[0] = moves[i].move;
-        moves[j].pv[1] = MOVE_NONE; // FIXME
-        j++;
-      }
+    for (int i = 0; i < lm_count; i++)
+    {
+        bool includeMove = includeAllMoves;
+
+        for (int k = 0; !includeMove && searchMoves[k] != MOVE_NONE; k++)
+            includeMove = (searchMoves[k] == mlist[i].move);
+
+        if (includeMove)
+        {
+            // Find a quick score for the move
+            UndoInfo u;
+            SearchStack ss[PLY_MAX_PLUS_2];
+
+            moves[count].move = mlist[i].move;
+            moves[count].nodes = 0ULL;
+            pos.do_move(moves[count].move, u);
+            moves[count].score = -qsearch(pos, ss, -VALUE_INFINITE, VALUE_INFINITE,
+                                          Depth(0), 1, 0);
+            pos.undo_move(moves[count].move, u);
+            moves[count].pv[0] = moves[i].move;
+            moves[count].pv[1] = MOVE_NONE; // FIXME
+            count++;
+        }
     }
-    count = j;
-    this->sort();
+    sort();
   }
 
 
@@ -1657,7 +1666,7 @@ namespace {
   void RootMoveList::set_move_score(int moveNum, Value score) {
     moves[moveNum].score = score;
   }
-  
+
   void RootMoveList::set_move_nodes(int moveNum, int64_t nodes) {
     moves[moveNum].nodes = nodes;
     moves[moveNum].cumulativeNodes += nodes;
@@ -1677,7 +1686,7 @@ namespace {
   int64_t RootMoveList::get_move_cumulative_nodes(int moveNum) {
     return moves[moveNum].cumulativeNodes;
   }
-  
+
   int RootMoveList::move_count() const {
     return count;
   }
@@ -1689,61 +1698,48 @@ namespace {
   // is returned, otherwise the function returns MOVE_NONE.  It is very
   // important that this function is called at the right moment:  The code
   // assumes that the first iteration has been completed and the moves have
-  // been sorted.
+  // been sorted. This is done in RootMoveList c'tor.
 
   Move RootMoveList::scan_for_easy_move() const {
-    Value bestMoveValue = this->get_move_score(0);
-    for(int i = 1; i < this->move_count(); i++)
-      if(this->get_move_score(i) >= bestMoveValue - EasyMoveMargin)
-        return MOVE_NONE;
-    return this->get_move(0);
-  }
 
+    assert(count);
+
+    if (count == 1)
+        return get_move(0);
+
+    // moves are sorted so just consider the best and the second one
+    if (get_move_score(0) > get_move_score(1) + EasyMoveMargin)
+        return get_move(0);
+
+    return MOVE_NONE;
+  }
 
   // RootMoveList::sort() sorts the root move list at the beginning of a new
   // iteration.
 
-  void RootMoveList::sort() {
-    for(int i = 1; i < count; i++) {
-      RootMove rm = moves[i];
-      int j;
-      for(j = i; j > 0 && compare_root_moves(moves[j-1], rm); j--)
-        moves[j] = moves[j-1];
-      moves[j] = rm;
-    }
+  inline void RootMoveList::sort() {
+
+    sort_multipv(count - 1); // all items
   }
 
 
   // RootMoveList::sort_multipv() sorts the first few moves in the root move
-  // list by their scores and depths.  It is used to order the different PVs
+  // list by their scores and depths. It is used to order the different PVs
   // correctly in MultiPV mode.
 
   void RootMoveList::sort_multipv(int n) {
-    for(int i = 1; i <= n; i++) {
+
+    for (int i = 1; i <= n; i++)
+    {
       RootMove rm = moves[i];
       int j;
-      for(j = i; j > 0 && moves[j-1].score < rm.score; j--)
-        moves[j] = moves[j-1];
+      for (j = i; j > 0 && moves[j-1] < rm; j--)
+          moves[j] = moves[j-1];
       moves[j] = rm;
     }
   }
 
 
-  // RootMoveList::compare_root_moves() is the comparison function used by
-  // RootMoveList::sort when sorting the moves.  A move m1 is considered to
-  // be better than a move m2 if it has a higher score, or if the moves have
-  // equal score but m1 has the higher node count.
-  
-  int RootMoveList::compare_root_moves(const RootMove &rm1,
-                                       const RootMove &rm2) {
-    if(rm1.score < rm2.score) return 1;
-    else if(rm1.score > rm2.score) return 0;
-    else if(rm1.nodes < rm2.nodes) return 1;
-    else if(rm1.nodes > rm2.nodes) return 0;
-    else return 1;
-  }
-
-
   // init_search_stack() initializes a search stack at the beginning of a
   // new search from the root.
 
@@ -1796,7 +1792,7 @@ namespace {
   // update_pv() is called whenever a search returns a value > alpha.  It
   // updates the PV in the SearchStack object corresponding to the current
   // node.
-    
+
   void update_pv(SearchStack ss[], int ply) {
     assert(ply >= 0 && ply < PLY_MAX);
 
@@ -1887,8 +1883,8 @@ namespace {
 
     return false;
   }
-    
-  
+
+
   // extension() decides whether a move should be searched with normal depth,
   // or with extended depth.  Certain classes of moves (checking moves, in
   // particular) are searched with bigger depth than ordinary moves.
@@ -1974,7 +1970,7 @@ namespace {
     // Case 4: Don't prune moves with good history.
     if(!H.ok_to_prune(pos.piece_on(move_from(m)), m, d))
       return false;
-    
+
     // Case 5: If the moving piece in the threatened move is a slider, don't
     // prune safe moves which block its ray.
     if(!PruneBlockingMoves && threat != MOVE_NONE
@@ -1984,12 +1980,12 @@ namespace {
 
     return true;
   }
-  
+
 
   // fail_high_ply_1() checks if some thread is currently resolving a fail
   // high at ply 1 at the node below the first root node.  This information
   // is used for time managment.
-  
+
   bool fail_high_ply_1() {
     for(int i = 0; i < ActiveThreads; i++)
       if(Threads[i].failHighPly1)
@@ -2042,7 +2038,7 @@ namespace {
       else if(strncmp(input, "ponderhit", 9) == 0)
         ponderhit();
     }
-    
+
     // Print search information
     if(t < 1000)
       lastInfoTime = 0;
@@ -2056,7 +2052,7 @@ namespace {
       std::cout << "info nodes " << nodes_searched() << " nps " << nps()
                 << " time " << t << " hashfull " << TT.full() << std::endl;
       lock_release(&IOLock);
-      if(ShowCurrentLine) 
+      if(ShowCurrentLine)
         Threads[0].printCurrentLine = true;
     }
 
@@ -2098,7 +2094,7 @@ namespace {
 
   // print_current_line() prints the current line of search for a given
   // thread.  Called when the UCI option UCI_ShowCurrLine is 'true'.
-  
+
   void print_current_line(SearchStack ss[], int ply, int threadID) {
     assert(ply >= 0 && ply < PLY_MAX);
     assert(threadID >= 0 && threadID < ActiveThreads);
@@ -2123,14 +2119,14 @@ namespace {
   // "bestmove" before the GUI sends it a "stop" or "ponderhit" command.
   // We simply wait here until one of these commands is sent, and return,
   // after which the bestmove and pondermove will be printed (in id_loop()).
-  
+
   void wait_for_stop_or_ponderhit() {
     std::string command;
 
     while(true) {
       if(!std::getline(std::cin, command))
         command = "quit";
-      
+
       if(command == "quit") {
         OpeningBook.close();
         stop_threads();
@@ -2142,7 +2138,7 @@ namespace {
     }
   }
 
-  
+
   // idle_loop() is where the threads are parked when they have no work to do.
   // The parameter "waitSp", if non-NULL, is a pointer to an active SplitPoint
   // object for which the current thread is the master.
@@ -2150,7 +2146,7 @@ namespace {
   void idle_loop(int threadID, SplitPoint *waitSp) {
     assert(threadID >= 0 && threadID < THREAD_MAX);
 
-    Threads[threadID].running = true; 
+    Threads[threadID].running = true;
 
     while(true) {
       if(AllThreadsShouldExit && threadID != 0)
@@ -2208,7 +2204,7 @@ namespace {
     for(int i = 0; i < THREAD_MAX; i++)
       for(int j = 0; j < MaxActiveSplitPoints; j++)
         lock_destroy(&(SplitPointStack[i][j].lock));
-  }  
+  }
 
 
   // thread_should_stop() checks whether the thread with a given threadID has
@@ -2218,7 +2214,7 @@ namespace {
 
   bool thread_should_stop(int threadID) {
     assert(threadID >= 0 && threadID < ActiveThreads);
-  
+
     SplitPoint *sp;
 
     if(Threads[threadID].stop)
@@ -2231,7 +2227,7 @@ namespace {
         return true;
       }
     return false;
-  }  
+  }
 
 
   // thread_is_available() checks whether the thread with threadID "slave" is
@@ -2246,7 +2242,7 @@ namespace {
     assert(slave >= 0 && slave < ActiveThreads);
     assert(master >= 0 && master < ActiveThreads);
     assert(ActiveThreads > 1);
-  
+
     if(!Threads[slave].idle || slave == master)
       return false;
 
@@ -2265,14 +2261,14 @@ namespace {
     return false;
   }
 
-  
+
   // idle_thread_exists() tries to find an idle thread which is available as
   // a slave for the thread with threadID "master".
 
   bool idle_thread_exists(int master) {
     assert(master >= 0 && master < ActiveThreads);
     assert(ActiveThreads > 1);
-  
+
     for(int i = 0; i < ActiveThreads; i++)
       if(thread_is_available(i, master))
         return true;
@@ -2410,20 +2406,20 @@ namespace {
 #endif
     }
   }
-    
+
 
   // init_thread() is the function which is called when a new thread is
   // launched.  It simply calls the idle_loop() function with the supplied
   // threadID.  There are two versions of this function; one for POSIX threads
   // and one for Windows threads.
-  
+
 #if !defined(_MSC_VER)
 
   void *init_thread(void *threadID) {
     idle_loop(*(int *)threadID, NULL);
     return NULL;
   }
-  
+
 #else
 
   DWORD WINAPI init_thread(LPVOID threadID) {