Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* ComplexVector.java
*
* Copyright (C) 2002-2007 Peter Graves
* $Id$
*
* This program 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 2
* of the License, or (at your option) any later version.
*
* This program 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under
* terms of your choice, provided that you also meet, for each linked
* independent module, the terms and conditions of the license of that
* module. An independent module is a module which is not derived from
* or based on this library. If you modify this library, you may extend
* this exception to your version of the library, but you are not
* obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
package org.armedbear.lisp;
import static org.armedbear.lisp.Lisp.*;
// A vector that is displaced to another array, has a fill pointer, and/or is
// expressly adjustable. It can hold elements of any type.
public final class ComplexVector extends AbstractVector
{
private int capacity;
private int fillPointer = -1; // -1 indicates no fill pointer.
private boolean isDisplaced;
// For non-displaced arrays.
private LispObject[] elements;
// For displaced arrays.
private AbstractArray array;
private int displacement;
public ComplexVector(int capacity)
{
elements = new LispObject[capacity];
for (int i = capacity; i-- > 0;)
elements[i] = Fixnum.ZERO;
this.capacity = capacity;
}
public ComplexVector(int capacity, AbstractArray array, int displacement)
{
this.capacity = capacity;
this.array = array;
this.displacement = displacement;
isDisplaced = true;
}
@Override
public LispObject typeOf()
{
return list(Symbol.VECTOR, T, Fixnum.getInstance(capacity));
}
@Override
public LispObject classOf()
{
return BuiltInClass.VECTOR;
}
@Override
public boolean hasFillPointer()
{
return fillPointer >= 0;
}
@Override
public int getFillPointer()
{
return fillPointer;
}
@Override
public void setFillPointer(int n)
{
fillPointer = n;
}
@Override
public void setFillPointer(LispObject obj)
{
if (obj == T)
fillPointer = capacity();
else {
int n = Fixnum.getValue(obj);
if (n > capacity()) {
StringBuffer sb = new StringBuffer("The new fill pointer (");
sb.append(n);
sb.append(") exceeds the capacity of the vector (");
sb.append(capacity());
sb.append(").");
error(new LispError(sb.toString()));
} else if (n < 0) {
StringBuffer sb = new StringBuffer("The new fill pointer (");
sb.append(n);
sb.append(") is negative.");
error(new LispError(sb.toString()));
} else
fillPointer = n;
}
}
@Override
public boolean isDisplaced()
{
return isDisplaced;
}
@Override
public LispObject arrayDisplacement()
{
LispObject value1, value2;
if (array != null) {
value1 = array;
value2 = Fixnum.getInstance(displacement);
} else {
value1 = NIL;
value2 = Fixnum.ZERO;
}
return LispThread.currentThread().setValues(value1, value2);
}
@Override
public LispObject getElementType()
{
return T;
}
@Override
public boolean isSimpleVector()
{
return false;
}
@Override
public int capacity()
{
return capacity;
}
@Override
public int length()
{
return fillPointer >= 0 ? fillPointer : capacity;
}
@Override
public LispObject elt(int index)
{
final int limit = length();
if (index < 0 || index >= limit)
badIndex(index, limit);
return AREF(index);
}
// Ignores fill pointer.
@Override
public LispObject AREF(int index)
{
if (elements != null) {
try {
return elements[index];
}
catch (ArrayIndexOutOfBoundsException e) {
badIndex(index, elements.length);
return NIL; // Not reached.
}
} else {
// Displaced array.
if (index < 0 || index >= capacity)
badIndex(index, capacity);
return array.AREF(index + displacement);
}
}
@Override
public void aset(int index, LispObject newValue)
{
if (elements != null) {
try {
elements[index] = newValue;
}
catch (ArrayIndexOutOfBoundsException e) {
badIndex(index, elements.length);
}
} else {
// Displaced array.
if (index < 0 || index >= capacity)
badIndex(index, capacity);
else
array.aset(index + displacement, newValue);
}
}
@Override
public LispObject subseq(int start, int end)
{
SimpleVector v = new SimpleVector(end - start);
int i = start, j = 0;
try {
while (i < end)
v.aset(j++, AREF(i++));
return v;
}
catch (ArrayIndexOutOfBoundsException e) {
return error(new TypeError("Array index out of bounds: " + i + "."));
}
}
@Override
public void fill(LispObject obj)
{
for (int i = capacity; i-- > 0;)
elements[i] = obj;
}
@Override
public void shrink(int n)
{
if (elements != null) {
if (n < elements.length) {
LispObject[] newArray = new LispObject[n];
System.arraycopy(elements, 0, newArray, 0, n);
elements = newArray;
capacity = n;
return;
}
if (n == elements.length)
return;
}
error(new LispError());
}
@Override
public LispObject reverse()
{
int length = length();
SimpleVector result = new SimpleVector(length);
int i, j;
for (i = 0, j = length - 1; i < length; i++, j--)
result.aset(i, AREF(j));
return result;
}
@Override
public LispObject nreverse()
{
if (elements != null) {
int i = 0;
int j = length() - 1;
while (i < j) {
LispObject temp = elements[i];
elements[i] = elements[j];
elements[j] = temp;
++i;
--j;
}
} else {
// Displaced array.
int length = length();
LispObject[] data = new LispObject[length];
int i, j;
for (i = 0, j = length - 1; i < length; i++, j--)
data[i] = AREF(j);
elements = data;
capacity = length;
array = null;
displacement = 0;
isDisplaced = false;
fillPointer = -1;
}
return this;
}
@Override
public void vectorPushExtend(LispObject element)
{
if (fillPointer < 0)
noFillPointer();
if (fillPointer >= capacity) {
// Need to extend vector.
ensureCapacity(capacity * 2 + 1);
}
aset(fillPointer++, element);
}
@Override
public LispObject VECTOR_PUSH_EXTEND(LispObject element)
{
vectorPushExtend(element);
return Fixnum.getInstance(fillPointer - 1);
}
@Override
public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension)
{
int ext = Fixnum.getValue(extension);
if (fillPointer < 0)
noFillPointer();
if (fillPointer >= capacity) {
// Need to extend vector.
ext = Math.max(ext, capacity + 1);
ensureCapacity(capacity + ext);
}
aset(fillPointer, element);
return Fixnum.getInstance(fillPointer++);
}
private final void ensureCapacity(int minCapacity)
{
if (elements != null) {
if (capacity < minCapacity) {
LispObject[] newArray = new LispObject[minCapacity];
System.arraycopy(elements, 0, newArray, 0, capacity);
elements = newArray;
capacity = minCapacity;
}
} else {
// Displaced array.
Debug.assertTrue(array != null);
if (capacity < minCapacity ||
array.getTotalSize() - displacement < minCapacity)
{
// Copy array.
elements = new LispObject[minCapacity];
final int limit =
Math.min(capacity, array.getTotalSize() - displacement);
for (int i = 0; i < limit; i++)
elements[i] = array.AREF(displacement + i);
capacity = minCapacity;
array = null;
displacement = 0;
isDisplaced = false;
}
}
}
@Override
public AbstractVector adjustArray(int newCapacity,
LispObject initialElement,
LispObject initialContents)
{
if (initialContents != null) {
// "If INITIAL-CONTENTS is supplied, it is treated as for MAKE-
// ARRAY. In this case none of the original contents of array
// appears in the resulting array."
LispObject[] newElements = new LispObject[newCapacity];
if (initialContents.listp()) {
LispObject list = initialContents;
for (int i = 0; i < newCapacity; i++) {
newElements[i] = list.car();
list = list.cdr();
}
} else if (initialContents.vectorp()) {
for (int i = 0; i < newCapacity; i++)
newElements[i] = initialContents.elt(i);
} else
type_error(initialContents, Symbol.SEQUENCE);
elements = newElements;
} else {
if (elements == null) {
// Displaced array. Copy existing elements.
elements = new LispObject[newCapacity];
final int limit = Math.min(capacity, newCapacity);
for (int i = 0; i < limit; i++)
elements[i] = array.AREF(displacement + i);
} else if (capacity != newCapacity) {
LispObject[] newElements = new LispObject[newCapacity];
System.arraycopy(elements, 0, newElements, 0,
Math.min(capacity, newCapacity));
elements = newElements;
}
// Initialize new elements (if any).
if (initialElement != null)
for (int i = capacity; i < newCapacity; i++)
elements[i] = initialElement;
}
capacity = newCapacity;
array = null;
displacement = 0;
isDisplaced = false;
return this;
}
@Override
public AbstractVector adjustArray(int newCapacity,
AbstractArray displacedTo,
int displacement)
{
capacity = newCapacity;
array = displacedTo;
this.displacement = displacement;
elements = null;
isDisplaced = true;
return this;
}
}