/* $Id: dither.c,v 1.1 89/12/07 16:17:43 nesheim Rel-5-2 $ */
/*****************************************************************************
* 	  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.					     *
*****************************************************************************/

/*
 * 8 to 1 dithering on the CM
 * Bill Nesheim
 * October, 1989
 */

#include <cm/paris.h>

/*
 * Return field should be a 2 bit field
 */
CM_field_id_t
dither_block (x_pos, y_pos, return_field)
CM_field_id_t x_pos, y_pos, return_field;
{
    CM_field_id_t x_odd, y_odd;
    CM_field_id_t sc, sc2;

    x_odd = CM_allocate_stack_field(1);
    y_odd = CM_allocate_stack_field(1);
    sc = CM_allocate_stack_field(1);
    sc2 = CM_allocate_stack_field(1);

    CM_store_context(sc);

    CM_u_move_1L(x_odd, x_pos, 1);
    CM_u_move_1L(y_odd, y_pos, 1);

    CM_u_eq_zero_1L(x_odd, 1);
    CM_logand_context_with_test();
    CM_store_context(sc2);
    /* x_odd == 0 */
    CM_u_eq_zero_1L(y_odd, 1);
    CM_logand_context_with_test();
    /* y_odd == 0 */
    CM_u_move_constant_1L(return_field, 0, 2);
    CM_load_context(sc2);
    CM_u_gt_zero_1L(y_odd, 1);
    CM_logand_context_with_test();
    CM_u_move_constant_1L(return_field, 2, 2);
    CM_load_context(sc2);
    CM_invert_context();
    CM_store_context(sc2);
    /* x_odd == 1 */
    CM_u_eq_zero_1L(y_odd, 1);
    CM_logand_context_with_test();
    /* y_odd == 0 */
    CM_u_move_constant_1L(return_field, 3, 2);
    CM_load_context(sc2);
    CM_u_gt_zero_1L(y_odd, 1);
    CM_logand_context_with_test();
    CM_u_move_constant_1L(return_field, 1, 2);

    CM_load_context(sc);
    CM_deallocate_stack_through(sc2);

    return (return_field);
}

/*
 * Assumes field is 8 bits, between 0 and 255
 */
dither(field, field_len)
CM_field_id_t field;
{
    CM_field_id_t result, threshold;
    CM_field_id_t x_temp, y_temp;
    CM_field_id_t saved_context;
    CM_field_id_t dither_block_result;
    int i;

    result = CM_allocate_stack_field(1);
    threshold = CM_allocate_stack_field(8);
    dither_block_result = CM_allocate_stack_field(32);
    saved_context = CM_allocate_stack_field(1);
    x_temp = CM_allocate_stack_field(8);
    y_temp = CM_allocate_stack_field(8);

    CM_store_context(saved_context);
    CM_set_context();
    CM_u_move_zero_1L(threshold, 8);
    CM_u_random_1L(threshold, 8, 16);

    CM_my_news_coordinate_1L(x_temp, 0, 32);
    MY_ash_constant_1L(x_temp, -1, 8);
    CM_my_news_coordinate_1L(y_temp, 1, 32);
    MY_ash_constant_1L(y_temp, -1, 8);
    CM_u_move_zero_1L(dither_block_result, 32);
    dither_block(x_temp, y_temp, dither_block_result);
    MY_ash_constant_1L(dither_block_result, 4, 32);
    CM_u_add_2_1L(threshold, dither_block_result, 8);

    CM_my_news_coordinate_1L(x_temp, 0, 32);
    CM_my_news_coordinate_1L(y_temp, 1, 32);
    CM_u_move_zero_1L(dither_block_result, 32);
    dither_block(x_temp, y_temp, dither_block_result);
    MY_ash_constant_1L(dither_block_result, 6, 32);
    CM_u_add_2_1L(threshold, dither_block_result, 8);

    /* If field <= threshold, result = 1 */
    CM_set_context();
    CM_u_le_1L(field, threshold, 8);
    CM_logand_context_with_test();
    CM_u_move_constant_1L(result, 1, 1);

    /* else result = 0 */
    CM_invert_context();
    CM_u_move_constant_1L(result, 0, 1);

    /* If field == 0, result = 1 */
    CM_set_context();
    CM_u_eq_constant_1L(field, 0, 8);
    CM_logand_context_with_test();
    CM_u_move_constant_1L(result, 1, 1);
    
    /* If field == 255, result = 0 */
    CM_set_context();
    CM_u_eq_constant_1L(field, 255, 8);
    CM_logand_context_with_test();
    CM_u_move_constant_1L(result, 0, 1); 

    CM_load_context(saved_context);
    CM_u_move_zero_1L(field, field_len);
    CM_u_move_2L(field, result, field_len, 1);
    CM_deallocate_stack_through(result);
}
    

MY_ash_constant_1L(field, shift, length)
CM_field_id_t field;
int shift, length;
{
    CM_field_id_t temp;
    int i;

    i = (shift > 0) ? shift : -shift;
    
    temp = CM_allocate_stack_field(length + i);

    if (shift > 0) {
	CM_u_move_zero_1L(temp, shift);
	CM_u_move_1L(CM_add_offset_to_field_id(temp, shift),
		     field, length);
    } else {
	CM_u_move_zero_1L(temp, length);
	CM_u_move_1L(temp,
		     CM_add_offset_to_field_id(field, -shift),
		     length + shift);
    }

    CM_u_move_1L(field, temp, length);
    CM_deallocate_stack_through(temp);
}
	
