/*****************************************************************************
* 	  Copyright (c) 1988 Thinking Machines Corporation, Inc.,	     *
*		of Cambridge, Mass.   All rights reserved.		     *
*									     *
*  This notice is intended as a precaution against inadvertent publication   *
*  and does not constitute an admission or acknowledgement that publication  *
*  has occurred or constitute a waiver of confidentiality.		     *
*									     *
*  Connection Machine software is the proprietary and confidential property  *
*  of Thinking Machines Corporation.					     *
*****************************************************************************/

/*
 * A sampling of data transposition rearrangement functions.
 * passed to CM transpose.
 * 
 * news_read_rearrangement() is used for reading serial data
 * stored in row-major order into a 2D CM geometry.
 *
 * news_write_rearrangement() is used for data
 * in a 2D CM geometry into a row-major serial file.
 *
 * The fb_read_rearrangement() and fb_write_rearrangement() functions
 * perform similar functions for data in a CM framebuffer ordered geometry.
 */


#include <cm/paris.h>

void
news_read_rearrangement(dest_send_address)
CM_field_id_t dest_send_address;
{
    CM_field_id_t x_address;
    CM_field_id_t y_address;
    CM_geometry_id_t geom;
    int columns;

    /* 
     * Allocate fields in CM memory to store the x and y coordinates 
     */
    x_address = CM_allocate_stack_field(CM_cube_address_length);
    y_address = CM_allocate_stack_field(CM_cube_address_length);

    /* 
     * Get the geometry from the send address 
     */
    geom = CM_vp_set_geometry(CM_field_vp_set(dest_send_address));
    columns = CM_geometry_axis_length(geom, 0);

    /* 
     * From the position in the serial file of a data item, which is 
     * given by the send address (dest_send_address) of the processor in
     * which the transpose would ordinarily place the data item,
     * compute the x,y coordinate of the data item.  Since we know
     * the serial file stores the data in row-major order, we know
     * that x=send_address/columns and  y=mod(send_address, columns) 
     */
    CM_u_move_1L(x_address, dest_send_address, CM_cube_address_length);
    CM_u_truncate_constant_2_1L(x_address, columns, CM_cube_address_length);
    CM_u_move_1L(y_address, dest_send_address, CM_cube_address_length);
    CM_u_mod_constant_2_1L(y_address, columns, CM_cube_address_length);

    /* 
     * Clear dest_send_address, in preparation for supplying 
     * CMFS_transpose_always with the newly computed dest_send_address 
     */
    CM_u_move_zero_1L(dest_send_address, CM_cube_address_length);

    /* 
     * Compute the send-address
     * of the processor in the 2-D VP set that corresponds to the 
     * x,y coordinate.  Place this send-address in dest_send_address. 
     * With this accomplished, CMFS_transpose_always will arrange 
     * the data in 2-D order in the CM. 
     */
    CM_deposit_news_coordinate_1L(geom,
				  dest_send_address, 0,
				  x_address, CM_cube_address_length);
    CM_deposit_news_coordinate_1L(geom,
				  dest_send_address, 1, 
				  y_address, CM_cube_address_length);


    CM_deallocate_stack_through(x_address);
}


void
news_write_rearrangement(dest_send_address)
CM_field_id_t dest_send_address;
{
    CM_field_id_t x_address;
    CM_field_id_t y_address;
    CM_geometry_id_t geom;
    int columns;

    /* 
     * Get the geometry from the send address 
     */
    geom = CM_vp_set_geometry(CM_field_vp_set(dest_send_address));
    columns = CM_geometry_axis_length(geom, 0);

    x_address = CM_allocate_stack_field(CM_cube_address_length);
    y_address = CM_allocate_stack_field(CM_cube_address_length);

    CM_u_move_zero_1L(x_address, CM_cube_address_length);
    CM_u_move_zero_1L(y_address, CM_cube_address_length);
    CM_extract_news_coordinate_1L(geom, x_address, 0, 
				  dest_send_address, CM_cube_address_length);
    CM_extract_news_coordinate_1L(geom, y_address, 1, 
				  dest_send_address, CM_cube_address_length);

    /* send_address = x*COLUMNS + y; */
    CM_u_move_1L(dest_send_address, x_address, CM_cube_address_length);
    CM_u_multiply_constant_2_1L(dest_send_address, columns, CM_cube_address_length);
    CM_u_add_2_1L(dest_send_address, y_address, CM_cube_address_length);
	
    CM_deallocate_stack_through(x_address);
}

void
fb_read_rearrangement(dest_send_address)
CM_field_id_t dest_send_address;
{
    CM_field_id_t x_address;
    CM_field_id_t y_address;
    CM_geometry_id_t geom;
    int columns;

    /* 
     * Allocate fields in CM memory to store the x and y coordinates 
     */
    x_address = CM_allocate_stack_field(CM_cube_address_length);
    y_address = CM_allocate_stack_field(CM_cube_address_length);

    /* 
     * Get the geometry from the send address 
     */
    geom = CM_vp_set_geometry(CM_field_vp_set(dest_send_address));
    columns = CM_geometry_axis_length(geom, 0);

    /* 
     * From the position in the serial file of a data item, which is 
     * given by the send address (dest_send_address) of the processor in
     * which the transpose would ordinarily place the data item,
     * compute the x,y coordinate of the data item.  Since we know
     * the serial file stores the data in row-major order, we know
     * that x=send_address/columns and  y=mod(send_address, columns) 
     */
    CM_u_move_1L(x_address, dest_send_address, CM_cube_address_length);
    CM_u_truncate_constant_2_1L(x_address, columns, CM_cube_address_length);
    CM_u_move_1L(y_address, dest_send_address, CM_cube_address_length);
    CM_u_mod_constant_2_1L(y_address, columns, CM_cube_address_length);

    /* 
     * Clear dest_send_address, in preparation for supplying 
     * CMFS_transpose_always with the newly computed dest_send_address 
     */
    CM_u_move_zero_1L(dest_send_address, CM_cube_address_length);

    /* 
     * Compute the send-address
     * of the processor in the 2-D VP set that corresponds to the 
     * x,y coordinate.  Place this send-address in dest_send_address. 
     * With this accomplished, CMFS_transpose_always will arrange 
     * the data in 2-D order in the CM. 
     */
    CMFB_shuffle_from_x_y(dest_send_address, y_address, x_address, geom);

    CM_deallocate_stack_through(x_address);
}





void
fb_write_rearrangement(dest_send_address)
CM_field_id_t dest_send_address;
{
    CM_field_id_t x_address;
    CM_field_id_t y_address;
    CM_geometry_id_t geom;
    int columns;

    /* 
     * Get the geometry from the send address 
     */
    geom = CM_vp_set_geometry(CM_field_vp_set(dest_send_address));
    columns = CM_geometry_axis_length(geom, 0);

    x_address = CM_allocate_stack_field(CM_cube_address_length);
    y_address = CM_allocate_stack_field(CM_cube_address_length);

    CM_u_move_zero_1L(x_address, CM_cube_address_length);
    CM_u_move_zero_1L(y_address, CM_cube_address_length);
    CMFB_x_from_shuffle(x_address, dest_send_address, geom);
    CMFB_y_from_shuffle(y_address, dest_send_address, geom);

    /* send_address = x*COLUMNS + y; */
    CM_u_move_1L(dest_send_address, x_address, CM_cube_address_length);
    CM_u_multiply_constant_2_1L(dest_send_address, columns, CM_cube_address_length);
    CM_u_add_2_1L(dest_send_address, y_address, CM_cube_address_length);
	
    CM_deallocate_stack_through(x_address);
}

