Example #1
0
gboolean parse_value (PREFS *images, char *key, char *prefsline, char *entry_place)
{
	/* Parse the given line. Check against keys,                */
	/* if it matches then copy value to the preferences object. */
	char current_key[KEY_WORDS_MAX_SIZE];			/* Left hand holder */
	char current_var[MAX_LINE_CHARACTERS];		/* Right hand holder */
	int key_length;														/* Length of current key */
	GtkWidget *entry_field;										/* Entry field to fill */
	
	/* Check to see if the keys match */
	key_length = strlen (key);								/* Get length of key */
	lefts (current_key, prefsline, key_length);
	if (strcmp (key, current_key))						/* Do they match? */
		return FALSE;														/* Keys don't match */
	
	/* The keys match, get the value of the key */
	rights (current_var, prefsline, strlen (prefsline) - key_length);
	lefts (current_var, current_var,  strlen (current_var) - 1);
	
	/* Check to see if the value is NULL */
	if (!strcmp ("", current_var))
		return TRUE;														/* The value was NULL */
	
	/* We have the value, put it in it's place */
	if (strcmp (KEY_DISPLAY_COMMAND, current_key))
	{
		/* This is for everything but the "Display Command" checkbox */
		entry_field = glade_xml_get_widget (images->xml, entry_place);
		gtk_entry_set_text (GTK_ENTRY (entry_field), current_var);
	}
	else
	{
		/* This is only for the "Display Command" checkbox */
		entry_field = glade_xml_get_widget (images->xml, entry_place);
		if (!strcmp (current_var, "TRUE"))
			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry_field), TRUE);
		else
			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry_field), FALSE);
	}
	
	return TRUE;
}
Example #2
0
static void _GraphicsScreen_cellArrayOrImage (GraphicsScreen me, double **z_float, double_rgbt **z_rgbt, unsigned char **z_byte,
	long ix1, long ix2, long x1DC, long x2DC,
	long iy1, long iy2, long y1DC, long y2DC,
	double minimum, double maximum,
	long clipx1, long clipx2, long clipy1, long clipy2, int interpolate)
{
	/*long t=clock();*/
	long nx = ix2 - ix1 + 1;   /* The number of cells along the horizontal axis. */
	long ny = iy2 - iy1 + 1;   /* The number of cells along the vertical axis. */
	double dx = (double) (x2DC - x1DC) / (double) nx;   /* Horizontal pixels per cell. Positive. */
	double dy = (double) (y2DC - y1DC) / (double) ny;   /* Vertical pixels per cell. Negative. */
	double scale = 255.0 / (maximum - minimum), offset = 255.0 + minimum * scale;
	if (x2DC <= x1DC || y1DC <= y2DC) return;
	trace ("scale %f", scale);
	/* Clip by the intersection of the world window and the outline of the cells. */
	//Melder_casual ("clipy1 %ld clipy2 %ld", clipy1, clipy2);
	if (clipx1 < x1DC) clipx1 = x1DC;
	if (clipx2 > x2DC) clipx2 = x2DC;
	if (clipy1 > y1DC) clipy1 = y1DC;
	if (clipy2 < y2DC) clipy2 = y2DC;
	/*
	 * The first decision is whether we are going to use the standard rectangle drawing
	 * (cellArray only), or whether we are going to write into a bitmap.
	 * The standard drawing is best for small numbers of cells,
	 * provided that some cells are larger than a pixel.
	 */
	if (! interpolate && nx * ny < 3000 && (dx > 1.0 || dy < -1.0)) {
		try {
			/*unsigned int cellWidth = (unsigned int) dx + 1;*/
			unsigned int cellHeight = (unsigned int) (- (int) dy) + 1;
			long ix, iy;
			#if cairo
				cairo_pattern_t *grey [256];
				for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++) {
					double v = igrey / ((double) (sizeof (grey) / sizeof (*grey)) - 1.0);
					grey [igrey] = cairo_pattern_create_rgb (v, v, v);
				}
			#elif win
				static HBRUSH greyBrush [256];
				RECT rect;
				if (! greyBrush [0])
					for (int igrey = 0; igrey <= 255; igrey ++)
						greyBrush [igrey] = CreateSolidBrush (RGB (igrey, igrey, igrey));   // once
			#elif mac
				GraphicsQuartz_initDraw (me);
				CGContextSetAlpha (my d_macGraphicsContext, 1.0);
				CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal);
			#endif
			autoNUMvector <long> lefts (ix1, ix2 + 1);
			for (ix = ix1; ix <= ix2 + 1; ix ++)
				lefts [ix] = x1DC + (long) ((ix - ix1) * dx);
			for (iy = iy1; iy <= iy2; iy ++) {
				long bottom = y1DC + (long) ((iy - iy1) * dy), top = bottom - cellHeight;
				if (top > clipy1 || bottom < clipy2) continue;
				if (top < clipy2) top = clipy2;
				if (bottom > clipy1) bottom = clipy1;
				#if win
					rect. bottom = bottom; rect. top = top;
				#endif
				for (ix = ix1; ix <= ix2; ix ++) {
					long left = lefts [ix], right = lefts [ix + 1];
					if (right < clipx1 || left > clipx2) continue;
					if (left < clipx1) left = clipx1;
					if (right > clipx2) right = clipx2;
					if (z_rgbt) {
						#if cairo
							// NYI
						#elif win
							// NYI
						#elif mac
							double red          = z_rgbt [iy] [ix]. red;
							double green        = z_rgbt [iy] [ix]. green;
							double blue         = z_rgbt [iy] [ix]. blue;
							double transparency = z_rgbt [iy] [ix]. transparency;
							red =   ( red   <= 0.0 ? 0.0 : red   >= 1.0 ? 1.0 : red   );
							green = ( green <= 0.0 ? 0.0 : green >= 1.0 ? 1.0 : green );
							blue =  ( blue  <= 0.0 ? 0.0 : blue  >= 1.0 ? 1.0 : blue  );
							CGContextSetRGBFillColor (my d_macGraphicsContext, red, green, blue, 1.0 - transparency);
							CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top));
						#endif
					} else {
						#if cairo
							long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] );
							cairo_set_source (my d_cairoGraphicsContext, grey [value <= 0 ? 0 : value >= sizeof (grey) / sizeof (*grey) ? sizeof (grey) / sizeof (*grey) : value]);
							cairo_rectangle (my d_cairoGraphicsContext, left, top, right - left, bottom - top);
							cairo_fill (my d_cairoGraphicsContext);
						#elif win
							long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] );
							rect. left = left; rect. right = right;
							FillRect (my d_gdiGraphicsContext, & rect, greyBrush [value <= 0 ? 0 : value >= 255 ? 255 : value]);
						#elif mac
							double value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] );
							double igrey = ( value <= 0 ? 0 : value >= 255 ? 255 : value ) / 255.0;
							CGContextSetRGBFillColor (my d_macGraphicsContext, igrey, igrey, igrey, 1.0);
							CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top));
						#endif
					}
				}
			}
			
			#if cairo
				for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++)
					cairo_pattern_destroy (grey [igrey]);
			#elif mac
				CGContextSetRGBFillColor (my d_macGraphicsContext, 0.0, 0.0, 0.0, 1.0);
				GraphicsQuartz_exitDraw (me);
			#endif
		} catch (MelderError) { }
	} else {
		long xDC, yDC;
		long undersampling = 1;
		/*
		 * Prepare for off-screen bitmap drawing.
		 */
		#if cairo
			long arrayWidth = clipx2 - clipx1;
			long arrayHeight = clipy1 - clipy2;
			trace ("arrayWidth %f, arrayHeight %f", (double) arrayWidth, (double) arrayHeight);
			cairo_surface_t *sfc = cairo_image_surface_create (CAIRO_FORMAT_RGB24, arrayWidth, arrayHeight);
			unsigned char *bits = cairo_image_surface_get_data (sfc);
			int scanLineLength = cairo_image_surface_get_stride (sfc);
			unsigned char grey [256];
			trace ("image surface address %p, bits address %p, scanLineLength %d, numberOfGreys %d", sfc, bits, scanLineLength, sizeof(grey)/sizeof(*grey));
			for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey++)
				grey [igrey] = 255 - (unsigned char) (igrey * 255.0 / (sizeof (grey) / sizeof (*grey) - 1));
		#elif win
			long bitmapWidth = clipx2 - clipx1, bitmapHeight = clipy1 - clipy2;
			int igrey;
			/*
			 * Create a device-independent bitmap, 32 bits deep.
			 */
			struct { BITMAPINFOHEADER header; } bitmapInfo;
			long scanLineLength = bitmapWidth * 4;   // for 24 bits: (bitmapWidth * 3 + 3) & ~3L;
			HBITMAP bitmap;
			unsigned char *bits;   // a pointer to memory allocated by VirtualAlloc or by CreateDIBSection ()
			bitmapInfo. header.biSize = sizeof (BITMAPINFOHEADER);
			bitmapInfo. header.biWidth = bitmapWidth;   // scanLineLength;
			bitmapInfo. header.biHeight = bitmapHeight;
			bitmapInfo. header.biPlanes = 1;
			bitmapInfo. header.biBitCount = 32;
			bitmapInfo. header.biCompression = 0;
			bitmapInfo. header.biSizeImage = 0;
			bitmapInfo. header.biXPelsPerMeter = 0;
			bitmapInfo. header.biYPelsPerMeter = 0;
			bitmapInfo. header.biClrUsed = 0;
			bitmapInfo. header.biClrImportant = 0;
			bitmap = CreateDIBSection (my d_gdiGraphicsContext /* ignored */, (CONST BITMAPINFO *) & bitmapInfo,
				DIB_RGB_COLORS, (VOID **) & bits, NULL, 0);
		#elif mac
			long bytesPerRow = (clipx2 - clipx1) * 4;
			Melder_assert (bytesPerRow > 0);
			long numberOfRows = clipy1 - clipy2;
			Melder_assert (numberOfRows > 0);
			unsigned char *imageData = Melder_malloc_f (unsigned char, bytesPerRow * numberOfRows);
		#endif
		/*
		 * Draw into the bitmap.
		 */
		#if cairo
			#define ROW_START_ADDRESS  (bits + (clipy1 - 1 - yDC) * scanLineLength)
			#define PUT_PIXEL \
				if (1) { \
					unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = 0; \
				}
		#elif win
			#define ROW_START_ADDRESS  (bits + (clipy1 - 1 - yDC) * scanLineLength)
			#define PUT_PIXEL \
				if (1) { \
					unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = 0; \
				}
		#elif mac
			#define ROW_START_ADDRESS  (imageData + (clipy1 - 1 - yDC) * bytesPerRow)
			#define PUT_PIXEL \
				if (my colourScale == kGraphics_colourScale_GREY) { \
					unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = 0; \
				} else if (my colourScale == kGraphics_colourScale_BLUE_TO_RED) { \
					if (value < 0.0) { \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 63; \
						*pixelAddress ++ = 0; \
					} else if (value < 64.0) { \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = (int) (value * 3 + 63.999); \
						*pixelAddress ++ = 0; \
					} else if (value < 128.0) { \
						*pixelAddress ++ = (int) (value * 4 - 256.0); \
						*pixelAddress ++ = (int) (value * 4 - 256.0); \
						*pixelAddress ++ = 255; \
						*pixelAddress ++ = 0; \
					} else if (value < 192.0) { \
						*pixelAddress ++ = 255; \
						*pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \
						*pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \
						*pixelAddress ++ = 0; \
					} else if (value < 256.0) { \
						*pixelAddress ++ = (int) ((256.0 - value) * 3 + 63.999); \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
					} else { \
						*pixelAddress ++ = 63; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
					} \
				}
		#else
			#define ROW_START_ADDRESS  NULL
			#define PUT_PIXEL
		#endif
		if (interpolate) {
			try {
				autoNUMvector <long> ileft (clipx1, clipx2);
				autoNUMvector <long> iright (clipx1, clipx2);
				autoNUMvector <double> rightWeight (clipx1, clipx2);
				autoNUMvector <double> leftWeight (clipx1, clipx2);
				for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
					double ix_real = ix1 - 0.5 + ((double) nx * (xDC - x1DC)) / (x2DC - x1DC);
					ileft [xDC] = floor (ix_real), iright [xDC] = ileft [xDC] + 1;
					rightWeight [xDC] = ix_real - ileft [xDC], leftWeight [xDC] = 1.0 - rightWeight [xDC];
					if (ileft [xDC] < ix1) ileft [xDC] = ix1;
					if (iright [xDC] > ix2) iright [xDC] = ix2;
				}
				for (yDC = clipy2; yDC < clipy1; yDC += undersampling) {
					double iy_real = iy2 + 0.5 - ((double) ny * (yDC - y2DC)) / (y1DC - y2DC);
					long itop = ceil (iy_real), ibottom = itop - 1;
					double bottomWeight = itop - iy_real, topWeight = 1.0 - bottomWeight;
					unsigned char *pixelAddress = ROW_START_ADDRESS;
					if (itop > iy2) itop = iy2;
					if (ibottom < iy1) ibottom = iy1;
					if (z_float) {
						double *ztop = z_float [itop], *zbottom = z_float [ibottom];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double interpol =
								rightWeight [xDC] *
									(topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) +
								leftWeight [xDC] *
									(topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]);
							double value = offset - scale * interpol;
							PUT_PIXEL
						}
					} else if (z_rgbt) {
						double_rgbt *ztop = z_rgbt [itop], *zbottom = z_rgbt [ibottom];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double red =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. red + bottomWeight * zbottom [iright [xDC]]. red) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. red + bottomWeight * zbottom [ileft  [xDC]]. red);
							double green =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. green + bottomWeight * zbottom [iright [xDC]]. green) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. green + bottomWeight * zbottom [ileft  [xDC]]. green);
							double blue =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. blue + bottomWeight * zbottom [iright [xDC]]. blue) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. blue + bottomWeight * zbottom [ileft  [xDC]]. blue);
							double transparency =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. transparency + bottomWeight * zbottom [iright [xDC]]. transparency) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. transparency + bottomWeight * zbottom [ileft  [xDC]]. transparency);
							if (red          < 0.0) red          = 0.0; else if (red          > 1.0) red          = 1.0;
							if (green        < 0.0) green        = 0.0; else if (green        > 1.0) green        = 1.0;
							if (blue         < 0.0) blue         = 0.0; else if (blue         > 1.0) blue         = 1.0;
							if (transparency < 0.0) transparency = 0.0; else if (transparency > 1.0) transparency = 1.0;
							#if win
								*pixelAddress ++ = blue         * 255.0;
								*pixelAddress ++ = green        * 255.0;
								*pixelAddress ++ = red          * 255.0;
								*pixelAddress ++ = 0;
							#elif mac
								*pixelAddress ++ = red          * 255.0;
								*pixelAddress ++ = green        * 255.0;
								*pixelAddress ++ = blue         * 255.0;
								*pixelAddress ++ = transparency * 255.0;
							#elif cairo
								*pixelAddress ++ = blue         * 255.0;
								*pixelAddress ++ = green        * 255.0;
								*pixelAddress ++ = red          * 255.0;
								*pixelAddress ++ = transparency * 255.0;
							#endif
						}
					} else {
						unsigned char *ztop = z_byte [itop], *zbottom = z_byte [ibottom];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double interpol =
								rightWeight [xDC] *
									(topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) +
								leftWeight [xDC] *
									(topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]);
							double value = offset - scale * interpol;
							PUT_PIXEL
						}
					}
				}
			} catch (MelderError) { Melder_clearError (); }
		} else {
			try {
				autoNUMvector <long> ix (clipx1, clipx2);
				for (xDC = clipx1; xDC < clipx2; xDC += undersampling)
					ix [xDC] = floor (ix1 + (nx * (xDC - x1DC)) / (x2DC - x1DC));
				for (yDC = clipy2; yDC < clipy1; yDC += undersampling) {
					long iy = ceil (iy2 - (ny * (yDC - y2DC)) / (y1DC - y2DC));
					unsigned char *pixelAddress = ROW_START_ADDRESS;
					Melder_assert (iy >= iy1 && iy <= iy2);
					if (z_float) {
						double *ziy = z_float [iy];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double value = offset - scale * ziy [ix [xDC]];
							PUT_PIXEL
						}
					} else {
						unsigned char *ziy = z_byte [iy];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double value = offset - scale * ziy [ix [xDC]];
							PUT_PIXEL
						}
					}
				}
			} catch (MelderError) { Melder_clearError (); }
		}
		/*
		 * Copy the bitmap to the screen.
		 */
		#if cairo
			cairo_matrix_t clip_trans;
			cairo_matrix_init_identity (& clip_trans);
			cairo_matrix_scale (& clip_trans, 1, -1);		// we painted in the reverse y-direction
			cairo_matrix_translate (& clip_trans, - clipx1, - clipy1);
			cairo_pattern_t *bitmap_pattern = cairo_pattern_create_for_surface (sfc);
			trace ("bitmap pattern %p", bitmap_pattern);
			if (cairo_status_t status = cairo_pattern_status (bitmap_pattern)) {
				Melder_casual ("bitmap pattern status: %s", cairo_status_to_string (status));
			} else {
				cairo_pattern_set_matrix (bitmap_pattern, & clip_trans);
				cairo_save (my d_cairoGraphicsContext);
				cairo_set_source (my d_cairoGraphicsContext, bitmap_pattern);
				cairo_paint (my d_cairoGraphicsContext);
				cairo_restore (my d_cairoGraphicsContext);
			}
			cairo_pattern_destroy (bitmap_pattern);
		#elif win
			SetDIBitsToDevice (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight,
				bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS);
			//StretchDIBits (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight,
			//	bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
		#elif mac
			CGImageRef image;
			static CGColorSpaceRef colourSpace = NULL;
			if (colourSpace == NULL) {
				colourSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);   // used to be kCGColorSpaceUserRGB
				Melder_assert (colourSpace != NULL);
			}
			if (1) {
				CGDataProviderRef dataProvider = CGDataProviderCreateWithData (NULL,
					imageData,
					bytesPerRow * numberOfRows,
					_mac_releaseDataCallback   // we need this because we cannot release the image data immediately after drawing,
						// because in PDF files the imageData has to stay available through EndPage
				);
				Melder_assert (dataProvider != NULL);
				image = CGImageCreate (clipx2 - clipx1, numberOfRows,
					8, 32, bytesPerRow, colourSpace, kCGImageAlphaNone, dataProvider, NULL, false, kCGRenderingIntentDefault);
				CGDataProviderRelease (dataProvider);
			} else if (0) {
				Melder_assert (CGBitmapContextCreate != NULL);
				CGContextRef bitmaptest = CGBitmapContextCreate (imageData, 100, 100,
					8, 800, colourSpace, 0);
				Melder_assert (bitmaptest != NULL);
				CGContextRef bitmap = CGBitmapContextCreate (NULL/*imageData*/, clipx2 - clipx1, numberOfRows,
					8, bytesPerRow, colourSpace, kCGImageAlphaLast);
				Melder_assert (bitmap != NULL);
				image = CGBitmapContextCreateImage (bitmap);
				// release bitmap?
			}
			Melder_assert (image != NULL);
			GraphicsQuartz_initDraw (me);
			CGContextDrawImage (my d_macGraphicsContext, CGRectMake (clipx1, clipy2, clipx2 - clipx1, clipy1 - clipy2), image);
			GraphicsQuartz_exitDraw (me);
			//CGColorSpaceRelease (colourSpace);
			CGImageRelease (image);
		#endif
		/*
		 * Clean up.
		 */
		#if cairo
			cairo_surface_destroy (sfc);
		#elif win
			DeleteBitmap (bitmap);
		#endif
	}
  void operator()(const Scores& scores,
		  Dependency& dependency)
  {
    const size_t sentence_size = dependency.size();
    const int    last_max = sentence_size + 1;
    
    actives.clear();
    actives.resize(sentence_size + 2, hypothesis_set_type(sentence_size + 2, sentence_size + 2, sentence_size + 2, hypothesis_type()));
    
    // initialize by axioms...
    for (int pos = 0; pos != last_max; ++ pos) {
      // we need to shift + 1 for correct indexing...
      // [h3, j, h3 j, j + 1] where j == pos + 1 and h3 should starts from -1
      
      for (int h3 = -1; h3 != pos; ++ h3)
	actives(pos, pos + 1)(h3 + 1, h3 + 1, pos + 1).score = 0.0;
    }
    
    for (int last = 2; last <= last_max; ++ last)
      for (int length = 2; last - length >= 0; ++ length)  {
	const int first = last - length;
	
	//
	// is it correct???
	// [h1, first, h2 h3, middle] [h3, middle, h4 h5, last]
	//
	// first  <= h3 < middle
	// middle <= h5 < last
	// h3 <= h4 < h5
	// -1 <= h1 < h3 (or first??? given h3 < middle...?)
	// h1 <= h2 < h3
	
	hypothesis_set_type& cells = actives(first, last);
	
	for (int middle = first + 1; middle < last; ++ middle) {
	  const hypothesis_set_type& lefts  = actives(first, middle);
	  const hypothesis_set_type& rights = actives(middle, last);
	  
	  for (int h3 = first; h3 < middle; ++ h3)
	    for (int h5 = middle; h5 < last; ++ h5)
	      for (int h4 = h3; h4 < h5; ++ h4)
		for (int h1 = -1; h1 < first; ++ h1)
		  for (int h2 = h1; h2 < h3; ++ h2) {
		    const hypothesis_type& left  = lefts(h1 + 1, h2 + 1, h3 + 1);
		    const hypothesis_type& right = rights(h3 + 1, h4 + 1, h5 + 1);
		    
		    // [h1, i, h2 h5, j] (la1; h5 -> h4)
		    // left attachment
		    if (h4 > 0)
		      enumerate(cells(h1 + 1, h2 + 1, h5 + 1),  left,  right, h5, h4, scores(h5, h4));
		    
		    // [h1, i, h2 h4, j] (ra1; h4 -> h5)
		    // right attachment
		    if (h4 >= 0)
		      enumerate(cells(h1 + 1, h2 + 1, h4 + 1), left, right, h4, h5, scores(h4, h5));
		    
		    // [h1, i, h4 h5, j] (la2; h5 -> h2)
		    // left attachment
		    if (h2 > 0)
		      enumerate(cells(h1 + 1, h4 + 1, h5 + 1), left, right, h5, h2, scores(h5, h2));
		    
		    // [h1, i, h2 h4, j] (ra2; h2 -> h5)
		    // right attachment
		    if (h2 >= 0)
		      enumerate(cells(h1 + 1, h2 + 1, h4 + 1), left, right, h2, h5, scores(h2, h5));
		  }
	}
      }
    
    const dep_set_type& deps = actives(0, last_max)(-1 + 1, -1 + 1, 0 + 1).deps;
    
    dep_set_type::const_iterator diter_end = deps.end();
    for (dep_set_type::const_iterator diter = deps.begin(); diter != diter_end; ++ diter)
      dependency[diter->second - 1] = diter->first;
  }