// -*- mode: Java; file-coding-system: *euc-japan*; -*-
// $Id: DoubleArrayEncodedData.java,v 1.2 1999/09/22 07:27:08 maeda Exp $
// Copyright (C) 1999 MAEDA Atusi

package jp.ac.tohoku.is.archi.mpi2.util;

import mpi.Datatype;
import mpi.MPI;

/**
 * doubleの配列を用いて送受信を行なう{@link EncodedData}の実装.
 *
 * この実装を用いるためには:
 * <ul>
 * <li> {@link Encodable#sizeInDouble}が正しい値を返すこと．
 * <li> {@link Encodable#encodeInDouble}が正しく実装されていること．
 * <li> {@link ObjectDecoder#sizeInDouble}が正しい値を返すこと．
 * <li> {@link ObjectDecoder#decodeFromDouble}が正しく実装されていること．
 * </ul>
 * が必要である．
 */
final class DoubleArrayEncodedData implements EncodedData {
  private double[] buffer = null;
  public Datatype type() {
    return MPI.DOUBLE;
  }
  public Object getArray() {
    if (buffer == null) {
      throw new RuntimeException("EncodedData not finished yet.");
    }
    return buffer;
  }
  public int length() {
    return buffer.length;
  }
  final class DoubleArrayEncoder implements Encoder {
    private int totalSize = 0;
    private int offset = 0;
    public void prepare(Encodable data) {
      totalSize += data.sizeInDouble();
    }
    public void finishPrepare() {
      buffer = new double[totalSize];
    }
    public void allocate(Encodable data, int nelem) {
      totalSize = data.sizeInDouble() * nelem;
      buffer = new double[totalSize];
    }
    public void encode(Encodable data) {
      data.encodeInDouble(buffer, offset);
      offset += data.sizeInDouble();
    }
    public void finishEncode() {
      // Do nothing.
    }
  }
  public Encoder getEncoder() {
    return new DoubleArrayEncoder();
  }
  final class DoubleArrayDecoder implements Decoder {
    private int totalSize = 0;
    private int offset = 0;
    public void prepare(ObjectDecoder od) {
      totalSize += od.sizeInDouble();
    }
    public void finishPrepare() {
      buffer = new double[totalSize];
    }
    public void allocate(ObjectDecoder od, int nelem) {
      buffer = new double[od.sizeInDouble() * nelem];
    }
    public void allocate(int size) {
      buffer = new double[size];
    }
    public Object decode(ObjectDecoder od) {
      Object value = od.decodeFromDouble(buffer, offset);
      offset += od.sizeInDouble();
      return value;
    }
  }
  public Decoder getDecoder() {
    return new DoubleArrayDecoder();
  }
}
