/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Storage.java
* Written by: Christian Julg, Jonas Thedering (Team 1)
*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* 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.
*
* Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.routing.experimentalAStar1;
/**
* Contains the open and closed lists for the A* algorithm and allows for
* getting the node corresponding to a position, if any
*
* @author Jonas Thedering
* @author Christian Jülg
*/
public class Storage implements Poolable<Storage> {
private boolean DEBUG = false;
private PriorityQueue queue = new PriorityQueue();
private Storage tail;
private Node[] nodeMap = null;
private int width = -1, height = -1, layers = -1;
private Node nodeListHead = null;
// Contains the node that was inserted first, needed to avoid list walking in cleanup
private Node nodeListLast = null;
// Bounding boxes for map cleaning
private int[] minX, maxX, minY, maxY;
// Only for debugging
private int nodeCount = 0;
public Storage() {
DEBUG &= AStarRoutingFrame.getInstance().isOutputEnabled();
}
/** Ensures the storage is set to the initial state */
public void initialize(int width, int height, int layers) {
if(nodeMap == null || width != this.width || height != this.height || layers != this.layers) {
this.width = width;
this.height = height;
this.layers = layers;
nodeMap = new Node[width * height*layers]; // All entries will implicitly be null
minX = new int[layers];
maxX = new int[layers];
minY = new int[layers];
maxY = new int[layers];
}
else {
long startTime = 0;
if (DEBUG) {
startTime= System.nanoTime();
}
for(int z=0; z<layers; ++z) {
int temp = z * height;
for(int y=minY[z]; y<=maxY[z]; ++y) {
int temp2 = (temp + y) * width;
for(int x=minX[z]; x<=maxX[z]; ++x)
nodeMap[temp2 + x] = null;
}
}
if(DEBUG) {
float percentage = 0.0f;
int sweepedCount = 0;
for(int z=0; z<layers; ++z)
if(maxX[z] >= minX[z] && maxY[z] >= minY[z])
sweepedCount += (maxY[z]-minY[z]+1)*(maxX[z]-minX[z]+1);
if(sweepedCount != 0)
percentage = (nodeCount * 100.0f) / sweepedCount;
System.out.printf("Storage: Sweeping nodeMap in %d ms, %d/%d necessary sweeps (%.1f %%)\n", (System.nanoTime() - startTime) / 1000000, nodeCount, sweepedCount, percentage);
}
nodeCount = 0;
}
for(int z=0; z < layers; ++z) {
minX[z] = Integer.MAX_VALUE;
maxX[z] = Integer.MIN_VALUE;
minY[z] = Integer.MAX_VALUE;
maxY[z] = Integer.MIN_VALUE;
}
queue.clear();
nodeListHead = null;
nodeListLast = null;
}
/** Adds the given node to the open list */
public void addToOpen(Node node) {
// Mark as open
node.childCount = -1;
queue.add(node);
int nodeMapIndex = (node.z * height + node.y) * width + node.x;
int z = node.z;
minX[z] = Math.min(minX[z], node.x);
maxX[z] = Math.max(maxX[z], node.x);
minY[z] = Math.min(minY[z], node.y);
maxY[z] = Math.max(maxY[z], node.y);
nodeMap[nodeMapIndex] = node;
++nodeCount;
// Add to node list for later cleanup
node.setTail(nodeListHead);
if(nodeListHead == null)
nodeListLast = node;
nodeListHead = node;
}
/** Moves the cheapest node from open list to closed list and returns it */
public Node shiftCheapestNode() {
Node node = queue.remove();
// Mark as closed
node.childCount = 0;
return node;
}
public boolean isOpenEmpty() {
return queue.isEmpty();
}
/** @return if there's a node corresponding to the given position*/
public boolean contains(int x, int y, int z) {
return nodeMap[(z * height + y) * width + x] != null;
}
/** @return the node corresponding to the given position, if any */
public Node get(int x, int y, int z) {
return nodeMap[(z * height + y) * width + x];
}
public boolean isNodeInOpen(Node node) {
return node.childCount == -1;
}
/** Updates the node's cost attribute and notifies the open list of it */
public void decreaseCost(Node node, int newCost) {
queue.decreaseKey(node, newCost);
}
/** Returns the nodes contained to the given pool */
public void freeNodes(ObjectPool<Node> pool) {
if(nodeListHead != null) {
pool.freeAllLinked(nodeListHead, nodeListLast);
nodeListHead = null;
nodeListLast = null;
}
}
public Storage getTail() {
return tail;
}
public void setTail(Storage tail) {
this.tail = tail;
}
}