001: // Copyright (c) 2002, 2003 Per M.A. Bothner and Brainfood Inc.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.kawa.functions;
005:
006: import gnu.lists.*;
007: import gnu.mapping.*;
008: import gnu.math.IntNum;
009:
010: /** Static methods for implementing Scheme (SRFI-25) arrays. */
011:
012: public class Arrays {
013: static final int[] shapeStrides = { 2, 1 };
014: static final int[] zeros2 = new int[2];
015:
016: public static Array shape(Object[] vals) {
017: int len = vals.length;
018: if ((len & 1) != 0)
019: throw new RuntimeException(
020: "shape: not an even number of arguments");
021: int d = len >> 1;
022: int[] dims = { d, 2 };
023: return new FVector(vals).transpose(zeros2, dims, 0,
024: shapeStrides);
025: }
026:
027: public static Array make(Array shape, Object value) {
028: int rank = shape.getSize(0);
029: int[] dimensions = new int[rank];
030: int[] lowBounds = null;
031: int total = 1;
032: for (int i = rank; --i >= 0;) {
033: int lo = ((Number) shape.getRowMajor(2 * i)).intValue();
034: int hi = ((Number) shape.getRowMajor(2 * i + 1)).intValue();
035: int size = hi - lo;
036: dimensions[i] = size;
037: if (lo != 0) {
038: if (lowBounds == null)
039: lowBounds = new int[rank];
040: lowBounds[i] = lo;
041: }
042: total *= size;
043: }
044: return GeneralArray.makeSimple(lowBounds, dimensions,
045: new FVector(total, value));
046: }
047:
048: public static Array makeSimple(Array shape, SimpleVector base) {
049: int rank = shape.getSize(0);
050: int[] dimensions = new int[rank];
051: int[] lowBounds = null;
052: for (int i = rank; --i >= 0;) {
053: int lo = ((Number) shape.getRowMajor(2 * i)).intValue();
054: int hi = ((Number) shape.getRowMajor(2 * i + 1)).intValue();
055: dimensions[i] = hi - lo;
056: if (lo != 0) {
057: if (lowBounds == null)
058: lowBounds = new int[rank];
059: lowBounds[i] = lo;
060: }
061: }
062: return GeneralArray.makeSimple(lowBounds, dimensions, base);
063: }
064:
065: public static int effectiveIndex(Array array, Procedure proc,
066: Object[] args, int[] work) throws Throwable {
067: Object mapval = proc.applyN(args);
068: if (mapval instanceof Values) {
069: Values mapvals = (Values) mapval;
070: for (int i = 0, j = 0; (i = mapvals.nextPos(i)) != 0; j++) {
071: work[j] = ((Number) mapvals.getPosPrevious(i))
072: .intValue();
073: }
074: } else
075: work[0] = ((Number) mapval).intValue();
076: return array.getEffectiveIndex(work);
077: }
078:
079: public static Array shareArray(Array array, Array shape,
080: Procedure proc) throws Throwable {
081: int rank = shape.getSize(0);
082: Object[] args = new Object[rank];
083: int[] dimensions = new int[rank];
084: int[] lowBounds = new int[rank]; // null - FIXME
085: boolean empty = false;
086: for (int i = rank; --i >= 0;) {
087: Object low = shape.getRowMajor(2 * i);
088: args[i] = low;
089: int lo = ((Number) low).intValue();
090: lowBounds[i] = lo;
091: int hi = ((Number) shape.getRowMajor(2 * i + 1)).intValue();
092: int size = hi - lo;
093: dimensions[i] = size;
094: if (size <= 0)
095: empty = true;
096: }
097: int arank = array.rank();
098: int[] offsets = new int[rank];
099: int offset0;
100: if (empty)
101: offset0 = 0;
102: else {
103: int[] work = new int[arank];
104: offset0 = effectiveIndex(array, proc, args, work);
105: for (int i = rank; --i >= 0;) {
106: int size = dimensions[i];
107: int lo = lowBounds[i];
108: if (size <= 1)
109: offsets[i] = 0;
110: else {
111: Object low = args[i];
112: args[i] = IntNum.make(lo + 1);
113: offsets[i] = (effectiveIndex(array, proc, args,
114: work) - offset0);
115: args[i] = low;
116: }
117: }
118: }
119: return array.transpose(lowBounds, dimensions, offset0, offsets);
120: }
121: }
|