/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"@(#)mlib_ImageColorTrue2Index.c	9.4	07/11/05 SMI"

/*
 * FUNCTION
 *      mlib_ImageColorTrue2Index - convert a true color image to an indexed
 *                                  color image
 *
 * SYNOPSIS
 *      mlib_status mlib_ImageColorTrue2Index(mlib_image       *dst,
 *                                            const mlib_image *src,
 *                                            const void       *colormap)
 *
 * ARGUMENTS
 *      colormap  Internal data structure for inverse color mapping.
 *      dst       Pointer to destination image.
 *      src       Pointer to source image.
 *
 * DESCRIPTION
 *      Convert a true color image to a pseudo color image with the method
 *      of finding the nearest matched lut entry for each pixel.
 *
 *      The src can be an MLIB_BYTE or MLIB_SHORT image with 3 or 4 channels.
 *      The dst must be a 1-channel MLIB_BYTE or MLIB_SHORT image.
 *
 *      The lut might have either 3 or 4 channels. The type of the lut can be
 *      one of the following:
 *              MLIB_BYTE in, MLIB_BYTE out (i.e., BYTE-to-BYTE)
 *              MLIB_BYTE in, MLIB_SHORT out (i.e., BYTE-to-SHORT)
 *              MLIB_SHORT in, MLIB_SHORT out (i.e., SHORT-to-SHORT)
 *              MLIB_SHORT in, MLIB_BYTE out (i.e., SHORT-to-BYTE)
 *
 *      The src image and the lut must have same number of channels.
 */

#include <mlib_image.h>
#include <mlib_ImageColormap.h>
#include <mlib_ImageCheck.h>

/* *********************************************************** */

#if ! defined(__MEDIALIB_OLD_NAMES)
#if defined(__SUNPRO_C)

#pragma weak mlib_ImageColorTrue2Index = __mlib_ImageColorTrue2Index

#elif defined(__GNUC__)	/* defined(__SUNPRO_C) */
__typeof__(__mlib_ImageColorTrue2Index) mlib_ImageColorTrue2Index
    __attribute__((weak, alias("__mlib_ImageColorTrue2Index")));

#else /* defined(__SUNPRO_C) */

#error  "unknown platform"

#endif /* defined(__SUNPRO_C) */
#endif /* ! defined(__MEDIALIB_OLD_NAMES) */

/* *********************************************************** */

#ifdef MLIB_VIS
#include <vis_proto.h>

#define	VIS_ALIGNADDR(X, Y)	vis_alignaddr((void *)(X), (Y))
#endif /* MLIB_VIS */

/* *********************************************************** */

#define	LUT_BYTE_COLORS_3CHANNELS	1000
#define	LUT_BYTE_COLORS_4CHANNELS	3000

#define	LUT_SHORT_COLORS_3CHANNELS	1000

#define	LUT_SHORT_COLORS_4CHANNELS	1000

/* *********************************************************** */

#define	MAIN_COLORTRUE2INDEX_LOOP(FROM_TYPE, TO_TYPE, NCHANNELS)               \
	for (y = 0; y < height; y++) {                                         \
	    mlib_ImageColorTrue2IndexLine_##FROM_TYPE##_##TO_TYPE##_##NCHANNELS\
		(sdata, ddata, width, colormap);                               \
	    sdata += sstride;                                                  \
	    ddata += dstride;                                                  \
	}

/* *********************************************************** */

#define	COLOR_CUBE_U8_3_SEARCH(TABLE_POINTER_TYPE, SHIFT, STEP)            \
	{                                                                  \
	    const mlib_u8 *c0, *c1, *c2;                                   \
	    TABLE_POINTER_TYPE *table = s->table;                          \
	    mlib_s32 bits = s->bits;                                       \
	    mlib_s32 nbits = 8 - bits;                                     \
	    mlib_s32 mask = ~((1 << nbits) - 1);                           \
	    mlib_s32 j;                                                    \
	                                                                   \
	    c0 = src + SHIFT;                                              \
	    c1 = src + 1 + SHIFT;                                          \
	    c2 = src + 2 + SHIFT;                                          \
	    switch (bits) {                                                \
	    case 1:                                                        \
	    case 2: {                                                      \
		    mlib_s32 bits0 = 8 - bits;                             \
		    mlib_s32 bits1 = bits0 - bits;                         \
		    mlib_s32 bits2 = bits1 - bits;                         \
	                                                                   \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) >> bits2) | ((*c1 &        \
			    mask) >> bits1) | ((*c2 & mask) >> bits0)];    \
			c0 += STEP;                                        \
			c1 += STEP;                                        \
			c2 += STEP;                                        \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 3: {                                                      \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) << 1) | ((*c1 & mask) >>   \
			    2) | ((*c2 & mask) >> 5)];                     \
			c0 += STEP;                                        \
			c1 += STEP;                                        \
			c2 += STEP;                                        \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 4: {                                                      \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) << 4) | (*c1 & mask) |     \
			    ((*c2 & mask) >> 4)];                          \
			c0 += STEP;                                        \
			c1 += STEP;                                        \
			c2 += STEP;                                        \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 5:                                                        \
	    case 6:                                                        \
	    case 7: {                                                      \
		    mlib_s32 bits0 = 8 - bits;                             \
		    mlib_s32 bits1 = bits * 2 - 8;                         \
		    mlib_s32 bits2 = bits1 + bits;                         \
	                                                                   \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) << bits2) | ((*c1 &        \
			    mask) << bits1) | ((*c2 & mask) >> bits0)];    \
			c0 += STEP;                                        \
			c1 += STEP;                                        \
			c2 += STEP;                                        \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 8: {                                                      \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) << 16) | ((*c1 & mask)     \
			    << 8) | (*c2 & mask)];                         \
			c0 += STEP;                                        \
			c1 += STEP;                                        \
			c2 += STEP;                                        \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    }                                                              \
	}

/* *********************************************************** */

#define	COLOR_CUBE_U8_4_SEARCH(TABLE_TYPE)                                 \
	{                                                                  \
	    const mlib_u8 *c0, *c1, *c2, *c3;                              \
	    TABLE_TYPE *table = s->table;                                  \
	    mlib_s32 bits = s->bits;                                       \
	    mlib_s32 nbits = 8 - bits;                                     \
	    mlib_s32 mask = ~((1 << nbits) - 1);                           \
	    mlib_s32 j;                                                    \
	                                                                   \
	    c0 = src;                                                      \
	    c1 = src + 1;                                                  \
	    c2 = src + 2;                                                  \
	    c3 = src + 3;                                                  \
	    switch (bits) {                                                \
	    case 1: {                                                      \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) >> 4) | ((*c1 & mask) >>   \
			    5) | ((*c2 & mask) >> 6) | ((*c3 & mask) >>    \
			    7)];                                           \
			c0 += 4;                                           \
			c1 += 4;                                           \
			c2 += 4;                                           \
			c3 += 4;                                           \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 2: {                                                      \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[(*c0 & mask) | ((*c1 & mask) >> 2) |     \
			    ((*c2 & mask) >> 4) | ((*c3 & mask) >> 6)];    \
			c0 += 4;                                           \
			c1 += 4;                                           \
			c2 += 4;                                           \
			c3 += 4;                                           \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 3: {                                                      \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) << 4) | ((*c1 & mask) <<   \
			    1) | ((*c2 & mask) >> 2) | ((*c3 & mask) >>    \
			    5)];                                           \
			c0 += 4;                                           \
			c1 += 4;                                           \
			c2 += 4;                                           \
			c3 += 4;                                           \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 4: {                                                      \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) << 8) | ((*c1 & mask) <<   \
			    4) | (*c2 & mask) | ((*c3 & mask) >> 4)];      \
			c0 += 4;                                           \
			c1 += 4;                                           \
			c2 += 4;                                           \
			c3 += 4;                                           \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 5:                                                        \
	    case 6: {                                                      \
		    mlib_s32 bits3 = bits * 4 - 8;                         \
		    mlib_s32 bits2 = bits3 - bits;                         \
		    mlib_s32 bits1 = bits2 - bits;                         \
		    mlib_s32 bits0 = 8 - bits;                             \
	                                                                   \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) << bits3) | ((*c1 &        \
			    mask) << bits2) | ((*c2 & mask) << bits1) |    \
			    ((*c3 & mask) >> bits0)];                      \
			c0 += 4;                                           \
			c1 += 4;                                           \
			c2 += 4;                                           \
			c3 += 4;                                           \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 7: {                                                      \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) << 20) | ((*c1 & mask)     \
			    << 13) | ((*c2 & mask) << 6) | ((*c3 & mask)   \
			    >> 1)];                                        \
			c0 += 4;                                           \
			c1 += 4;                                           \
			c2 += 4;                                           \
			c3 += 4;                                           \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    case 8:                                                        \
/*                                                                         \
 * will never be called                                                    \
 */                                                                        \
		{                                                          \
		    for (j = 0; j < length; j++) {                         \
			dst[j] =                                           \
			    table[((*c0 & mask) << 24) | ((*c1 & mask)     \
			    << 16) | ((*c2 & mask) << 8) | (*c3 &          \
			    mask)];                                        \
			c0 += 4;                                           \
			c1 += 4;                                           \
			c2 += 4;                                           \
			c3 += 4;                                           \
		    }                                                      \
		    break;                                                 \
		}                                                          \
	    }                                                              \
	}

/* *********************************************************** */

#define	COLOR_CUBE_S16_3_SEARCH(TABLE_TYPE, SHIFT, STEP)                      \
	{                                                                     \
	    const mlib_s16 *c0, *c1, *c2;                                     \
	    mlib_s32 bits = s->bits;                                          \
	    mlib_s32 nbits = 16 - bits;                                       \
	    mlib_s32 mask = ~((1 << nbits) - 1);                              \
	    TABLE_TYPE *table = s->table;                                     \
	    mlib_s32 j;                                                       \
	                                                                      \
	    c0 = src + SHIFT;                                                 \
	    c1 = src + 1 + SHIFT;                                             \
	    c2 = src + 2 + SHIFT;                                             \
	    switch (bits) {                                                   \
	    case 1:                                                           \
	    case 2:                                                           \
	    case 3:                                                           \
	    case 4:                                                           \
	    case 5: {                                                         \
		    mlib_s32 bits0 = 16 - bits;                               \
		    mlib_s32 bits1 = bits0 - bits;                            \
		    mlib_s32 bits2 = bits1 - bits;                            \
	                                                                      \
		    for (j = 0; j < length; j++) {                            \
			dst[j] =                                              \
			    table[(((*c0 -                                    \
			    MLIB_S16_MIN) & mask) >> bits2) | (((*c1 -        \
			    MLIB_S16_MIN) & mask) >> bits1) | (((*c2 -        \
			    MLIB_S16_MIN) & mask) >> bits0)];                 \
			c0 += STEP;                                           \
			c1 += STEP;                                           \
			c2 += STEP;                                           \
		    }                                                         \
		    break;                                                    \
		}                                                             \
	    case 6:                                                           \
	    case 7: {                                                         \
		    mlib_s32 bits0 = 16 - bits;                               \
		    mlib_s32 bits1 = bits0 - bits;                            \
		    mlib_s32 bits2 = bits * 3 - 16;                           \
	                                                                      \
		    for (j = 0; j < length; j++) {                            \
			dst[j] =                                              \
			    table[(((*c0 -                                    \
			    MLIB_S16_MIN) & mask) << bits2) | (((*c1 -        \
			    MLIB_S16_MIN) & mask) >> bits1) | (((*c2 -        \
			    MLIB_S16_MIN) & mask) >> bits0)];                 \
			c0 += STEP;                                           \
			c1 += STEP;                                           \
			c2 += STEP;                                           \
		    }                                                         \
		    break;                                                    \
		}                                                             \
	    case 8: {                                                         \
		    for (j = 0; j < length; j++) {                            \
			dst[j] =                                              \
			    table[(((*c0 -                                    \
			    MLIB_S16_MIN) & mask) << 8) | ((*c1 -             \
			    MLIB_S16_MIN) & mask) | (((*c2 -                  \
			    MLIB_S16_MIN) & mask) >> 8)];                     \
			c0 += STEP;                                           \
			c1 += STEP;                                           \
			c2 += STEP;                                           \
		    }                                                         \
		    break;                                                    \
		}                                                             \
	    case 9:                                                           \
	    case 10: {                                                        \
		    mlib_s32 bits0 = 16 - bits;                               \
		    mlib_s32 bits1 = 2 * bits - 16;                           \
		    mlib_s32 bits2 = bits1 + bits;                            \
	                                                                      \
		    for (j = 0; j < length; j++) {                            \
			dst[j] =                                              \
			    table[(((*c0 -                                    \
			    MLIB_S16_MIN) & mask) << bits2) | (((*c1 -        \
			    MLIB_S16_MIN) & mask) << bits1) | (((*c2 -        \
			    MLIB_S16_MIN) & mask) >> bits0)];                 \
			c0 += STEP;                                           \
			c1 += STEP;                                           \
			c2 += STEP;                                           \
		    }                                                         \
		    break;                                                    \
		}                                                             \
	                                                                      \
/*                                                                            \
 * Other cases may not be considered as the table size will be more than 2^32 \
 */                                                                           \
	    }                                                                 \
	}

/* *********************************************************** */

#define	COLOR_CUBE_S16_4_SEARCH(TABLE_TYPE)                                   \
	{                                                                     \
	    const mlib_s16 *c0, *c1, *c2, *c3;                                \
	    TABLE_TYPE *table = s->table;                                     \
	    mlib_s32 bits = s->bits;                                          \
	    mlib_s32 nbits = 16 - bits;                                       \
	    mlib_s32 mask = ~((1 << nbits) - 1);                              \
	    mlib_s32 j;                                                       \
	                                                                      \
	    c0 = src;                                                         \
	    c1 = src + 1;                                                     \
	    c2 = src + 2;                                                     \
	    c3 = src + 3;                                                     \
	    switch (bits) {                                                   \
	    case 1:                                                           \
	    case 2:                                                           \
	    case 3: {                                                         \
		    mlib_s32 bits0 = 16 - bits;                               \
		    mlib_s32 bits1 = bits0 - bits;                            \
		    mlib_s32 bits2 = bits1 - bits;                            \
		    mlib_s32 bits3 = bits2 - bits;                            \
	                                                                      \
		    for (j = 0; j < length; j++) {                            \
			dst[j] =                                              \
			    table[(((*c0 -                                    \
			    MLIB_S16_MIN) & mask) >> bits3) | (((*c1 -        \
			    MLIB_S16_MIN) & mask) >> bits2) | (((*c2 -        \
			    MLIB_S16_MIN) & mask) >> bits1) | (((*c3 -        \
			    MLIB_S16_MIN) & mask) >> bits0)];                 \
			c0 += 4;                                              \
			c1 += 4;                                              \
			c2 += 4;                                              \
			c3 += 4;                                              \
		    }                                                         \
		    break;                                                    \
		}                                                             \
	    case 4: {                                                         \
		    for (j = 0; j < length; j++) {                            \
			dst[j] =                                              \
			    table[((*c0 -                                     \
			    MLIB_S16_MIN) & mask) | (((*c1 -                  \
			    MLIB_S16_MIN) & mask) >> 4) | (((*c2 -            \
			    MLIB_S16_MIN) & mask) >> 8) | (((*c3 -            \
			    MLIB_S16_MIN) & mask) >> 12)];                    \
			c0 += 4;                                              \
			c1 += 4;                                              \
			c2 += 4;                                              \
			c3 += 4;                                              \
		    }                                                         \
		    break;                                                    \
		}                                                             \
	    case 5: {                                                         \
		    for (j = 0; j < length; j++) {                            \
			dst[j] =                                              \
			    table[(((*c0 -                                    \
			    MLIB_S16_MIN) & mask) << 4) | (((*c1 -            \
			    MLIB_S16_MIN) & mask) >> 1) | (((*c2 -            \
			    MLIB_S16_MIN) & mask) >> 6) | (((*c3 -            \
			    MLIB_S16_MIN) & mask) >> 11)];                    \
			c0 += 4;                                              \
			c1 += 4;                                              \
			c2 += 4;                                              \
			c3 += 4;                                              \
		    }                                                         \
		    break;                                                    \
		}                                                             \
	    case 6:                                                           \
	    case 7: {                                                         \
		    mlib_s32 bits0 = 16 - bits;                               \
		    mlib_s32 bits1 = bits0 - bits;                            \
		    mlib_s32 bits3 = bits * 4 - 16;                           \
		    mlib_s32 bits2 = bits3 - bits;                            \
	                                                                      \
		    for (j = 0; j < length; j++) {                            \
			dst[j] =                                              \
			    table[(((*c0 -                                    \
			    MLIB_S16_MIN) & mask) << bits3) | (((*c1 -        \
			    MLIB_S16_MIN) & mask) << bits2) | (((*c2 -        \
			    MLIB_S16_MIN) & mask) >> bits1) | (((*c3 -        \
			    MLIB_S16_MIN) & mask) >> bits0)];                 \
			c0 += 4;                                              \
			c1 += 4;                                              \
			c2 += 4;                                              \
			c3 += 4;                                              \
		    }                                                         \
		    break;                                                    \
		}                                                             \
	    case 8: {                                                         \
		    for (j = 0; j < length; j++) {                            \
			dst[j] =                                              \
			    table[(((*c0 -                                    \
			    MLIB_S16_MIN) & mask) << 16) | (((*c1 -           \
			    MLIB_S16_MIN) & mask) << 8) | ((*c2 -             \
			    MLIB_S16_MIN) & mask) | (((*c3 -                  \
			    MLIB_S16_MIN) & mask) >> 8)];                     \
			c0 += 4;                                              \
			c1 += 4;                                              \
			c2 += 4;                                              \
			c3 += 4;                                              \
		    }                                                         \
		    break;                                                    \
		}                                                             \
	                                                                      \
/*                                                                            \
 * Other cases may not be considered as the table size will be more than 2^32 \
 */                                                                           \
	    }                                                                 \
	}

/* *********************************************************** */

#define	FUNC_NAME(F)	mlib_search_quadrant_##F

#define	BINARY_TREE_SEARCH_RIGHT(POSITION, COLOR_MAX, SHIFT)          \
	{                                                             \
	    if ((distance >=                                          \
		(((position[POSITION] + current_size -                \
		c[POSITION]) * (position[POSITION] + current_size -   \
		c[POSITION])) >> SHIFT)) &&                           \
		(position[POSITION] + current_size != COLOR_MAX))     \
		continue_up = 1;                                      \
	}

/* *********************************************************** */

#define	BINARY_TREE_EXPLORE_RIGHT_3(POSITION, COLOR_MAX,                       \
	IMAGE_TYPE, FIRST_NEIBOUR, SECOND_NEIBOUR, SUBTRACTION,                \
	SHIFT)                                                                 \
	{                                                                      \
	    if (distance >=                                                    \
		(((position[POSITION] + current_size -                         \
		c[POSITION]) * (position[POSITION] + current_size -            \
		c[POSITION])) >> SHIFT)) {                                     \
		if (distance <                                                 \
		    (((COLOR_MAX - c[POSITION]) * (COLOR_MAX -                 \
		    c[POSITION])) >> SHIFT)) {                                 \
		    if (distance <                                             \
			(((position[POSITION] + current_size * 2 -             \
			c[POSITION]) * (position[POSITION] +                   \
			current_size * 2 - c[POSITION])) >> SHIFT)) {          \
	                                                                       \
/*                                                                             \
 * Check only a part of quadrant                                               \
 */                                                                            \
			mlib_s32 qq = q ^ (1 << POSITION);                     \
	                                                                       \
			check_neibours[FIRST_NEIBOUR] += 1;                    \
			check_neibours[SECOND_NEIBOUR] += 1;                   \
			check_corner += 1;                                     \
			if (node->tag & (1 << qq)) {                           \
	                                                                       \
/*                                                                             \
 * Here is another color cell. Check the distance                              \
 */                                                                            \
			    mlib_s32 new_found_color =                         \
				node->contents.index[qq];                      \
			    mlib_u32 newdistance =                             \
				FIND_DISTANCE_3(c[0],                          \
				p[0][new_found_color] - SUBTRACTION,           \
				c[1],                                          \
				p[1][new_found_color] - SUBTRACTION,           \
				c[2],                                          \
				p[2][new_found_color] - SUBTRACTION,           \
				SHIFT);                                        \
			    if (newdistance < distance) {                      \
				found_color = new_found_color;                 \
				distance = newdistance;                        \
			    }                                                  \
			} else if (node->contents.quadrants[qq])               \
/*                                                                             \
 * Only a part of quadrant needs checking                                      \
 */                                                                            \
			    distance =                                         \
				FUNC_NAME(part_to_left_##IMAGE_TYPE##_3)       \
				(node->contents.quadrants[qq], distance,       \
				&found_color, c, p,                            \
				position[POSITION] + current_size,             \
				pass - 1, POSITION);                           \
		    } else                                                     \
/*                                                                             \
 * Check whole quadrant                                                        \
 */                                                                            \
		    {                                                          \
			mlib_s32 qq = q ^ (1 << POSITION);                     \
	                                                                       \
			check_neibours[FIRST_NEIBOUR] += 2;                    \
			check_neibours[SECOND_NEIBOUR] += 2;                   \
			check_corner += 2;                                     \
			continue_up = 1;                                       \
			if (node->tag & (1 << qq)) {                           \
	                                                                       \
/*                                                                             \
 * Here is another color cell. Check the distance                              \
 */                                                                            \
			    mlib_s32 new_found_color =                         \
				node->contents.index[qq];                      \
			    mlib_u32 newdistance =                             \
				FIND_DISTANCE_3(c[0],                          \
				p[0][new_found_color] - SUBTRACTION,           \
				c[1],                                          \
				p[1][new_found_color] - SUBTRACTION,           \
				c[2],                                          \
				p[2][new_found_color] - SUBTRACTION,           \
				SHIFT);                                        \
			    if (newdistance < distance) {                      \
				found_color = new_found_color;                 \
				distance = newdistance;                        \
			    }                                                  \
			} else if (node->contents.quadrants[qq])               \
/*                                                                             \
 * Here is a full node. Just explore it                                        \
 */                                                                            \
			    distance =                                         \
				FUNC_NAME(IMAGE_TYPE##_3)                      \
				(node->contents.quadrants[qq], distance,       \
				&found_color, c[0], c[1], c[2], p);            \
		    }                                                          \
		} else                                                         \
/*                                                                             \
 * Cell is on the edge of the space                                            \
 */                                                                            \
		{                                                              \
		    if (position[POSITION] + current_size * 2 ==               \
			COLOR_MAX) {                                           \
	                                                                       \
/*                                                                             \
 * Check only a part of quadrant                                               \
 */                                                                            \
			mlib_s32 qq = q ^ (1 << POSITION);                     \
	                                                                       \
			check_neibours[FIRST_NEIBOUR] += 1;                    \
			check_neibours[SECOND_NEIBOUR] += 1;                   \
			check_corner += 1;                                     \
			if (node->tag & (1 << qq)) {                           \
	                                                                       \
/*                                                                             \
 * Here is another color cell. Check the distance                              \
 */                                                                            \
			    mlib_s32 new_found_color =                         \
				node->contents.index[qq];                      \
			    mlib_u32 newdistance =                             \
				FIND_DISTANCE_3(c[0],                          \
				p[0][new_found_color] - SUBTRACTION,           \
				c[1],                                          \
				p[1][new_found_color] - SUBTRACTION,           \
				c[2],                                          \
				p[2][new_found_color] - SUBTRACTION,           \
				SHIFT);                                        \
			    if (newdistance < distance) {                      \
				found_color = new_found_color;                 \
				distance = newdistance;                        \
			    }                                                  \
			} else if (node->contents.quadrants[qq])               \
/*                                                                             \
 * Only a part of quadrant needs checking                                      \
 */                                                                            \
			    distance =                                         \
				FUNC_NAME(part_to_left_##IMAGE_TYPE##_3)       \
				(node->contents.quadrants[qq], distance,       \
				&found_color, c, p,                            \
				position[POSITION] + current_size,             \
				pass - 1, POSITION);                           \
		    } else                                                     \
/*                                                                             \
 * Check whole quadrant                                                        \
 */                                                                            \
		    {                                                          \
			mlib_s32 qq = q ^ (1 << POSITION);                     \
	                                                                       \
			check_neibours[FIRST_NEIBOUR] += 2;                    \
			check_neibours[SECOND_NEIBOUR] += 2;                   \
			check_corner += 2;                                     \
			continue_up = 1;                                       \
			if (node->tag & (1 << qq)) {                           \
	                                                                       \
/*                                                                             \
 * Here is another color cell. Check the distance                              \
 */                                                                            \
			    mlib_s32 new_found_color =                         \
				node->contents.index[qq];                      \
			    mlib_u32 newdistance =                             \
				FIND_DISTANCE_3(c[0],                          \
				p[0][new_found_color] - SUBTRACTION,           \
				c[1],                                          \
				p[1][new_found_color] - SUBTRACTION,           \
				c[2],                                          \
				p[2][new_found_color] - SUBTRACTION,           \
				SHIFT);                                        \
			    if (newdistance < distance) {                      \
				found_color = new_found_color;                 \
				distance = newdistance;                        \
			    }                                                  \
			} else if (node->contents.quadrants[qq])               \
/*                                                                             \
 * Here is a full node. Just explore it                                        \
 */                                                                            \
			    distance =                                         \
				FUNC_NAME(IMAGE_TYPE##_3)                      \
				(node->contents.quadrants[qq], distance,       \
				&found_color, c[0], c[1], c[2], p);            \
		    }                                                          \
		}                                                              \
	    }                                                                  \
	}

/* *********************************************************** */

#define	BINARY_TREE_EXPLORE_RIGHT_4(POSITION, COLOR_MAX,                    \
	IMAGE_TYPE, FIRST_NEIBOUR, SECOND_NEIBOUR, THIRD_NEIBOUR,           \
	SUBTRACTION, SHIFT)                                                 \
	{                                                                   \
	    if (distance >=                                                 \
		(((position[POSITION] + current_size -                      \
		c[POSITION]) * (position[POSITION] + current_size -         \
		c[POSITION])) >> SHIFT)) {                                  \
		if (distance <                                              \
		    (((COLOR_MAX - c[POSITION]) * (COLOR_MAX -              \
		    c[POSITION])) >> SHIFT)) {                              \
		    if (distance <                                          \
			(((position[POSITION] + current_size * 2 -          \
			c[POSITION]) * (position[POSITION] +                \
			current_size * 2 - c[POSITION])) >> SHIFT)) {       \
	                                                                    \
/*                                                                          \
 * Check only a part of quadrant                                            \
 */                                                                         \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 1;                 \
			check_neibours[SECOND_NEIBOUR] += 1;                \
			check_neibours[THIRD_NEIBOUR] += 1;                 \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_4(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				c[3],                                       \
				p[3][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Only a part of quadrant needs checking                                   \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(part_to_left_##IMAGE_TYPE##_4)    \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c, p,                         \
				position[POSITION] + current_size,          \
				pass - 1, POSITION);                        \
		    } else                                                  \
/*                                                                          \
 * Check whole quadrant                                                     \
 */                                                                         \
		    {                                                       \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 2;                 \
			check_neibours[SECOND_NEIBOUR] += 2;                \
			check_neibours[THIRD_NEIBOUR] += 2;                 \
			continue_up = 1;                                    \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_4(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				c[3],                                       \
				p[3][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Here is a full node. Just explore it                                     \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(IMAGE_TYPE##_4)                   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c[0], c[1], c[2], c[3],       \
				p);                                         \
		    }                                                       \
		} else                                                      \
/*                                                                          \
 * Cell is on the edge of the space                                         \
 */                                                                         \
		{                                                           \
		    if (position[POSITION] + current_size * 2 ==            \
			COLOR_MAX) {                                        \
	                                                                    \
/*                                                                          \
 * Check only a part of quadrant                                            \
 */                                                                         \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 1;                 \
			check_neibours[SECOND_NEIBOUR] += 1;                \
			check_neibours[THIRD_NEIBOUR] += 1;                 \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_4(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				c[3],                                       \
				p[3][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Only a part of quadrant needs checking                                   \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(part_to_left_##IMAGE_TYPE##_4)    \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c, p,                         \
				position[POSITION] + current_size,          \
				pass - 1, POSITION);                        \
		    } else                                                  \
/*                                                                          \
 * Check whole quadrant                                                     \
 */                                                                         \
		    {                                                       \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 2;                 \
			check_neibours[SECOND_NEIBOUR] += 2;                \
			check_neibours[THIRD_NEIBOUR] += 2;                 \
			continue_up = 1;                                    \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_4(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				c[3],                                       \
				p[3][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Here is a full node. Just explore it                                     \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(IMAGE_TYPE##_4)                   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c[0], c[1], c[2], c[3],       \
				p);                                         \
		    }                                                       \
		}                                                           \
	    }                                                               \
	}

/* *********************************************************** */

#define	BINARY_TREE_SEARCH_LEFT(POSITION, SHIFT)                  \
	{                                                         \
	    if ((distance >                                       \
		(((position[POSITION] -                           \
		c[POSITION]) * (position[POSITION] -              \
		c[POSITION])) >> SHIFT)) && position[POSITION])   \
		continue_up = 1;                                  \
	}

/* *********************************************************** */

#define	BINARY_TREE_EXPLORE_LEFT_3(POSITION, IMAGE_TYPE,                    \
	FIRST_NEIBOUR, SECOND_NEIBOUR, SUBTRACTION, SHIFT)                  \
	{                                                                   \
	    if (distance >                                                  \
		(((c[POSITION] - position[POSITION]) * (c[POSITION] -       \
		position[POSITION])) >> SHIFT)) {                           \
		if (distance <= ((c[POSITION] * c[POSITION]) >> SHIFT)) {   \
		    if (distance <=                                         \
			(((c[POSITION] + current_size -                     \
			position[POSITION]) * (c[POSITION] +                \
			current_size - position[POSITION])) >> SHIFT)) {    \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 1;                 \
			check_neibours[SECOND_NEIBOUR] += 1;                \
			check_corner += 1;                                  \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_3(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Only a part of quadrant needs checking                                   \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(part_to_right_##IMAGE_TYPE##_3)   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c, p,                         \
				position[POSITION] - current_size,          \
				pass - 1, POSITION);                        \
		    } else                                                  \
/*                                                                          \
 * Check whole quadrant                                                     \
 */                                                                         \
		    {                                                       \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 2;                 \
			check_neibours[SECOND_NEIBOUR] += 2;                \
			check_corner += 2;                                  \
			continue_up = 1;                                    \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_3(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Here is a full node. Just explore it                                     \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(IMAGE_TYPE##_3)                   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c[0], c[1], c[2], p);         \
		    }                                                       \
		} else {                                                    \
		    if (!(position[POSITION] - current_size)) {             \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 1;                 \
			check_neibours[SECOND_NEIBOUR] += 1;                \
			check_corner += 1;                                  \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_3(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Only a part of quadrant needs checking                                   \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(part_to_right_##IMAGE_TYPE##_3)   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c, p,                         \
				position[POSITION] - current_size,          \
				pass - 1, POSITION);                        \
		    } else {                                                \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 2;                 \
			check_neibours[SECOND_NEIBOUR] += 2;                \
			check_corner += 2;                                  \
			continue_up = 1;                                    \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_3(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Here is a full node. Just explore it                                     \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(IMAGE_TYPE##_3)                   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c[0], c[1], c[2], p);         \
		    }                                                       \
		}                                                           \
	    }                                                               \
	}

/* *********************************************************** */

#define	BINARY_TREE_EXPLORE_LEFT_4(POSITION, IMAGE_TYPE,                    \
	FIRST_NEIBOUR, SECOND_NEIBOUR, THIRD_NEIBOUR, SUBTRACTION,          \
	SHIFT)                                                              \
	{                                                                   \
	    if (distance >                                                  \
		(((c[POSITION] - position[POSITION]) * (c[POSITION] -       \
		position[POSITION])) >> SHIFT)) {                           \
		if (distance <= ((c[POSITION] * c[POSITION]) >> SHIFT)) {   \
		    if (distance <=                                         \
			(((c[POSITION] + current_size -                     \
			position[POSITION]) * (c[POSITION] +                \
			current_size - position[POSITION])) >> SHIFT)) {    \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 1;                 \
			check_neibours[SECOND_NEIBOUR] += 1;                \
			check_neibours[THIRD_NEIBOUR] += 1;                 \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_4(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				c[3],                                       \
				p[3][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Only a part of quadrant needs checking                                   \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(part_to_right_##IMAGE_TYPE##_4)   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c, p,                         \
				position[POSITION] - current_size,          \
				pass - 1, POSITION);                        \
		    } else                                                  \
/*                                                                          \
 * Check whole quadrant                                                     \
 */                                                                         \
		    {                                                       \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 2;                 \
			check_neibours[SECOND_NEIBOUR] += 2;                \
			check_neibours[THIRD_NEIBOUR] += 2;                 \
			continue_up = 1;                                    \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_4(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				c[3],                                       \
				p[3][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Here is a full node. Just explore it                                     \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(IMAGE_TYPE##_4)                   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c[0], c[1], c[2], c[3],       \
				p);                                         \
		    }                                                       \
		} else {                                                    \
		    if (!(position[POSITION] - current_size)) {             \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 1;                 \
			check_neibours[SECOND_NEIBOUR] += 1;                \
			check_neibours[THIRD_NEIBOUR] += 1;                 \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_4(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				c[3],                                       \
				p[3][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Only a part of quadrant needs checking                                   \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(part_to_right_##IMAGE_TYPE##_4)   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c, p,                         \
				position[POSITION] - current_size,          \
				pass - 1, POSITION);                        \
		    } else {                                                \
			mlib_s32 qq = q ^ (1 << POSITION);                  \
	                                                                    \
			check_neibours[FIRST_NEIBOUR] += 2;                 \
			check_neibours[SECOND_NEIBOUR] += 2;                \
			check_neibours[THIRD_NEIBOUR] += 2;                 \
			continue_up = 1;                                    \
			if (node->tag & (1 << qq)) {                        \
	                                                                    \
/*                                                                          \
 * Here is another color cell. Check the distance                           \
 */                                                                         \
			    mlib_s32 new_found_color =                      \
				node->contents.index[qq];                   \
			    mlib_u32 newdistance =                          \
				FIND_DISTANCE_4(c[0],                       \
				p[0][new_found_color] - SUBTRACTION,        \
				c[1],                                       \
				p[1][new_found_color] - SUBTRACTION,        \
				c[2],                                       \
				p[2][new_found_color] - SUBTRACTION,        \
				c[3],                                       \
				p[3][new_found_color] - SUBTRACTION,        \
				SHIFT);                                     \
			    if (newdistance < distance) {                   \
				found_color = new_found_color;              \
				distance = newdistance;                     \
			    }                                               \
			} else if (node->contents.quadrants[qq])            \
/*                                                                          \
 * Here is a full node. Just explore it                                     \
 */                                                                         \
			    distance =                                      \
				FUNC_NAME(IMAGE_TYPE##_4)                   \
				(node->contents.quadrants[qq], distance,    \
				&found_color, c[0], c[1], c[2], c[3],       \
				p);                                         \
		    }                                                       \
		}                                                           \
	    }                                                               \
	}

/* *********************************************************** */

#define	CHECK_QUADRANT_U8_3(qq)                                           \
	{                                                                 \
	    if (node->tag & (1 << qq)) {                                  \
	                                                                  \
/*                                                                        \
 * Here is another color cell. Check the distance                         \
 */                                                                       \
		mlib_s32 new_found_color = node->contents.index[qq];      \
		mlib_u32 newdistance =                                    \
		    FIND_DISTANCE_3(c[0], p[0][new_found_color], c[1],    \
		    p[1][new_found_color], c[2], p[2][new_found_color],   \
		    0);                                                   \
		if (newdistance < distance) {                             \
		    found_color = new_found_color;                        \
		    distance = newdistance;                               \
		}                                                         \
	    } else if (node->contents.quadrants[qq])                      \
/*                                                                        \
 * Here is a full node. Just explore it all                               \
 */                                                                       \
		distance =                                                \
		    mlib_search_quadrant_U8_3(node->contents.             \
		    quadrants[qq], distance, &found_color, c[0], c[1],    \
		    c[2], p);                                             \
/*                                                                        \
 * Else there is just an empty cell                                       \
 */                                                                       \
	}

/* *********************************************************** */

#define	CHECK_QUADRANT_S16_3(qq)                                         \
	{                                                                \
	    if (node->tag & (1 << qq)) {                                 \
	                                                                 \
/*                                                                       \
 * Here is another color cell. Check the distance                        \
 */                                                                      \
		mlib_s32 new_found_color = node->contents.index[qq];     \
		mlib_u32 palc0, palc1, palc2, newdistance;               \
	                                                                 \
		palc0 = p[0][new_found_color] - MLIB_S16_MIN;            \
		palc1 = p[1][new_found_color] - MLIB_S16_MIN;            \
		palc2 = p[2][new_found_color] - MLIB_S16_MIN;            \
		newdistance =                                            \
		    FIND_DISTANCE_3(c[0], palc0, c[1], palc1, c[2],      \
		    palc2, 2);                                           \
		if (newdistance < distance) {                            \
		    found_color = new_found_color;                       \
		    distance = newdistance;                              \
		}                                                        \
	    } else if (node->contents.quadrants[qq])                     \
/*                                                                       \
 * Here is a full node. Just explore it all                              \
 */                                                                      \
		distance =                                               \
		    mlib_search_quadrant_S16_3(node->contents.           \
		    quadrants[qq], distance, &found_color, c[0], c[1],   \
		    c[2], p);                                            \
/*                                                                       \
 * Else there is just an empty cell                                      \
 */                                                                      \
	}

/* *********************************************************** */

#define	BINARY_TREE_SEARCH_3(SOURCE_IMAGE, POINTER_TYPE,                   \
	BITS, COLOR_MAX, SUBTRACTION, POINTER_SHIFT, STEP, SHIFT)          \
	{                                                                  \
	    const POINTER_TYPE *channels[3], *p[3];                        \
	    mlib_u32 c[3];                                                 \
	    mlib_s32 j;                                                    \
	                                                                   \
	    p[0] = s->lut[0];                                              \
	    p[1] = s->lut[1];                                              \
	    p[2] = s->lut[2];                                              \
	    channels[0] = src + POINTER_SHIFT;                             \
	    channels[1] = src + 1 + POINTER_SHIFT;                         \
	    channels[2] = src + 2 + POINTER_SHIFT;                         \
	    for (j = 0; j < length; j++) {                                 \
		mlib_s32 pass = BITS - 1;                                  \
		mlib_u32 position[3] = {                                   \
		    0, 0, 0                                                \
		}                                                          \
		;                                                          \
		mlib_s32 we_found_it = 0;                                  \
		struct lut_node_3 *node = s->table;                        \
	                                                                   \
/*                                                                         \
 * Stack pointer pointers to the first free element of stack.              \
 */                                                                        \
	                                                                   \
/*                                                                         \
 * The node we are in is in the `node'                                     \
 */                                                                        \
		struct                                                     \
		{                                                          \
		    struct lut_node_3 *node;                               \
		    mlib_s32 q;                                            \
		}                                                          \
		stack[BITS];                                               \
		mlib_s32 stack_pointer = 0;                                \
	                                                                   \
		c[0] = *channels[0] - SUBTRACTION;                         \
		c[1] = *channels[1] - SUBTRACTION;                         \
		c[2] = *channels[2] - SUBTRACTION;                         \
		do {                                                       \
		    mlib_s32 q;                                            \
		    mlib_u32 current_size = 1 << pass;                     \
	                                                                   \
		    q = ((c[0] >> pass) & 1) | (((c[1] << 1) >> pass) &    \
			2) | (((c[2] << 2) >> pass) & 4);                  \
		    position[0] |= c[0] & current_size;                    \
		    position[1] |= c[1] & current_size;                    \
		    position[2] |= c[2] & current_size;                    \
		    if (node->tag & (1 << q)) {                            \
	                                                                   \
/*                                                                         \
 * Here is a cell with one color. We need to be sure it's the one that     \
 * is the closest to our color                                             \
 */                                                                        \
			mlib_s32 palindex = node->contents.index[q];       \
			mlib_u32 palc[3];                                  \
			mlib_s32 identical;                                \
	                                                                   \
			palc[0] = p[0][palindex] - SUBTRACTION;            \
			palc[1] = p[1][palindex] - SUBTRACTION;            \
			palc[2] = p[2][palindex] - SUBTRACTION;            \
			identical =                                        \
			    (palc[0] - c[0]) | (palc[1] -                  \
			    c[1]) | (palc[2] - c[2]);                      \
			if (!identical || BITS - pass == bits) {           \
	                                                                   \
/*                                                                         \
 * Oh, here it is :)                                                       \
 */                                                                        \
			    dst[j] = palindex + s->offset;                 \
			    we_found_it = 1;                               \
			} else {                                           \
			    mlib_u32 distance;                             \
	                                                                   \
/*                                                                         \
 * First index is the channel, second is the number of the side            \
 */                                                                        \
			    mlib_s32 found_color;                          \
			    mlib_s32 continue_up;                          \
	                                                                   \
			    distance =                                     \
				FIND_DISTANCE_3(c[0], palc[0], c[1],       \
				palc[1], c[2], palc[2], SHIFT);            \
			    found_color = palindex;                        \
			    do {                                           \
				mlib_s32 check_corner;                     \
	                                                                   \
/*                                                                         \
 * Neighbors are enumerated in a circle: 0 - between quadrants 0           \
 * and 1, 1 - between quadrants 1 and 2 and 2 - between                    \
 * quadrants 2 and 0                                                       \
 */                                                                        \
				mlib_s32 check_neibours[3];                \
	                                                                   \
/*                                                                         \
 * Others are three two neibour quadrants Side number is [                 \
 * <number of the coordinate >][ <the bit in the quadrant                  \
 * number of the corner, corresponding to this coordinate> ],              \
 * e.g. 2 is 0..010b, so the sides it has near are: [ 0                    \
 * (coordinate number) ][ 0 (bit 0 in the number) ] [ 1                    \
 * (coordinate number) ][ 1 (bit 1 in the number) ] Now we can             \
 * look in the three nearest quadrants. Do we really need it ?             \
 * Check it.                                                               \
 */                                                                        \
				check_corner = check_neibours[0] =         \
				    check_neibours[1] =                    \
				    check_neibours[2] = 0;                 \
				continue_up = 0;                           \
				if (q & 1) {                               \
				    BINARY_TREE_EXPLORE_LEFT_3(0,          \
					SOURCE_IMAGE, 2, 0, SUBTRACTION,   \
					SHIFT);                            \
				} else {                                   \
				    BINARY_TREE_EXPLORE_RIGHT_3(0,         \
					COLOR_MAX, SOURCE_IMAGE, 2, 0,     \
					SUBTRACTION, SHIFT);               \
				}                                          \
				if (q & 2) {                               \
				    BINARY_TREE_EXPLORE_LEFT_3(1,          \
					SOURCE_IMAGE, 0, 1, SUBTRACTION,   \
					SHIFT);                            \
				} else {                                   \
				    BINARY_TREE_EXPLORE_RIGHT_3(1,         \
					COLOR_MAX, SOURCE_IMAGE, 0, 1,     \
					SUBTRACTION, SHIFT);               \
				}                                          \
				if (q & 4) {                               \
				    BINARY_TREE_EXPLORE_LEFT_3(2,          \
					SOURCE_IMAGE, 1, 2, SUBTRACTION,   \
					SHIFT);                            \
				} else {                                   \
				    BINARY_TREE_EXPLORE_RIGHT_3(2,         \
					COLOR_MAX, SOURCE_IMAGE, 1, 2,     \
					SUBTRACTION, SHIFT);               \
				}                                          \
				if (check_neibours[0] >= 2) {              \
				    mlib_s32 qq = q ^ 3;                   \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_3      \
					(qq);                              \
				}                                          \
				if (check_neibours[1] >= 2) {              \
				    mlib_s32 qq = q ^ 6;                   \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_3      \
					(qq);                              \
				}                                          \
				if (check_neibours[2] >= 2) {              \
				    mlib_s32 qq = q ^ 5;                   \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_3      \
					(qq);                              \
				}                                          \
				if (check_corner >= 3) {                   \
				    mlib_s32 qq = q ^ 7;                   \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_3      \
					(qq);                              \
				}                                          \
				if (q & 1) {                               \
				    BINARY_TREE_SEARCH_RIGHT(0,            \
					COLOR_MAX, SHIFT);                 \
				} else {                                   \
				    BINARY_TREE_SEARCH_LEFT(0, SHIFT);     \
				}                                          \
				if (q & 2) {                               \
				    BINARY_TREE_SEARCH_RIGHT(1,            \
					COLOR_MAX, SHIFT);                 \
				} else {                                   \
				    BINARY_TREE_SEARCH_LEFT(1, SHIFT);     \
				}                                          \
				if (q & 4) {                               \
				    BINARY_TREE_SEARCH_RIGHT(2,            \
					COLOR_MAX, SHIFT);                 \
				} else {                                   \
				    BINARY_TREE_SEARCH_LEFT(2, SHIFT);     \
				}                                          \
				position[0] &= ~(c[0] & current_size);     \
				position[1] &= ~(c[1] & current_size);     \
				position[2] &= ~(c[2] & current_size);     \
				current_size <<= 1;                        \
				pass++;                                    \
				stack_pointer--;                           \
				q = stack[stack_pointer].q;                \
				node = stack[stack_pointer].node;          \
			    }                                              \
			    while (continue_up);                           \
			    dst[j] = found_color + s->offset;              \
			    we_found_it = 1;                               \
			}                                                  \
		    } else if (node->contents.quadrants[q]) {              \
	                                                                   \
/*                                                                         \
 * Descend one level                                                       \
 */                                                                        \
			stack[stack_pointer].node = node;                  \
			stack[stack_pointer++].q = q;                      \
			node = node->contents.quadrants[q];                \
		    } else {                                               \
	                                                                   \
/*                                                                         \
 * Found the empty quadrant. Look around                                   \
 */                                                                        \
			mlib_u32 distance = MLIB_U32_MAX;                  \
			mlib_s32 found_color;                              \
			mlib_s32 continue_up;                              \
	                                                                   \
/*                                                                         \
 * As we had come to this level, it is warranted that there are other      \
 * points on this level near the empty quadrant                            \
 */                                                                        \
			do {                                               \
			    mlib_s32 check_corner;                         \
			    mlib_s32 check_neibours[3];                    \
	                                                                   \
			    check_corner = check_neibours[0] =             \
				check_neibours[1] = check_neibours[2] =    \
				0;                                         \
			    continue_up = 0;                               \
			    if (q & 1) {                                   \
				BINARY_TREE_EXPLORE_LEFT_3(0,              \
				    SOURCE_IMAGE, 2, 0, SUBTRACTION,       \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_EXPLORE_RIGHT_3(0,             \
				    COLOR_MAX, SOURCE_IMAGE, 2, 0,         \
				    SUBTRACTION, SHIFT);                   \
			    }                                              \
			    if (q & 2) {                                   \
				BINARY_TREE_EXPLORE_LEFT_3(1,              \
				    SOURCE_IMAGE, 0, 1, SUBTRACTION,       \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_EXPLORE_RIGHT_3(1,             \
				    COLOR_MAX, SOURCE_IMAGE, 0, 1,         \
				    SUBTRACTION, SHIFT);                   \
			    }                                              \
			    if (q & 4) {                                   \
				BINARY_TREE_EXPLORE_LEFT_3(2,              \
				    SOURCE_IMAGE, 1, 2, SUBTRACTION,       \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_EXPLORE_RIGHT_3(2,             \
				    COLOR_MAX, SOURCE_IMAGE, 1, 2,         \
				    SUBTRACTION, SHIFT);                   \
			    }                                              \
			    if (check_neibours[0] >= 2) {                  \
				mlib_s32 qq = q ^ 3;                       \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_3          \
				    (qq);                                  \
			    }                                              \
			    if (check_neibours[1] >= 2) {                  \
				mlib_s32 qq = q ^ 6;                       \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_3          \
				    (qq);                                  \
			    }                                              \
			    if (check_neibours[2] >= 2) {                  \
				mlib_s32 qq = q ^ 5;                       \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_3          \
				    (qq);                                  \
			    }                                              \
			    if (check_corner >= 3) {                       \
				mlib_s32 qq = q ^ 7;                       \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_3          \
				    (qq);                                  \
			    }                                              \
			    if (q & 1) {                                   \
				BINARY_TREE_SEARCH_RIGHT(0, COLOR_MAX,     \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_SEARCH_LEFT(0, SHIFT);         \
			    }                                              \
			    if (q & 2) {                                   \
				BINARY_TREE_SEARCH_RIGHT(1, COLOR_MAX,     \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_SEARCH_LEFT(1, SHIFT);         \
			    }                                              \
			    if (q & 4) {                                   \
				BINARY_TREE_SEARCH_RIGHT(2, COLOR_MAX,     \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_SEARCH_LEFT(2, SHIFT);         \
			    }                                              \
			    position[0] &= ~(c[0] & current_size);         \
			    position[1] &= ~(c[1] & current_size);         \
			    position[2] &= ~(c[2] & current_size);         \
			    current_size <<= 1;                            \
			    pass++;                                        \
			    stack_pointer--;                               \
			    q = stack[stack_pointer].q;                    \
			    node = stack[stack_pointer].node;              \
			}                                                  \
			while (continue_up);                               \
			dst[j] = found_color + s->offset;                  \
			we_found_it = 1;                                   \
		    }                                                      \
		    pass--;                                                \
		}                                                          \
		while (!we_found_it);                                      \
		channels[0] += STEP;                                       \
		channels[1] += STEP;                                       \
		channels[2] += STEP;                                       \
	    }                                                              \
	}

/* *********************************************************** */

#define	CHECK_QUADRANT_U8_4(qq)                                           \
	{                                                                 \
	    if (node->tag & (1 << qq)) {                                  \
	                                                                  \
/*                                                                        \
 * Here is another color cell. Check the distance                         \
 */                                                                       \
		mlib_s32 new_found_color = node->contents.index[qq];      \
		mlib_u32 newdistance =                                    \
		    FIND_DISTANCE_4(c[0], p[0][new_found_color], c[1],    \
		    p[1][new_found_color], c[2], p[2][new_found_color],   \
		    c[3], p[3][new_found_color], 0);                      \
		if (newdistance < distance) {                             \
		    found_color = new_found_color;                        \
		    distance = newdistance;                               \
		}                                                         \
	    } else if (node->contents.quadrants[qq])                      \
/*                                                                        \
 * Here is a full node. Just explore it all                               \
 */                                                                       \
		distance =                                                \
		    mlib_search_quadrant_U8_4(node->contents.             \
		    quadrants[qq], distance, &found_color, c[0], c[1],    \
		    c[2], c[3], p);                                       \
/*                                                                        \
 * Else there is just an empty cell                                       \
 */                                                                       \
	}

/* *********************************************************** */

#define	CHECK_QUADRANT_S16_4(qq)                                         \
	{                                                                \
	    if (node->tag & (1 << qq)) {                                 \
	                                                                 \
/*                                                                       \
 * Here is another color cell. Check the distance                        \
 */                                                                      \
		mlib_s32 new_found_color = node->contents.index[qq];     \
		mlib_u32 palc0, palc1, palc2, palc3, newdistance;        \
	                                                                 \
		palc0 = p[0][new_found_color] - MLIB_S16_MIN;            \
		palc1 = p[1][new_found_color] - MLIB_S16_MIN;            \
		palc2 = p[2][new_found_color] - MLIB_S16_MIN;            \
		palc3 = p[3][new_found_color] - MLIB_S16_MIN;            \
		newdistance =                                            \
		    FIND_DISTANCE_4(c[0], palc0, c[1], palc1, c[2],      \
		    palc2, c[3], palc3, 2);                              \
		if (newdistance < distance) {                            \
		    found_color = new_found_color;                       \
		    distance = newdistance;                              \
		}                                                        \
	    } else if (node->contents.quadrants[qq])                     \
/*                                                                       \
 * Here is a full node. Just explore it all                              \
 */                                                                      \
		distance =                                               \
		    mlib_search_quadrant_S16_4(node->contents.           \
		    quadrants[qq], distance, &found_color, c[0], c[1],   \
		    c[2], c[3], p);                                      \
/*                                                                       \
 * Else there is just an empty cell                                      \
 */                                                                      \
	}

/* *********************************************************** */

#define	BINARY_TREE_SEARCH_4(SOURCE_IMAGE, POINTER_TYPE,                   \
	BITS, COLOR_MAX, SUBTRACTION, SHIFT)                               \
	{                                                                  \
	    const POINTER_TYPE *channels[4], *p[4];                        \
	    mlib_u32 c[4];                                                 \
	    mlib_s32 j;                                                    \
	                                                                   \
	    p[0] = s->lut[0];                                              \
	    p[1] = s->lut[1];                                              \
	    p[2] = s->lut[2];                                              \
	    p[3] = s->lut[3];                                              \
	    channels[0] = src;                                             \
	    channels[1] = src + 1;                                         \
	    channels[2] = src + 2;                                         \
	    channels[3] = src + 3;                                         \
	    for (j = 0; j < length; j++) {                                 \
		mlib_s32 pass = BITS - 1;                                  \
		mlib_u32 position[4] = {                                   \
		    0, 0, 0, 0                                             \
		}                                                          \
		;                                                          \
		mlib_s32 we_found_it = 0;                                  \
		struct lut_node_4 *node = s->table;                        \
	                                                                   \
/*                                                                         \
 * Stack pointer pointers to the first free element of stack.              \
 */                                                                        \
	                                                                   \
/*                                                                         \
 * The node we are in is in the `node'                                     \
 */                                                                        \
		struct                                                     \
		{                                                          \
		    struct lut_node_4 *node;                               \
		    mlib_s32 q;                                            \
		}                                                          \
		stack[BITS];                                               \
		mlib_s32 stack_pointer = 0;                                \
	                                                                   \
		c[0] = *channels[0] - SUBTRACTION;                         \
		c[1] = *channels[1] - SUBTRACTION;                         \
		c[2] = *channels[2] - SUBTRACTION;                         \
		c[3] = *channels[3] - SUBTRACTION;                         \
		do {                                                       \
		    mlib_s32 q;                                            \
		    mlib_u32 current_size = 1 << pass;                     \
	                                                                   \
		    q = ((c[0] >> pass) & 1) | (((c[1] << 1) >> pass) &    \
			2) | (((c[2] << 2) >> pass) & 4) | (((c[3] << 3)   \
			>> pass) & 8);                                     \
		    position[0] |= c[0] & current_size;                    \
		    position[1] |= c[1] & current_size;                    \
		    position[2] |= c[2] & current_size;                    \
		    position[3] |= c[3] & current_size;                    \
		    if (node->tag & (1 << q)) {                            \
	                                                                   \
/*                                                                         \
 * Here is a cell with one color. We need to be sure it's the one that     \
 * is the closest to our color                                             \
 */                                                                        \
			mlib_s32 palindex = node->contents.index[q];       \
			mlib_u32 palc[4];                                  \
			mlib_s32 identical;                                \
	                                                                   \
			palc[0] = p[0][palindex] - SUBTRACTION;            \
			palc[1] = p[1][palindex] - SUBTRACTION;            \
			palc[2] = p[2][palindex] - SUBTRACTION;            \
			palc[3] = p[3][palindex] - SUBTRACTION;            \
			identical =                                        \
			    (palc[0] - c[0]) | (palc[1] -                  \
			    c[1]) | (palc[2] - c[2]) | (palc[3] - c[3]);   \
			if (!identical || BITS - pass == bits) {           \
	                                                                   \
/*                                                                         \
 * Oh, here it is :)                                                       \
 */                                                                        \
			    dst[j] = palindex + s->offset;                 \
			    we_found_it = 1;                               \
			} else {                                           \
			    mlib_u32 distance;                             \
	                                                                   \
/*                                                                         \
 * First index is the channel, second is the number of the side            \
 */                                                                        \
			    mlib_s32 found_color;                          \
			    mlib_s32 continue_up;                          \
	                                                                   \
			    distance =                                     \
				FIND_DISTANCE_4(c[0], palc[0], c[1],       \
				palc[1], c[2], palc[2], c[3], palc[3],     \
				SHIFT);                                    \
			    found_color = palindex;                        \
			    do {                                           \
				mlib_s32 check_corner;                     \
				mlib_s32 check_neibours[6];                \
				mlib_s32 check_far_neibours[4];            \
	                                                                   \
/*                                                                         \
 * Check neibours: quadrants that are different by 2 bits from             \
 * the quadrant, that we are in: 3 - 0 5 - 1 6 - 2 9 - 3 10 -              \
 * 4 12 - 5 Far quadrants: different by 3 bits: 7 - 0 11 - 1               \
 * 13 - 2 14 - 3                                                           \
 */                                                                        \
				check_neibours[0] = check_neibours[1] =    \
				    check_neibours[2] =                    \
				    check_neibours[3] =                    \
				    check_neibours[4] =                    \
				    check_neibours[5] = 0;                 \
				continue_up = 0;                           \
				if (q & 1) {                               \
				    BINARY_TREE_EXPLORE_LEFT_4(0,          \
					SOURCE_IMAGE, 0, 1, 3,             \
					SUBTRACTION, SHIFT);               \
				} else {                                   \
				    BINARY_TREE_EXPLORE_RIGHT_4(0,         \
					COLOR_MAX, SOURCE_IMAGE, 0, 1,     \
					3, SUBTRACTION, SHIFT);            \
				}                                          \
				if (q & 2) {                               \
				    BINARY_TREE_EXPLORE_LEFT_4(1,          \
					SOURCE_IMAGE, 0, 2, 4,             \
					SUBTRACTION, SHIFT);               \
				} else {                                   \
				    BINARY_TREE_EXPLORE_RIGHT_4(1,         \
					COLOR_MAX, SOURCE_IMAGE, 0, 2,     \
					4, SUBTRACTION, SHIFT);            \
				}                                          \
				if (q & 4) {                               \
				    BINARY_TREE_EXPLORE_LEFT_4(2,          \
					SOURCE_IMAGE, 1, 2, 5,             \
					SUBTRACTION, SHIFT);               \
				} else {                                   \
				    BINARY_TREE_EXPLORE_RIGHT_4(2,         \
					COLOR_MAX, SOURCE_IMAGE, 1, 2,     \
					5, SUBTRACTION, SHIFT);            \
				}                                          \
				if (q & 8) {                               \
				    BINARY_TREE_EXPLORE_LEFT_4(3,          \
					SOURCE_IMAGE, 3, 4, 5,             \
					SUBTRACTION, SHIFT);               \
				} else {                                   \
				    BINARY_TREE_EXPLORE_RIGHT_4(3,         \
					COLOR_MAX, SOURCE_IMAGE, 3, 4,     \
					5, SUBTRACTION, SHIFT);            \
				}                                          \
				check_far_neibours[0] =                    \
				    check_neibours[0] +                    \
				    check_neibours[1] +                    \
				    check_neibours[2];                     \
				check_far_neibours[1] =                    \
				    check_neibours[0] +                    \
				    check_neibours[3] +                    \
				    check_neibours[4];                     \
				check_far_neibours[2] =                    \
				    check_neibours[1] +                    \
				    check_neibours[3] +                    \
				    check_neibours[5];                     \
				check_far_neibours[3] =                    \
				    check_neibours[2] +                    \
				    check_neibours[4] +                    \
				    check_neibours[5];                     \
				check_corner =                             \
				    check_far_neibours[0] +                \
				    check_far_neibours[1] +                \
				    check_far_neibours[2] +                \
				    check_far_neibours[3];                 \
				if (check_neibours[0] >= 2) {              \
				    mlib_s32 qq = q ^ 3;                   \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_neibours[1] >= 2) {              \
				    mlib_s32 qq = q ^ 5;                   \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_neibours[2] >= 2) {              \
				    mlib_s32 qq = q ^ 6;                   \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_neibours[3] >= 2) {              \
				    mlib_s32 qq = q ^ 9;                   \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_neibours[4] >= 2) {              \
				    mlib_s32 qq = q ^ 10;                  \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_neibours[5] >= 2) {              \
				    mlib_s32 qq = q ^ 12;                  \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_far_neibours[0] >= 3) {          \
				    mlib_s32 qq = q ^ 7;                   \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_far_neibours[1] >= 3) {          \
				    mlib_s32 qq = q ^ 11;                  \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_far_neibours[2] >= 3) {          \
				    mlib_s32 qq = q ^ 13;                  \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_far_neibours[3] >= 3) {          \
				    mlib_s32 qq = q ^ 14;                  \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (check_corner >= 4) {                   \
				    mlib_s32 qq = q ^ 15;                  \
	                                                                   \
				    CHECK_QUADRANT_##SOURCE_IMAGE##_4      \
					(qq);                              \
				}                                          \
				if (q & 1) {                               \
				    BINARY_TREE_SEARCH_RIGHT(0,            \
					COLOR_MAX, SHIFT);                 \
				} else {                                   \
				    BINARY_TREE_SEARCH_LEFT(0, SHIFT);     \
				}                                          \
				if (q & 2) {                               \
				    BINARY_TREE_SEARCH_RIGHT(1,            \
					COLOR_MAX, SHIFT);                 \
				} else {                                   \
				    BINARY_TREE_SEARCH_LEFT(1, SHIFT);     \
				}                                          \
				if (q & 4) {                               \
				    BINARY_TREE_SEARCH_RIGHT(2,            \
					COLOR_MAX, SHIFT);                 \
				} else {                                   \
				    BINARY_TREE_SEARCH_LEFT(2, SHIFT);     \
				}                                          \
				if (q & 8) {                               \
				    BINARY_TREE_SEARCH_RIGHT(3,            \
					COLOR_MAX, SHIFT);                 \
				} else {                                   \
				    BINARY_TREE_SEARCH_LEFT(3, SHIFT);     \
				}                                          \
				position[0] &= ~(c[0] & current_size);     \
				position[1] &= ~(c[1] & current_size);     \
				position[2] &= ~(c[2] & current_size);     \
				position[3] &= ~(c[3] & current_size);     \
				current_size <<= 1;                        \
				pass++;                                    \
				stack_pointer--;                           \
				q = stack[stack_pointer].q;                \
				node = stack[stack_pointer].node;          \
			    }                                              \
			    while (continue_up);                           \
			    dst[j] = found_color + s->offset;              \
			    we_found_it = 1;                               \
			}                                                  \
		    } else if (node->contents.quadrants[q]) {              \
	                                                                   \
/*                                                                         \
 * Descend one level                                                       \
 */                                                                        \
			stack[stack_pointer].node = node;                  \
			stack[stack_pointer++].q = q;                      \
			node = node->contents.quadrants[q];                \
		    } else {                                               \
	                                                                   \
/*                                                                         \
 * Found the empty quadrant. Look around                                   \
 */                                                                        \
			mlib_u32 distance = MLIB_U32_MAX;                  \
			mlib_s32 found_color;                              \
			mlib_s32 continue_up;                              \
	                                                                   \
/*                                                                         \
 * As we had come to this level, it is warranted that there are other      \
 * points on this level near the empty quadrant                            \
 */                                                                        \
			do {                                               \
			    mlib_s32 check_corner;                         \
			    mlib_s32 check_neibours[6];                    \
			    mlib_s32 check_far_neibours[4];                \
	                                                                   \
/*                                                                         \
 * Check neibours: quadrants that are different by 2 bits from the         \
 * quadrant, that we are in: 3 - 0 5 - 1 6 - 2 9 - 3 10 - 4 12 - 5         \
 * Far quadrants: different by 3 bits: 7 - 0 11 - 1 13 - 2 14 - 3          \
 */                                                                        \
			    check_neibours[0] = check_neibours[1] =        \
				check_neibours[2] = check_neibours[3] =    \
				check_neibours[4] = check_neibours[5] =    \
				0;                                         \
			    continue_up = 0;                               \
			    if (q & 1) {                                   \
				BINARY_TREE_EXPLORE_LEFT_4(0,              \
				    SOURCE_IMAGE, 0, 1, 3, SUBTRACTION,    \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_EXPLORE_RIGHT_4(0,             \
				    COLOR_MAX, SOURCE_IMAGE, 0, 1, 3,      \
				    SUBTRACTION, SHIFT);                   \
			    }                                              \
			    if (q & 2) {                                   \
				BINARY_TREE_EXPLORE_LEFT_4(1,              \
				    SOURCE_IMAGE, 0, 2, 4, SUBTRACTION,    \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_EXPLORE_RIGHT_4(1,             \
				    COLOR_MAX, SOURCE_IMAGE, 0, 2, 4,      \
				    SUBTRACTION, SHIFT);                   \
			    }                                              \
			    if (q & 4) {                                   \
				BINARY_TREE_EXPLORE_LEFT_4(2,              \
				    SOURCE_IMAGE, 1, 2, 5, SUBTRACTION,    \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_EXPLORE_RIGHT_4(2,             \
				    COLOR_MAX, SOURCE_IMAGE, 1, 2, 5,      \
				    SUBTRACTION, SHIFT);                   \
			    }                                              \
			    if (q & 8) {                                   \
				BINARY_TREE_EXPLORE_LEFT_4(3,              \
				    SOURCE_IMAGE, 3, 4, 5, SUBTRACTION,    \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_EXPLORE_RIGHT_4(3,             \
				    COLOR_MAX, SOURCE_IMAGE, 3, 4, 5,      \
				    SUBTRACTION, SHIFT);                   \
			    }                                              \
			    check_far_neibours[0] =                        \
				check_neibours[0] + check_neibours[1] +    \
				check_neibours[2];                         \
			    check_far_neibours[1] =                        \
				check_neibours[0] + check_neibours[3] +    \
				check_neibours[4];                         \
			    check_far_neibours[2] =                        \
				check_neibours[1] + check_neibours[3] +    \
				check_neibours[5];                         \
			    check_far_neibours[3] =                        \
				check_neibours[2] + check_neibours[4] +    \
				check_neibours[5];                         \
			    check_corner =                                 \
				check_far_neibours[0] +                    \
				check_far_neibours[1] +                    \
				check_far_neibours[2] +                    \
				check_far_neibours[3];                     \
			    if (check_neibours[0] >= 2) {                  \
				mlib_s32 qq = q ^ 3;                       \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_neibours[1] >= 2) {                  \
				mlib_s32 qq = q ^ 5;                       \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_neibours[2] >= 2) {                  \
				mlib_s32 qq = q ^ 6;                       \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_neibours[3] >= 2) {                  \
				mlib_s32 qq = q ^ 9;                       \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_neibours[4] >= 2) {                  \
				mlib_s32 qq = q ^ 10;                      \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_neibours[5] >= 2) {                  \
				mlib_s32 qq = q ^ 12;                      \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_far_neibours[0] >= 3) {              \
				mlib_s32 qq = q ^ 7;                       \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_far_neibours[1] >= 3) {              \
				mlib_s32 qq = q ^ 11;                      \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_far_neibours[2] >= 3) {              \
				mlib_s32 qq = q ^ 13;                      \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_far_neibours[3] >= 3) {              \
				mlib_s32 qq = q ^ 14;                      \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (check_corner >= 4) {                       \
				mlib_s32 qq = q ^ 15;                      \
	                                                                   \
				CHECK_QUADRANT_##SOURCE_IMAGE##_4          \
				    (qq);                                  \
			    }                                              \
			    if (q & 1) {                                   \
				BINARY_TREE_SEARCH_RIGHT(0, COLOR_MAX,     \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_SEARCH_LEFT(0, SHIFT);         \
			    }                                              \
			    if (q & 2) {                                   \
				BINARY_TREE_SEARCH_RIGHT(1, COLOR_MAX,     \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_SEARCH_LEFT(1, SHIFT);         \
			    }                                              \
			    if (q & 4) {                                   \
				BINARY_TREE_SEARCH_RIGHT(2, COLOR_MAX,     \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_SEARCH_LEFT(2, SHIFT);         \
			    }                                              \
			    if (q & 8) {                                   \
				BINARY_TREE_SEARCH_RIGHT(3, COLOR_MAX,     \
				    SHIFT);                                \
			    } else {                                       \
				BINARY_TREE_SEARCH_LEFT(3, SHIFT);         \
			    }                                              \
			    position[0] &= ~(c[0] & current_size);         \
			    position[1] &= ~(c[1] & current_size);         \
			    position[2] &= ~(c[2] & current_size);         \
			    position[3] &= ~(c[3] & current_size);         \
			    current_size <<= 1;                            \
			    pass++;                                        \
			    stack_pointer--;                               \
			    q = stack[stack_pointer].q;                    \
			    node = stack[stack_pointer].node;              \
			}                                                  \
			while (continue_up);                               \
			dst[j] = found_color + s->offset;                  \
			we_found_it = 1;                                   \
		    }                                                      \
		    pass--;                                                \
		}                                                          \
		while (!we_found_it);                                      \
		channels[0] += 4;                                          \
		channels[1] += 4;                                          \
		channels[2] += 4;                                          \
		channels[3] += 4;                                          \
	    }                                                              \
	}

/* *********************************************************** */
#if defined(_NO_LONGLONG)
/* *********************************************************** */

#define	FIND_NEAREST_U8_3_C(SHIFT, STEP)                        \
	mlib_s32 i, k, k_min, min_dist, diff, mask;             \
	mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;        \
	    mlib_s32                                            \
		entries = s->lutlength;                         \
	    mlib_d64 *                                          \
		double_lut = mlib_ImageGetLutDoubleData(s);     \
	    mlib_d64                                            \
		col0,                                           \
		col1,                                           \
		col2;                                           \
	    mlib_d64                                            \
		dist,                                           \
		len0,                                           \
		len1,                                           \
		len2;                                           \
	                                                        \
	for (i = 0; i < length; i++)                            \
	{                                                       \
	col0 = src[STEP * i + SHIFT];                           \
	col1 = src[STEP * i + 1 + SHIFT];                       \
	col2 = src[STEP * i + 2 + SHIFT];                       \
	min_dist = MLIB_S32_MAX;                                \
	k_min = 1;                                              \
	len0 = double_lut[0] - col0;                            \
	len1 = double_lut[1] - col1;                            \
	len2 = double_lut[2] - col2;                            \
	for (k = 1; k <= entries; k++) {                        \
	    dist = len0 * len0;                                 \
	    len0 = double_lut[3 * k] - col0;                    \
	    dist += len1 * len1;                                \
	    len1 = double_lut[3 * k + 1] - col1;                \
	    dist += len2 * len2;                                \
	    len2 = double_lut[3 * k + 2] - col2;                \
	    diff = (mlib_s32)dist - min_dist;                   \
	    mask = diff >> 31;                                  \
	    min_dist += diff & mask;                            \
	    k_min += (k - k_min) & mask;                        \
	}                                                       \
	dst[i] = k_min + offset;                                \
	}

/* *********************************************************** */
#else
/* *********************************************************** */
#define	FIND_NEAREST_U8_3_C(SHIFT, STEP)                        \
	mlib_s32 i, k, k_min, min_dist, diff, mask;             \
	mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;        \
	    mlib_s32                                            \
		entries = s->lutlength;                         \
	    mlib_d64 *                                          \
		double_lut = (mlib_d64 *)mlib_ImageGetLutDoubleData(s);     \
	    mlib_s64                                            \
		col0,                                           \
		col1,                                           \
		col2;                                           \
	    mlib_s64                                            \
		dist,                                           \
		len0,                                           \
		len1,                                           \
		len2;                                           \
	                                                        \
	for (i = 0; i < length; i++)                            \
	{                                                       \
	col0 = src[STEP * i + SHIFT];                           \
	col1 = src[STEP * i + 1 + SHIFT];                       \
	col2 = src[STEP * i + 2 + SHIFT];                       \
	min_dist = MLIB_S32_MAX;                                \
	k_min = 1;                                              \
	len0 = double_lut[0] - col0;                            \
	len1 = double_lut[1] - col1;                            \
	len2 = double_lut[2] - col2;                            \
	for (k = 1; k <= entries; k++) {                        \
	    dist = len0 * len0;                                 \
	    len0 = double_lut[3 * k] - col0;                    \
	    dist += len1 * len1;                                \
	    len1 = double_lut[3 * k + 1] - col1;                \
	    dist += len2 * len2;                                \
	    len2 = double_lut[3 * k + 2] - col2;                \
	    diff = (mlib_s32)dist - min_dist;                   \
	    mask = diff >> 31;                                  \
	    min_dist += diff & mask;                            \
	    k_min += (k - k_min) & mask;                        \
	}                                                       \
	dst[i] = k_min + offset;                                \
	}
/* *********************************************************** */
#endif
/* *********************************************************** */
#if defined(_NO_LONGLONG)
/* *********************************************************** */

#define	FIND_NEAREST_U8_4_C                                     \
	mlib_s32 i, k, k_min, min_dist, diff, mask;             \
	mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;        \
	    mlib_s32                                            \
		entries = s->lutlength;                         \
	    mlib_d64 *                                          \
		double_lut = mlib_ImageGetLutDoubleData(s);     \
	    mlib_d64                                            \
		col0,                                           \
		col1,                                           \
		col2,                                           \
		col3;                                           \
	    mlib_d64                                            \
		dist,                                           \
		len0,                                           \
		len1,                                           \
		len2,                                           \
		len3;                                           \
	                                                        \
	for (i = 0; i < length; i++)                            \
	{                                                       \
	col0 = src[4 * i];                                      \
	col1 = src[4 * i + 1];                                  \
	col2 = src[4 * i + 2];                                  \
	col3 = src[4 * i + 3];                                  \
	min_dist = MLIB_S32_MAX;                                \
	k_min = 1;                                              \
	len0 = double_lut[0] - col0;                            \
	len1 = double_lut[1] - col1;                            \
	len2 = double_lut[2] - col2;                            \
	len3 = double_lut[3] - col3;                            \
	for (k = 1; k <= entries; k++) {                        \
	    dist = len0 * len0;                                 \
	    len0 = double_lut[4 * k] - col0;                    \
	    dist += len1 * len1;                                \
	    len1 = double_lut[4 * k + 1] - col1;                \
	    dist += len2 * len2;                                \
	    len2 = double_lut[4 * k + 2] - col2;                \
	    dist += len3 * len3;                                \
	    len3 = double_lut[4 * k + 3] - col3;                \
	    diff = (mlib_s32)dist - min_dist;                   \
	    mask = diff >> 31;                                  \
	    min_dist += diff & mask;                            \
	    k_min += (k - k_min) & mask;                        \
	}                                                       \
	dst[i] = k_min + offset;                                \
	}

/* *********************************************************** */
#else
/* *********************************************************** */

#define	FIND_NEAREST_U8_4_C                                     \
	mlib_s32 i, k, k_min, min_dist, diff, mask;             \
	mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;        \
	    mlib_s32                                            \
		entries = s->lutlength;                         \
	    mlib_d64 *                                          \
		double_lut = (mlib_d64 *)mlib_ImageGetLutDoubleData(s);     \
	    mlib_s64                                            \
		col0,                                           \
		col1,                                           \
		col2,                                           \
		col3;                                           \
	    mlib_s64                                            \
		dist,                                           \
		len0,                                           \
		len1,                                           \
		len2,                                           \
		len3;                                           \
	                                                        \
	for (i = 0; i < length; i++)                            \
	{                                                       \
	col0 = src[4 * i];                                      \
	col1 = src[4 * i + 1];                                  \
	col2 = src[4 * i + 2];                                  \
	col3 = src[4 * i + 3];                                  \
	min_dist = MLIB_S32_MAX;                                \
	k_min = 1;                                              \
	len0 = double_lut[0] - col0;                            \
	len1 = double_lut[1] - col1;                            \
	len2 = double_lut[2] - col2;                            \
	len3 = double_lut[3] - col3;                            \
	for (k = 1; k <= entries; k++) {                        \
	    dist = len0 * len0;                                 \
	    len0 = double_lut[4 * k] - col0;                    \
	    dist += len1 * len1;                                \
	    len1 = double_lut[4 * k + 1] - col1;                \
	    dist += len2 * len2;                                \
	    len2 = double_lut[4 * k + 2] - col2;                \
	    dist += len3 * len3;                                \
	    len3 = double_lut[4 * k + 3] - col3;                \
	    diff = (mlib_s32)dist - min_dist;                   \
	    mask = diff >> 31;                                  \
	    min_dist += diff & mask;                            \
	    k_min += (k - k_min) & mask;                        \
	}                                                       \
	dst[i] = k_min + offset;                                \
	}
/* *********************************************************** */
#endif
/* *********************************************************** */

#define	FSQR_S16_HI(dsrc)                                            \
	vis_fpadd32(vis_fmuld8ulx16(vis_read_hi(dsrc),               \
	    vis_read_hi(dsrc)), vis_fmuld8sux16(vis_read_hi(dsrc),   \
	    vis_read_hi(dsrc)))

/* *********************************************************** */

#define	FSQR_S16_LO(dsrc)                                            \
	vis_fpadd32(vis_fmuld8ulx16(vis_read_lo(dsrc),               \
	    vis_read_lo(dsrc)), vis_fmuld8sux16(vis_read_lo(dsrc),   \
	    vis_read_lo(dsrc)))

/* *********************************************************** */

#define	FIND_NEAREST_U8_3                                                  \
	{                                                                  \
	    mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3;   \
	    mlib_d64 dcolor, dind, dres, dres1, dpind[1], dpmin[1];        \
	    mlib_d64 done = vis_to_double_dup(1), dmax =                   \
		vis_to_double_dup(MLIB_S32_MAX);                           \
	    mlib_f32 *lut = (mlib_f32 *)mlib_ImageGetLutNormalTable(s);    \
	    mlib_f32 fone = vis_to_float(0x100);                           \
	    mlib_s32 i, k, mask;                                           \
	    mlib_s32 gsr[1];                                               \
	    mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;               \
	    mlib_s32 entries = s->lutlength;                               \
	                                                                   \
	    gsr[0] = vis_read_gsr();                                       \
	    for (i = 0; i <= (length - 2); i += 2) {                       \
		dpsrc = VIS_ALIGNADDR(src, -1);                            \
		src += 6;                                                  \
		dsrc = dpsrc[0];                                           \
		dsrc1 = dpsrc[1];                                          \
		dsrc1 = vis_faligndata(dsrc, dsrc1);                       \
		dsrc = vis_fmul8x16al(vis_read_hi(dsrc1), fone);           \
		VIS_ALIGNADDR(dpsrc, 3);                                   \
		dsrc1 = vis_faligndata(dsrc1, dsrc1);                      \
		dsrc1 = vis_fmul8x16al(vis_read_hi(dsrc1), fone);          \
		dpind[0] = dind = done;                                    \
		dpmin[0] = dmax;                                           \
		dcolor = vis_fmul8x16al(lut[0], fone);                     \
		for (k = 1; k <= entries; k++) {                           \
		    ddist1 = vis_fpsub16(dcolor, dsrc);                    \
		    ddist = FSQR_S16_HI(ddist1);                           \
		    ddist1 = FSQR_S16_LO(ddist1);                          \
		    dres = vis_fpadd32(ddist, ddist1);                     \
		    ddist3 = vis_fpsub16(dcolor, dsrc1);                   \
		    ddist2 = FSQR_S16_HI(ddist3);                          \
		    ddist3 = FSQR_S16_LO(ddist3);                          \
		    dres1 = vis_fpadd32(ddist2, ddist3);                   \
		    dcolor = vis_fmul8x16al(lut[k], fone);                 \
		    dres =                                                 \
			vis_freg_pair(vis_fpadd32s(vis_read_hi(dres),      \
			vis_read_lo(dres)),                                \
			vis_fpadd32s(vis_read_hi(dres1),                   \
			vis_read_lo(dres1)));                              \
		    mask = vis_fcmplt32(dres, dpmin[0]);                   \
		    vis_pst_32(dind, (void *)dpind, mask);                 \
		    dind = vis_fpadd32(dind, done);                        \
		    vis_pst_32(dres, (void *)dpmin, mask);                 \
		}                                                          \
		dst[i] = ((mlib_s32 *)dpind)[0] + offset;                  \
		dst[i + 1] = ((mlib_s32 *)dpind)[1] + offset;              \
	    }                                                              \
	    if (i < length) {                                              \
		dpsrc = VIS_ALIGNADDR(src, -1);                            \
		dsrc = dpsrc[0];                                           \
		dsrc1 = dpsrc[1];                                          \
		dsrc1 = vis_faligndata(dsrc, dsrc1);                       \
		dsrc = vis_fmul8x16al(vis_read_hi(dsrc1), fone);           \
		dpind[0] = dind = done;                                    \
		dpmin[0] = dmax;                                           \
		for (k = 0; k < entries; k++) {                            \
		    dcolor = vis_fmul8x16al(lut[k], fone);                 \
		    ddist1 = vis_fpsub16(dcolor, dsrc);                    \
		    ddist = FSQR_S16_HI(ddist1);                           \
		    ddist1 = FSQR_S16_LO(ddist1);                          \
		    dres = vis_fpadd32(ddist, ddist1);                     \
		    dres =                                                 \
			vis_write_lo(dres,                                 \
			vis_fpadd32s(vis_read_hi(dres),                    \
			vis_read_lo(dres)));                               \
		    mask = vis_fcmplt32(dres, dpmin[0]);                   \
		    vis_pst_32(dind, (void *)dpind, mask);                 \
		    dind = vis_fpadd32(dind, done);                        \
		    vis_pst_32(dres, (void *)dpmin, mask);                 \
		}                                                          \
		dst[i] = ((mlib_s32 *)dpind)[1] + offset;                  \
	    }                                                              \
	    vis_write_gsr(gsr[0]);                                         \
	}

/* *********************************************************** */

#define	FIND_NEAREST_U8_3_IN4                                              \
	{                                                                  \
	    mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3;   \
	    mlib_d64 dcolor, dind, dres, dres1, dpind[1], dpmin[1];        \
	    mlib_d64 done = vis_to_double_dup(1), dmax =                   \
		vis_to_double_dup(MLIB_S32_MAX);                           \
	    mlib_f32 *lut = (mlib_f32 *)mlib_ImageGetLutNormalTable(s);    \
	    mlib_f32 fone = vis_to_float(0x100);                           \
	    mlib_s32 i, k, mask, gsr[1];                                   \
	    mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;               \
	    mlib_s32 entries = s->lutlength;                               \
	                                                                   \
	    gsr[0] = vis_read_gsr();                                       \
	    dpsrc = VIS_ALIGNADDR(src, 0);                                 \
	    for (i = 0; i <= (length - 2); i += 2) {                       \
		dsrc = dpsrc[0];                                           \
		dsrc1 = dpsrc[1];                                          \
		dsrc1 = vis_faligndata(dsrc, dsrc1);                       \
		dpsrc++;                                                   \
		dsrc = vis_fmul8x16al(vis_read_hi(dsrc1), fone);           \
		dsrc1 = vis_fmul8x16al(vis_read_lo(dsrc1), fone);          \
		dpind[0] = dind = done;                                    \
		dpmin[0] = dmax;                                           \
		dcolor = vis_fmul8x16al(lut[0], fone);                     \
		for (k = 1; k <= entries; k++) {                           \
		    ddist1 = vis_fpsub16(dcolor, dsrc);                    \
		    ddist = FSQR_S16_HI(ddist1);                           \
		    ddist1 = FSQR_S16_LO(ddist1);                          \
		    dres = vis_fpadd32(ddist, ddist1);                     \
		    ddist3 = vis_fpsub16(dcolor, dsrc1);                   \
		    ddist2 = FSQR_S16_HI(ddist3);                          \
		    ddist3 = FSQR_S16_LO(ddist3);                          \
		    dres1 = vis_fpadd32(ddist2, ddist3);                   \
		    dcolor = vis_fmul8x16al(lut[k], fone);                 \
		    dres =                                                 \
			vis_freg_pair(vis_fpadd32s(vis_read_hi(dres),      \
			vis_read_lo(dres)),                                \
			vis_fpadd32s(vis_read_hi(dres1),                   \
			vis_read_lo(dres1)));                              \
		    mask = vis_fcmplt32(dres, dpmin[0]);                   \
		    vis_pst_32(dind, (void *)dpind, mask);                 \
		    dind = vis_fpadd32(dind, done);                        \
		    vis_pst_32(dres, (void *)dpmin, mask);                 \
		}                                                          \
		dst[i] = ((mlib_s32 *)dpind)[0] + offset;                  \
		dst[i + 1] = ((mlib_s32 *)dpind)[1] + offset;              \
	    }                                                              \
	    if (i < length) {                                              \
		dsrc = dpsrc[0];                                           \
		dsrc1 = dpsrc[1];                                          \
		dsrc1 = vis_faligndata(dsrc, dsrc1);                       \
		dsrc = vis_fmul8x16al(vis_read_hi(dsrc1), fone);           \
		dpind[0] = dind = done;                                    \
		dpmin[0] = dmax;                                           \
		for (k = 0; k < entries; k++) {                            \
		    dcolor = vis_fmul8x16al(lut[k], fone);                 \
		    ddist1 = vis_fpsub16(dcolor, dsrc);                    \
		    ddist = FSQR_S16_HI(ddist1);                           \
		    ddist1 = FSQR_S16_LO(ddist1);                          \
		    dres = vis_fpadd32(ddist, ddist1);                     \
		    dres =                                                 \
			vis_write_lo(dres,                                 \
			vis_fpadd32s(vis_read_hi(dres),                    \
			vis_read_lo(dres)));                               \
		    mask = vis_fcmplt32(dres, dpmin[0]);                   \
		    vis_pst_32(dind, (void *)dpind, mask);                 \
		    dind = vis_fpadd32(dind, done);                        \
		    vis_pst_32(dres, (void *)dpmin, mask);                 \
		}                                                          \
		dst[i] = ((mlib_s32 *)dpind)[1] + offset;                  \
	    }                                                              \
	    vis_write_gsr(gsr[0]);                                         \
	}

/* *********************************************************** */

#define	FIND_NEAREST_U8_4                                                  \
	{                                                                  \
	    mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3;   \
	    mlib_d64 dcolor, dind, dres, dres1, dpind[1], dpmin[1];        \
	    mlib_d64 done = vis_to_double_dup(1), dmax =                   \
		vis_to_double_dup(MLIB_S32_MAX);                           \
	    mlib_f32 *lut = (mlib_f32 *)mlib_ImageGetLutNormalTable(s);    \
	    mlib_f32 fone = vis_to_float(0x100);                           \
	    mlib_s32 i, k, mask, gsr[1];                                   \
	    mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;               \
	    mlib_s32 entries = s->lutlength;                               \
	                                                                   \
	    gsr[0] = vis_read_gsr();                                       \
	    dpsrc = VIS_ALIGNADDR(src, 0);                                 \
	    for (i = 0; i <= (length - 2); i += 2) {                       \
		dsrc = dpsrc[0];                                           \
		dsrc1 = dpsrc[1];                                          \
		dsrc1 = vis_faligndata(dsrc, dsrc1);                       \
		dpsrc++;                                                   \
		dsrc = vis_fmul8x16al(vis_read_hi(dsrc1), fone);           \
		dsrc1 = vis_fmul8x16al(vis_read_lo(dsrc1), fone);          \
		dpind[0] = dind = done;                                    \
		dpmin[0] = dmax;                                           \
		dcolor = vis_fmul8x16al(lut[0], fone);                     \
		for (k = 1; k <= entries; k++) {                           \
		    ddist1 = vis_fpsub16(dcolor, dsrc);                    \
		    ddist = FSQR_S16_HI(ddist1);                           \
		    ddist1 = FSQR_S16_LO(ddist1);                          \
		    dres = vis_fpadd32(ddist, ddist1);                     \
		    ddist3 = vis_fpsub16(dcolor, dsrc1);                   \
		    ddist2 = FSQR_S16_HI(ddist3);                          \
		    ddist3 = FSQR_S16_LO(ddist3);                          \
		    dres1 = vis_fpadd32(ddist2, ddist3);                   \
		    dcolor = vis_fmul8x16al(lut[k], fone);                 \
		    dres =                                                 \
			vis_freg_pair(vis_fpadd32s(vis_read_hi(dres),      \
			vis_read_lo(dres)),                                \
			vis_fpadd32s(vis_read_hi(dres1),                   \
			vis_read_lo(dres1)));                              \
		    mask = vis_fcmplt32(dres, dpmin[0]);                   \
		    vis_pst_32(dind, (void *)dpind, mask);                 \
		    dind = vis_fpadd32(dind, done);                        \
		    vis_pst_32(dres, (void *)dpmin, mask);                 \
		}                                                          \
		dst[i] = ((mlib_s32 *)dpind)[0] + offset;                  \
		dst[i + 1] = ((mlib_s32 *)dpind)[1] + offset;              \
	    }                                                              \
	    if (i < length) {                                              \
		dsrc = dpsrc[0];                                           \
		dsrc1 = dpsrc[1];                                          \
		dsrc1 = vis_faligndata(dsrc, dsrc1);                       \
		dsrc = vis_fmul8x16al(vis_read_hi(dsrc1), fone);           \
		dpind[0] = dind = done;                                    \
		dpmin[0] = dmax;                                           \
		for (k = 0; k < entries; k++) {                            \
		    dcolor = vis_fmul8x16al(lut[k], fone);                 \
		    ddist1 = vis_fpsub16(dcolor, dsrc);                    \
		    ddist = FSQR_S16_HI(ddist1);                           \
		    ddist1 = FSQR_S16_LO(ddist1);                          \
		    dres = vis_fpadd32(ddist, ddist1);                     \
		    dres =                                                 \
			vis_write_lo(dres,                                 \
			vis_fpadd32s(vis_read_hi(dres),                    \
			vis_read_lo(dres)));                               \
		    mask = vis_fcmplt32(dres, dpmin[0]);                   \
		    vis_pst_32(dind, (void *)dpind, mask);                 \
		    dind = vis_fpadd32(dind, done);                        \
		    vis_pst_32(dres, (void *)dpmin, mask);                 \
		}                                                          \
		dst[i] = ((mlib_s32 *)dpind)[1] + offset;                  \
	    }                                                              \
	    vis_write_gsr(gsr[0]);                                         \
	}

/* *********************************************************** */
#if defined(_NO_LONGLONG)
/* *********************************************************** */

#define	FIND_NEAREST_S16_3(SHIFT, STEP)                         \
	mlib_s32 i, k, k_min, min_dist, diff, mask;             \
	mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;        \
	    mlib_s32                                            \
		entries = s->lutlength;                         \
	    mlib_d64 *                                          \
		double_lut = mlib_ImageGetLutDoubleData(s);     \
	    mlib_d64                                            \
		col0,                                           \
		col1,                                           \
		col2;                                           \
	    mlib_d64                                            \
		dist,                                           \
		len0,                                           \
		len1,                                           \
		len2;                                           \
	                                                        \
	for (i = 0; i < length; i++)                            \
	{                                                       \
	col0 = src[STEP * i + SHIFT];                           \
	col1 = src[STEP * i + 1 + SHIFT];                       \
	col2 = src[STEP * i + 2 + SHIFT];                       \
	min_dist = MLIB_S32_MAX;                                \
	k_min = 1;                                              \
	len0 = double_lut[0] - col0;                            \
	len1 = double_lut[1] - col1;                            \
	len2 = double_lut[2] - col2;                            \
	for (k = 1; k <= entries; k++) {                        \
	    dist = len0 * len0;                                 \
	    len0 = double_lut[3 * k] - col0;                    \
	    dist += len1 * len1;                                \
	    len1 = double_lut[3 * k + 1] - col1;                \
	    dist += len2 * len2;                                \
	    len2 = double_lut[3 * k + 2] - col2;                \
	    diff = (mlib_s32)(dist * 0.125) - min_dist;         \
	    mask = diff >> 31;                                  \
	    min_dist += diff & mask;                            \
	    k_min += (k - k_min) & mask;                        \
	}                                                       \
	dst[i] = k_min + offset;                                \
	}

/* *********************************************************** */
#else
/* *********************************************************** */

#define	FIND_NEAREST_S16_3(SHIFT, STEP)                         \
	mlib_s32 i, k, k_min, min_dist, diff, mask;             \
	mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;        \
	    mlib_s32                                            \
		entries = s->lutlength;                         \
	    mlib_d64 *                                          \
		double_lut = (mlib_d64 *)mlib_ImageGetLutDoubleData(s);     \
	    mlib_s64                                            \
		col0,                                           \
		col1,                                           \
		col2;                                           \
	    mlib_s64                                            \
		dist,                                           \
		len0,                                           \
		len1,                                           \
		len2;                                           \
	                                                        \
	for (i = 0; i < length; i++)                            \
	{                                                       \
	col0 = src[STEP * i + SHIFT];                           \
	col1 = src[STEP * i + 1 + SHIFT];                       \
	col2 = src[STEP * i + 2 + SHIFT];                       \
	min_dist = MLIB_S32_MAX;                                \
	k_min = 1;                                              \
	len0 = double_lut[0] - col0;                            \
	len1 = double_lut[1] - col1;                            \
	len2 = double_lut[2] - col2;                            \
	for (k = 1; k <= entries; k++) {                        \
	    dist = len0 * len0;                                 \
	    len0 = double_lut[3 * k] - col0;                    \
	    dist += len1 * len1;                                \
	    len1 = double_lut[3 * k + 1] - col1;                \
	    dist += len2 * len2;                                \
	    len2 = double_lut[3 * k + 2] - col2;                \
	    diff = (mlib_s32)(dist * 0.125) - min_dist;         \
	    mask = diff >> 31;                                  \
	    min_dist += diff & mask;                            \
	    k_min += (k - k_min) & mask;                        \
	}                                                       \
	dst[i] = k_min + offset;                                \
	}

/* *********************************************************** */
#endif
/* *********************************************************** */
#if defined(_NO_LONGLONG)
/* *********************************************************** */

#define	FIND_NEAREST_S16_4                                      \
	mlib_s32 i, k, k_min, min_dist, diff, mask;             \
	mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;        \
	    mlib_s32                                            \
		entries = s->lutlength;                         \
	    mlib_d64 *                                          \
		double_lut = mlib_ImageGetLutDoubleData(s);     \
	    mlib_d64                                            \
		col0,                                           \
		col1,                                           \
		col2,                                           \
		col3;                                           \
	    mlib_d64                                            \
		dist,                                           \
		len0,                                           \
		len1,                                           \
		len2,                                           \
		len3;                                           \
	                                                        \
	for (i = 0; i < length; i++)                            \
	{                                                       \
	col0 = src[4 * i];                                      \
	col1 = src[4 * i + 1];                                  \
	col2 = src[4 * i + 2];                                  \
	col3 = src[4 * i + 3];                                  \
	min_dist = MLIB_S32_MAX;                                \
	k_min = 1;                                              \
	len0 = double_lut[0] - col0;                            \
	len1 = double_lut[1] - col1;                            \
	len2 = double_lut[2] - col2;                            \
	len3 = double_lut[3] - col3;                            \
	for (k = 1; k <= entries; k++) {                        \
	    dist = len0 * len0;                                 \
	    len0 = double_lut[4 * k] - col0;                    \
	    dist += len1 * len1;                                \
	    len1 = double_lut[4 * k + 1] - col1;                \
	    dist += len2 * len2;                                \
	    len2 = double_lut[4 * k + 2] - col2;                \
	    dist += len3 * len3;                                \
	    len3 = double_lut[4 * k + 3] - col3;                \
	    diff = (mlib_s32)(dist * 0.125) - min_dist;         \
	    mask = diff >> 31;                                  \
	    min_dist += diff & mask;                            \
	    k_min += (k - k_min) & mask;                        \
	}                                                       \
	dst[i] = k_min + offset;                                \
	}

/* *********************************************************** */
#else
/* *********************************************************** */

#define	FIND_NEAREST_S16_4                                      \
	mlib_s32 i, k, k_min, min_dist, diff, mask;             \
	mlib_s32 offset = mlib_ImageGetLutOffset(s) - 1;        \
	    mlib_s32                                            \
		entries = s->lutlength;                         \
	    mlib_d64 *                                          \
		double_lut = (mlib_d64 *)mlib_ImageGetLutDoubleData(s);     \
	    mlib_s64                                            \
		col0,                                           \
		col1,                                           \
		col2,                                           \
		col3;                                           \
	    mlib_s64                                            \
		dist,                                           \
		len0,                                           \
		len1,                                           \
		len2,                                           \
		len3;                                           \
	                                                        \
	for (i = 0; i < length; i++)                            \
	{                                                       \
	col0 = src[4 * i];                                      \
	col1 = src[4 * i + 1];                                  \
	col2 = src[4 * i + 2];                                  \
	col3 = src[4 * i + 3];                                  \
	min_dist = MLIB_S32_MAX;                                \
	k_min = 1;                                              \
	len0 = double_lut[0] - col0;                            \
	len1 = double_lut[1] - col1;                            \
	len2 = double_lut[2] - col2;                            \
	len3 = double_lut[3] - col3;                            \
	for (k = 1; k <= entries; k++) {                        \
	    dist = len0 * len0;                                 \
	    len0 = double_lut[4 * k] - col0;                    \
	    dist += len1 * len1;                                \
	    len1 = double_lut[4 * k + 1] - col1;                \
	    dist += len2 * len2;                                \
	    len2 = double_lut[4 * k + 2] - col2;                \
	    dist += len3 * len3;                                \
	    len3 = double_lut[4 * k + 3] - col3;                \
	    diff = (mlib_s32)(dist * 0.125) - min_dist;         \
	    mask = diff >> 31;                                  \
	    min_dist += diff & mask;                            \
	    k_min += (k - k_min) & mask;                        \
	}                                                       \
	dst[i] = k_min + offset;                                \
	}
/* *********************************************************** */
#endif
/* *********************************************************** */

mlib_status
__mlib_ImageColorTrue2Index(
    mlib_image *dst,
    const mlib_image *src,
    const void *colormap)
{
	mlib_s32 y, width, height, sstride, dstride, schann;
	mlib_colormap *s = (mlib_colormap *) colormap;
	mlib_s32 channels;
	mlib_type stype, dtype;

	MLIB_IMAGE_CHECK(src);
	MLIB_IMAGE_CHECK(dst);
	MLIB_IMAGE_SIZE_EQUAL(src, dst);
	MLIB_IMAGE_HAVE_CHAN(dst, 1);

	if (!colormap)
		return (MLIB_NULLPOINTER);

	channels = s->channels;
	stype = mlib_ImageGetType(src);
	dtype = mlib_ImageGetType(dst);
	width = mlib_ImageGetWidth(src);
	height = mlib_ImageGetHeight(src);
	sstride = mlib_ImageGetStride(src);
	dstride = mlib_ImageGetStride(dst);
	schann = mlib_ImageGetChannels(src);

	if (stype != s->intype || dtype != s->outtype)
		return (MLIB_FAILURE);

	if (channels != schann)
		return (MLIB_FAILURE);

	switch (stype) {
	case MLIB_BYTE:
	    {
		    mlib_u8 *sdata = mlib_ImageGetData(src);

		    switch (dtype) {
		    case MLIB_BYTE:
			{
				mlib_u8 *ddata = mlib_ImageGetData(dst);

				switch (channels) {
				case 3:
				    {
					    MAIN_COLORTRUE2INDEX_LOOP(U8, U8,
						3);
					    return (MLIB_SUCCESS);
				    }

				case 4:
				    {
					    MAIN_COLORTRUE2INDEX_LOOP(U8, U8,
						4);
					    return (MLIB_SUCCESS);
				    }

				default:
					return (MLIB_FAILURE);
				}
			}

		    case MLIB_SHORT:
			{
				mlib_s16 *ddata = mlib_ImageGetData(dst);

				dstride /= 2;
				switch (channels) {
				case 3:
				    {
					    MAIN_COLORTRUE2INDEX_LOOP(U8, S16,
						3);
					    return (MLIB_SUCCESS);
				    }

				case 4:
				    {
					    MAIN_COLORTRUE2INDEX_LOOP(U8, S16,
						4);
					    return (MLIB_SUCCESS);
				    }

				default:
					return (MLIB_FAILURE);
				}
			}
		    default:
			return (MLIB_FAILURE);
		    }
	    }

	case MLIB_SHORT:
	    {
		    mlib_s16 *sdata = mlib_ImageGetData(src);

		    sstride /= 2;
		    switch (dtype) {
		    case MLIB_BYTE:
			{
				mlib_u8 *ddata = mlib_ImageGetData(dst);

				switch (channels) {
				case 3:
				    {
					    MAIN_COLORTRUE2INDEX_LOOP(S16, U8,
						3);
					    return (MLIB_SUCCESS);
				    }

				case 4:
				    {
					    MAIN_COLORTRUE2INDEX_LOOP(S16, U8,
						4);
					    return (MLIB_SUCCESS);
				    }

				default:
					return (MLIB_FAILURE);
				}
			}

		    case MLIB_SHORT:
			{
				mlib_s16 *ddata = mlib_ImageGetData(dst);

				dstride /= 2;
				switch (channels) {
				case 3:
				    {
					    MAIN_COLORTRUE2INDEX_LOOP(S16, S16,
						3);
					    return (MLIB_SUCCESS);
				    }

				case 4:
				    {
					    MAIN_COLORTRUE2INDEX_LOOP(S16, S16,
						4);
					    return (MLIB_SUCCESS);
				    }

				default:
					return (MLIB_FAILURE);
				}
			}
		    default:
			return (MLIB_FAILURE);
		    }
	    }

	default:
		return (MLIB_FAILURE);
	}
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_U8_3(
    struct lut_node_3 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    mlib_u32 c0,
    mlib_u32 c1,
    mlib_u32 c2,
    const mlib_u8 **base)
{
	mlib_s32 i;

	for (i = 0; i < 8; i++) {

		if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
			mlib_s32 newindex = node->contents.index[i];
			mlib_u32 newpalc0, newpalc1, newpalc2;
			mlib_u32 newdistance;

			newpalc0 = base[0][newindex];
			newpalc1 = base[1][newindex];
			newpalc2 = base[2][newindex];
			newdistance =
			    FIND_DISTANCE_3(c0, newpalc0, c1, newpalc1, c2,
			    newpalc2, 0);

			if (distance > newdistance) {
				*found_color = newindex;
				distance = newdistance;
			}
		} else if (node->contents.quadrants[i])
			distance =
			    mlib_search_quadrant_U8_3(node->contents.
			    quadrants[i], distance, found_color, c0, c1, c2,
			    base);
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_part_to_left_U8_3(
    struct lut_node_3 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    const mlib_u32 *c,
    const mlib_u8 **base,
    mlib_u32 position,
    mlib_s32 pass,
    mlib_s32 dir_bit)
{
	mlib_u32 current_size = 1 << pass;
	mlib_s32 i;
	static mlib_s32 opposite_quadrants[3][4] = {
		{0, 2, 4, 6},
		{0, 1, 4, 5},
		{0, 1, 2, 3}
	};

/*
 * Search only quadrant's half until it is necessary to check the
 * whole quadrant
 */

/* Search half of quadrant */
	if (distance <
	    (position + current_size - c[dir_bit]) * (position + current_size -
	    c[dir_bit])) {
		for (i = 0; i < 4; i++) {
			mlib_s32 qq = opposite_quadrants[dir_bit][i];

			if (node->tag & (1 << qq)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[qq];
				mlib_u32 newpalc0, newpalc1, newpalc2;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex];
				newpalc1 = base[1][newindex];
				newpalc2 = base[2][newindex];
				newdistance =
				    FIND_DISTANCE_3(c[0], newpalc0, c[1],
				    newpalc1, c[2], newpalc2, 0);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[qq])
				distance =
				    mlib_search_quadrant_part_to_left_U8_3
				    (node->contents.quadrants[qq], distance,
				    found_color, c, base, position, pass - 1,
				    dir_bit);
		}
	} else {
/* Search whole quadrant */

		mlib_s32 mask = 1 << dir_bit;

		for (i = 0; i < 8; i++) {

			if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[i];
				mlib_u32 newpalc0, newpalc1, newpalc2;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex];
				newpalc1 = base[1][newindex];
				newpalc2 = base[2][newindex];
				newdistance =
				    FIND_DISTANCE_3(c[0], newpalc0, c[1],
				    newpalc1, c[2], newpalc2, 0);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[i]) {

				if (i & mask)
/* This quadrant may require partial checking */
					distance =
					    FUNC_NAME(part_to_left_U8_3)
					    (node->contents.quadrants[i],
					    distance, found_color, c, base,
					    position + current_size, pass - 1,
					    dir_bit);
				else
/* Here we should check all */
					distance =
					    mlib_search_quadrant_U8_3(node->
					    contents.quadrants[i], distance,
					    found_color, c[0], c[1], c[2],
					    base);
			}
		}
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_part_to_right_U8_3(
    struct lut_node_3 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    const mlib_u32 *c,
    const mlib_u8 **base,
    mlib_u32 position,
    mlib_s32 pass,
    mlib_s32 dir_bit)
{
	mlib_u32 current_size = 1 << pass;
	mlib_s32 i;
	static mlib_s32 opposite_quadrants[3][4] = {
		{1, 3, 5, 7},
		{2, 3, 6, 7},
		{4, 5, 6, 7}
	};

/*
 * Search only quadrant's half until it is necessary to check the
 * whole quadrant
 */

/* Search half of quadrant */
	if (distance <=
	    (c[dir_bit] - position - current_size) * (c[dir_bit] - position -
	    current_size)) {
		for (i = 0; i < 4; i++) {
			mlib_s32 qq = opposite_quadrants[dir_bit][i];

			if (node->tag & (1 << qq)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[qq];
				mlib_u32 newpalc0, newpalc1, newpalc2;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex];
				newpalc1 = base[1][newindex];
				newpalc2 = base[2][newindex];
				newdistance =
				    FIND_DISTANCE_3(c[0], newpalc0, c[1],
				    newpalc1, c[2], newpalc2, 0);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[qq])
				distance =
				    mlib_search_quadrant_part_to_right_U8_3
				    (node->contents.quadrants[qq], distance,
				    found_color, c, base,
				    position + current_size, pass - 1, dir_bit);
		}
	} else {
/* Search whole quadrant */

		mlib_s32 mask = 1 << dir_bit;

		for (i = 0; i < 8; i++) {

			if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[i];
				mlib_u32 newpalc0, newpalc1, newpalc2;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex];
				newpalc1 = base[1][newindex];
				newpalc2 = base[2][newindex];
				newdistance =
				    FIND_DISTANCE_3(c[0], newpalc0, c[1],
				    newpalc1, c[2], newpalc2, 0);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[i]) {

				if (i & mask)
/* Here we should check all */
					distance =
					    mlib_search_quadrant_U8_3(node->
					    contents.quadrants[i], distance,
					    found_color, c[0], c[1], c[2],
					    base);
				else
/* This quadrant may require partial checking */
					distance =
					    FUNC_NAME(part_to_right_U8_3)
					    (node->contents.quadrants[i],
					    distance, found_color, c, base,
					    position, pass - 1, dir_bit);
			}
		}
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_S16_3(
    struct lut_node_3 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    mlib_u32 c0,
    mlib_u32 c1,
    mlib_u32 c2,
    const mlib_s16 **base)
{
	mlib_s32 i;

	for (i = 0; i < 8; i++) {

		if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
			mlib_s32 newindex = node->contents.index[i];
			mlib_u32 newpalc0, newpalc1, newpalc2;
			mlib_u32 newdistance;

			newpalc0 = base[0][newindex] - MLIB_S16_MIN;
			newpalc1 = base[1][newindex] - MLIB_S16_MIN;
			newpalc2 = base[2][newindex] - MLIB_S16_MIN;
			newdistance =
			    FIND_DISTANCE_3(c0, newpalc0, c1, newpalc1, c2,
			    newpalc2, 2);

			if (distance > newdistance) {
				*found_color = newindex;
				distance = newdistance;
			}
		} else if (node->contents.quadrants[i])
			distance =
			    mlib_search_quadrant_S16_3(node->contents.
			    quadrants[i], distance, found_color, c0, c1, c2,
			    base);
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_part_to_left_S16_3(
    struct lut_node_3 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    const mlib_u32 *c,
    const mlib_s16 **base,
    mlib_u32 position,
    mlib_s32 pass,
    mlib_s32 dir_bit)
{
	mlib_u32 current_size = 1 << pass;
	mlib_s32 i;
	static mlib_s32 opposite_quadrants[3][4] = {
		{0, 2, 4, 6},
		{0, 1, 4, 5},
		{0, 1, 2, 3}
	};

/*
 * Search only quadrant's half until it is necessary to check the
 * whole quadrant
 */

/* Search half of quadrant */
	if (distance <
	    (((position + current_size - c[dir_bit]) * (position +
	    current_size - c[dir_bit])) >> 2)) {
		for (i = 0; i < 4; i++) {
			mlib_s32 qq = opposite_quadrants[dir_bit][i];

			if (node->tag & (1 << qq)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[qq];
				mlib_u32 newpalc0, newpalc1, newpalc2;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex] - MLIB_S16_MIN;
				newpalc1 = base[1][newindex] - MLIB_S16_MIN;
				newpalc2 = base[2][newindex] - MLIB_S16_MIN;
				newdistance =
				    FIND_DISTANCE_3(c[0], newpalc0, c[1],
				    newpalc1, c[2], newpalc2, 2);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[qq])
				distance =
				    mlib_search_quadrant_part_to_left_S16_3
				    (node->contents.quadrants[qq], distance,
				    found_color, c, base, position, pass - 1,
				    dir_bit);
		}
	} else {
/* Search whole quadrant */

		mlib_s32 mask = 1 << dir_bit;

		for (i = 0; i < 8; i++) {

			if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[i];
				mlib_u32 newpalc0, newpalc1, newpalc2;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex] - MLIB_S16_MIN;
				newpalc1 = base[1][newindex] - MLIB_S16_MIN;
				newpalc2 = base[2][newindex] - MLIB_S16_MIN;
				newdistance =
				    FIND_DISTANCE_3(c[0], newpalc0, c[1],
				    newpalc1, c[2], newpalc2, 2);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[i]) {

				if (i & mask)
/* This quadrant may require partial checking */
					distance =
					    FUNC_NAME(part_to_left_S16_3)
					    (node->contents.quadrants[i],
					    distance, found_color, c, base,
					    position + current_size, pass - 1,
					    dir_bit);
				else
/* Here we should check all */
					distance =
					    mlib_search_quadrant_S16_3(node->
					    contents.quadrants[i], distance,
					    found_color, c[0], c[1], c[2],
					    base);
			}
		}
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_part_to_right_S16_3(
    struct lut_node_3 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    const mlib_u32 *c,
    const mlib_s16 **base,
    mlib_u32 position,
    mlib_s32 pass,
    mlib_s32 dir_bit)
{
	mlib_u32 current_size = 1 << pass;
	mlib_s32 i;
	static mlib_s32 opposite_quadrants[3][4] = {
		{1, 3, 5, 7},
		{2, 3, 6, 7},
		{4, 5, 6, 7}
	};

/*
 * Search only quadrant's half until it is necessary to check the
 * whole quadrant
 */

/* Search half of quadrant */
	if (distance <=
	    (((c[dir_bit] - position - current_size) * (c[dir_bit] - position -
	    current_size)) >> 2)) {
		for (i = 0; i < 4; i++) {
			mlib_s32 qq = opposite_quadrants[dir_bit][i];

			if (node->tag & (1 << qq)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[qq];
				mlib_u32 newpalc0, newpalc1, newpalc2;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex] - MLIB_S16_MIN;
				newpalc1 = base[1][newindex] - MLIB_S16_MIN;
				newpalc2 = base[2][newindex] - MLIB_S16_MIN;
				newdistance =
				    FIND_DISTANCE_3(c[0], newpalc0, c[1],
				    newpalc1, c[2], newpalc2, 2);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[qq])
				distance =
				    mlib_search_quadrant_part_to_right_S16_3
				    (node->contents.quadrants[qq], distance,
				    found_color, c, base,
				    position + current_size, pass - 1, dir_bit);
		}
	} else {
/* Search whole quadrant */

		mlib_s32 mask = 1 << dir_bit;

		for (i = 0; i < 8; i++) {

			if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[i];
				mlib_u32 newpalc0, newpalc1, newpalc2;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex] - MLIB_S16_MIN;
				newpalc1 = base[1][newindex] - MLIB_S16_MIN;
				newpalc2 = base[2][newindex] - MLIB_S16_MIN;
				newdistance =
				    FIND_DISTANCE_3(c[0], newpalc0, c[1],
				    newpalc1, c[2], newpalc2, 2);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[i]) {

				if (i & mask)
/* Here we should check all */
					distance =
					    mlib_search_quadrant_S16_3(node->
					    contents.quadrants[i], distance,
					    found_color, c[0], c[1], c[2],
					    base);
				else
/* This quadrant may require partial checking */
					distance =
					    FUNC_NAME(part_to_right_S16_3)
					    (node->contents.quadrants[i],
					    distance, found_color, c, base,
					    position, pass - 1, dir_bit);
			}
		}
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_U8_4(
    struct lut_node_4 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    mlib_u32 c0,
    mlib_u32 c1,
    mlib_u32 c2,
    mlib_u32 c3,
    const mlib_u8 **base)
{
	mlib_s32 i;

	for (i = 0; i < 16; i++) {

		if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
			mlib_s32 newindex = node->contents.index[i];
			mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
			mlib_u32 newdistance;

			newpalc0 = base[0][newindex];
			newpalc1 = base[1][newindex];
			newpalc2 = base[2][newindex];
			newpalc3 = base[3][newindex];
			newdistance = FIND_DISTANCE_4(c0, newpalc0,
			    c1, newpalc1, c2, newpalc2, c3, newpalc3, 0);

			if (distance > newdistance) {
				*found_color = newindex;
				distance = newdistance;
			}
		} else if (node->contents.quadrants[i])
			distance =
			    mlib_search_quadrant_U8_4(node->contents.
			    quadrants[i], distance, found_color, c0, c1, c2, c3,
			    base);
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_part_to_left_U8_4(
    struct lut_node_4 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    const mlib_u32 *c,
    const mlib_u8 **base,
    mlib_u32 position,
    mlib_s32 pass,
    mlib_s32 dir_bit)
{
	mlib_u32 current_size = 1 << pass;
	mlib_s32 i;
	static mlib_s32 opposite_quadrants[4][8] = {
		{0, 2, 4, 6, 8, 10, 12, 14},
		{0, 1, 4, 5, 8, 9, 12, 13},
		{0, 1, 2, 3, 8, 9, 10, 11},
		{0, 1, 2, 3, 4, 5, 6, 7}
	};

/*
 * Search only quadrant's half until it is necessary to check the
 * whole quadrant
 */

/* Search half of quadrant */
	if (distance <
	    (position + current_size - c[dir_bit]) * (position + current_size -
	    c[dir_bit])) {
		for (i = 0; i < 8; i++) {
			mlib_s32 qq = opposite_quadrants[dir_bit][i];

			if (node->tag & (1 << qq)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[qq];
				mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex];
				newpalc1 = base[1][newindex];
				newpalc2 = base[2][newindex];
				newpalc3 = base[3][newindex];
				newdistance = FIND_DISTANCE_4(c[0], newpalc0,
				    c[1], newpalc1, c[2], newpalc2, c[3],
				    newpalc3, 0);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[qq])
				distance =
				    mlib_search_quadrant_part_to_left_U8_4
				    (node->contents.quadrants[qq], distance,
				    found_color, c, base, position, pass - 1,
				    dir_bit);
		}
	} else {
/* Search whole quadrant */

		mlib_s32 mask = 1 << dir_bit;

		for (i = 0; i < 16; i++) {

			if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[i];
				mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex];
				newpalc1 = base[1][newindex];
				newpalc2 = base[2][newindex];
				newpalc3 = base[3][newindex];
				newdistance = FIND_DISTANCE_4(c[0], newpalc0,
				    c[1], newpalc1, c[2], newpalc2, c[3],
				    newpalc3, 0);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[i]) {

				if (i & mask)
/* This quadrant may require partial checking */
					distance =
					    FUNC_NAME(part_to_left_U8_4)
					    (node->contents.quadrants[i],
					    distance, found_color, c, base,
					    position + current_size, pass - 1,
					    dir_bit);
				else
/* Here we should check all */
					distance =
					    mlib_search_quadrant_U8_4(node->
					    contents.quadrants[i], distance,
					    found_color, c[0], c[1], c[2], c[3],
					    base);
			}
		}
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_part_to_right_U8_4(
    struct lut_node_4 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    const mlib_u32 *c,
    const mlib_u8 **base,
    mlib_u32 position,
    mlib_s32 pass,
    mlib_s32 dir_bit)
{
	mlib_u32 current_size = 1 << pass;
	mlib_s32 i;
	static mlib_s32 opposite_quadrants[4][8] = {
		{1, 3, 5, 7, 9, 11, 13, 15},
		{2, 3, 6, 7, 10, 11, 14, 15},
		{4, 5, 6, 7, 12, 13, 14, 15},
		{8, 9, 10, 11, 12, 13, 14, 15}
	};

/*
 * Search only quadrant's half until it is necessary to check the
 * whole quadrant
 */

/* Search half of quadrant */
	if (distance <=
	    (c[dir_bit] - position - current_size) * (c[dir_bit] - position -
	    current_size)) {
		for (i = 0; i < 8; i++) {
			mlib_s32 qq = opposite_quadrants[dir_bit][i];

			if (node->tag & (1 << qq)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[qq];
				mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex];
				newpalc1 = base[1][newindex];
				newpalc2 = base[2][newindex];
				newpalc3 = base[3][newindex];
				newdistance = FIND_DISTANCE_4(c[0], newpalc0,
				    c[1], newpalc1, c[2], newpalc2, c[3],
				    newpalc3, 0);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[qq])
				distance =
				    mlib_search_quadrant_part_to_right_U8_4
				    (node->contents.quadrants[qq], distance,
				    found_color, c, base,
				    position + current_size, pass - 1, dir_bit);
		}
	} else {
/* Search whole quadrant */

		mlib_s32 mask = 1 << dir_bit;

		for (i = 0; i < 16; i++) {

			if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[i];
				mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex];
				newpalc1 = base[1][newindex];
				newpalc2 = base[2][newindex];
				newpalc3 = base[3][newindex];
				newdistance = FIND_DISTANCE_4(c[0], newpalc0,
				    c[1], newpalc1, c[2], newpalc2, c[3],
				    newpalc3, 0);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[i]) {

				if (i & mask)
/* Here we should check all */
					distance =
					    mlib_search_quadrant_U8_4(node->
					    contents.quadrants[i], distance,
					    found_color, c[0], c[1], c[2], c[3],
					    base);
				else
/* This quadrant may require partial checking */
					distance =
					    FUNC_NAME(part_to_right_U8_4)
					    (node->contents.quadrants[i],
					    distance, found_color, c, base,
					    position, pass - 1, dir_bit);
			}
		}
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_S16_4(
    struct lut_node_4 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    mlib_u32 c0,
    mlib_u32 c1,
    mlib_u32 c2,
    mlib_u32 c3,
    const mlib_s16 **base)
{
	mlib_s32 i;

	for (i = 0; i < 16; i++) {

		if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
			mlib_s32 newindex = node->contents.index[i];
			mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
			mlib_u32 newdistance;

			newpalc0 = base[0][newindex] - MLIB_S16_MIN;
			newpalc1 = base[1][newindex] - MLIB_S16_MIN;
			newpalc2 = base[2][newindex] - MLIB_S16_MIN;
			newpalc3 = base[3][newindex] - MLIB_S16_MIN;
			newdistance = FIND_DISTANCE_4(c0, newpalc0,
			    c1, newpalc1, c2, newpalc2, c3, newpalc3, 2);

			if (distance > newdistance) {
				*found_color = newindex;
				distance = newdistance;
			}
		} else if (node->contents.quadrants[i])
			distance =
			    mlib_search_quadrant_S16_4(node->contents.
			    quadrants[i], distance, found_color, c0, c1, c2, c3,
			    base);
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_part_to_left_S16_4(
    struct lut_node_4 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    const mlib_u32 *c,
    const mlib_s16 **base,
    mlib_u32 position,
    mlib_s32 pass,
    mlib_s32 dir_bit)
{
	mlib_u32 current_size = 1 << pass;
	mlib_s32 i;
	static mlib_s32 opposite_quadrants[4][8] = {
		{0, 2, 4, 6, 8, 10, 12, 14},
		{0, 1, 4, 5, 8, 9, 12, 13},
		{0, 1, 2, 3, 8, 9, 10, 11},
		{0, 1, 2, 3, 4, 5, 6, 7}
	};

/*
 * Search only quadrant's half until it is necessary to check the
 * whole quadrant
 */

/* Search half of quadrant */
	if (distance <
	    (((position + current_size - c[dir_bit]) * (position +
	    current_size - c[dir_bit])) >> 2)) {
		for (i = 0; i < 8; i++) {
			mlib_s32 qq = opposite_quadrants[dir_bit][i];

			if (node->tag & (1 << qq)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[qq];
				mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex] - MLIB_S16_MIN;
				newpalc1 = base[1][newindex] - MLIB_S16_MIN;
				newpalc2 = base[2][newindex] - MLIB_S16_MIN;
				newpalc3 = base[3][newindex] - MLIB_S16_MIN;
				newdistance = FIND_DISTANCE_4(c[0], newpalc0,
				    c[1], newpalc1, c[2], newpalc2, c[3],
				    newpalc3, 2);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[qq])
				distance =
				    mlib_search_quadrant_part_to_left_S16_4
				    (node->contents.quadrants[qq], distance,
				    found_color, c, base, position, pass - 1,
				    dir_bit);
		}
	} else {
/* Search whole quadrant */

		mlib_s32 mask = 1 << dir_bit;

		for (i = 0; i < 16; i++) {

			if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[i];
				mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex] - MLIB_S16_MIN;
				newpalc1 = base[1][newindex] - MLIB_S16_MIN;
				newpalc2 = base[2][newindex] - MLIB_S16_MIN;
				newpalc3 = base[3][newindex] - MLIB_S16_MIN;
				newdistance = FIND_DISTANCE_4(c[0], newpalc0,
				    c[1], newpalc1, c[2], newpalc2, c[3],
				    newpalc3, 2);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[i]) {

				if (i & mask)
/* This quadrant may require partial checking */
					distance =
					    FUNC_NAME(part_to_left_S16_4)
					    (node->contents.quadrants[i],
					    distance, found_color, c, base,
					    position + current_size, pass - 1,
					    dir_bit);
				else
/* Here we should check all */
					distance =
					    mlib_search_quadrant_S16_4(node->
					    contents.quadrants[i], distance,
					    found_color, c[0], c[1], c[2], c[3],
					    base);
			}
		}
	}

	return (distance);
}

/* *********************************************************** */

mlib_u32
mlib_search_quadrant_part_to_right_S16_4(
    struct lut_node_4 *node,
    mlib_u32 distance,
    mlib_s32 *found_color,
    const mlib_u32 *c,
    const mlib_s16 **base,
    mlib_u32 position,
    mlib_s32 pass,
    mlib_s32 dir_bit)
{
	mlib_u32 current_size = 1 << pass;
	mlib_s32 i;
	static mlib_s32 opposite_quadrants[4][8] = {
		{1, 3, 5, 7, 9, 11, 13, 15},
		{2, 3, 6, 7, 10, 11, 14, 15},
		{4, 5, 6, 7, 12, 13, 14, 15},
		{8, 9, 10, 11, 12, 13, 14, 15}
	};

/*
 * Search only quadrant's half until it is necessary to check the
 * whole quadrant
 */

/* Search half of quadrant */
	if (distance <=
	    (((c[dir_bit] - position - current_size) * (c[dir_bit] - position -
	    current_size)) >> 2)) {
		for (i = 0; i < 8; i++) {
			mlib_s32 qq = opposite_quadrants[dir_bit][i];

			if (node->tag & (1 << qq)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[qq];
				mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex] - MLIB_S16_MIN;
				newpalc1 = base[1][newindex] - MLIB_S16_MIN;
				newpalc2 = base[2][newindex] - MLIB_S16_MIN;
				newpalc3 = base[3][newindex] - MLIB_S16_MIN;
				newdistance = FIND_DISTANCE_4(c[0], newpalc0,
				    c[1], newpalc1, c[2], newpalc2, c[3],
				    newpalc3, 2);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[qq])
				distance =
				    mlib_search_quadrant_part_to_right_S16_4
				    (node->contents.quadrants[qq], distance,
				    found_color, c, base,
				    position + current_size, pass - 1, dir_bit);
		}
	} else {
/* Search whole quadrant */

		mlib_s32 mask = 1 << dir_bit;

		for (i = 0; i < 16; i++) {

			if (node->tag & (1 << i)) {
/* Here is alone color cell. Check the distance */
				mlib_s32 newindex = node->contents.index[i];
				mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
				mlib_u32 newdistance;

				newpalc0 = base[0][newindex] - MLIB_S16_MIN;
				newpalc1 = base[1][newindex] - MLIB_S16_MIN;
				newpalc2 = base[2][newindex] - MLIB_S16_MIN;
				newpalc3 = base[3][newindex] - MLIB_S16_MIN;
				newdistance = FIND_DISTANCE_4(c[0], newpalc0,
				    c[1], newpalc1, c[2], newpalc2, c[3],
				    newpalc3, 2);

				if (distance > newdistance) {
					*found_color = newindex;
					distance = newdistance;
				}
			} else if (node->contents.quadrants[i]) {

				if (i & mask)
/* Here we should check all */
					distance =
					    mlib_search_quadrant_S16_4(node->
					    contents.quadrants[i], distance,
					    found_color, c[0], c[1], c[2], c[3],
					    base);
				else
/* This quadrant may require partial checking */
					distance =
					    FUNC_NAME(part_to_right_S16_4)
					    (node->contents.quadrants[i],
					    distance, found_color, c, base,
					    position, pass - 1, dir_bit);
			}
		}
	}

	return (distance);
}

/* *********************************************************** */

#define	TAB_SIZE_mlib_u8	256
#define	TAB_SIZE_mlib_s16	1024

/* *********************************************************** */

#define	SRC_mlib_u8(i)	src[i]
#define	SRC_mlib_s16(i)	(((mlib_u16*)src)[i] >> 6)

/* *********************************************************** */

#define	DIMENSIONS_SEARCH_3(STYPE, DTYPE, STEP)                    \
	{                                                          \
	    DTYPE *tab0 = ((mlib_colormap *) state)->table;        \
	    DTYPE *tab1 = tab0 + TAB_SIZE_##STYPE;                 \
	    DTYPE *tab2 = tab1 + TAB_SIZE_##STYPE;                 \
	    mlib_s32 i;                                            \
	                                                           \
	    for (i = 0; i < length; i++) {                         \
		dst[i] =                                           \
		    tab0[SRC_##STYPE(0)] +                         \
		    tab1[SRC_##STYPE(1)] + tab2[SRC_##STYPE(2)];   \
		src += STEP;                                       \
	    }                                                      \
	}

/* *********************************************************** */

#define	DIMENSIONS_SEARCH_4(STYPE, DTYPE)                          \
	{                                                          \
	    DTYPE *tab0 = ((mlib_colormap *) state)->table;        \
	    DTYPE *tab1 = tab0 + TAB_SIZE_##STYPE;                 \
	    DTYPE *tab2 = tab1 + TAB_SIZE_##STYPE;                 \
	    DTYPE *tab3 = tab2 + TAB_SIZE_##STYPE;                 \
	    mlib_s32 i;                                            \
	                                                           \
	    for (i = 0; i < length; i++) {                         \
		dst[i] =                                           \
		    tab0[SRC_##STYPE(0)] +                         \
		    tab1[SRC_##STYPE(1)] +                         \
		    tab2[SRC_##STYPE(2)] + tab3[SRC_##STYPE(3)];   \
		src += 4;                                          \
	    }                                                      \
	}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_U8_U8_3(
    const mlib_u8 *src,
    mlib_u8 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;

	switch (s->method) {
#if LUT_BYTE_COLORS_3CHANNELS <= 256
	case LUT_BINARY_TREE_SEARCH:
	    {
		    mlib_s32 bits = s->bits;
		    BINARY_TREE_SEARCH_3(U8, mlib_u8,
			8,
			    (MLIB_U8_MAX + 1),
			0,
			0,
			3,
			0);
	    }

		break;

#endif /* LUT_BYTE_COLORS_3CHANNELS <= 256 */
	case LUT_COLOR_CUBE_SEARCH:
	    {
		    COLOR_CUBE_U8_3_SEARCH(mlib_u8,
			0,
			3);
	    }

		break;

	case LUT_STUPID_SEARCH:
	    {
#ifdef MLIB_VIS
		    FIND_NEAREST_U8_3;
#else /* MLIB_VIS */
		    FIND_NEAREST_U8_3_C(0, 3);
#endif /* MLIB_VIS */
	    }

		break;

	case LUT_COLOR_DIMENSIONS:
		DIMENSIONS_SEARCH_3(mlib_u8,
		    mlib_u8,
		    3)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_U8_U8_3_in_4(
    const mlib_u8 *src,
    mlib_u8 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;

	switch (s->method) {
#if LUT_BYTE_COLORS_3CHANNELS <= 256
	case LUT_BINARY_TREE_SEARCH:
	    {
		    mlib_s32 bits = s->bits;
		    BINARY_TREE_SEARCH_3(U8, mlib_u8,
			8,
			    (MLIB_U8_MAX + 1),
			0,
			1,
			4,
			0);

		    break;
	    }

#endif /* LUT_BYTE_COLORS_3CHANNELS <= 256 */
	case LUT_COLOR_CUBE_SEARCH:
	    {
		    COLOR_CUBE_U8_3_SEARCH(mlib_u8,
			1,
			4);

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
#ifdef MLIB_VIS
		    FIND_NEAREST_U8_3_IN4;
#else /* MLIB_VIS */
		    FIND_NEAREST_U8_3_C(1, 4);
#endif /* MLIB_VIS */
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		src++;
		DIMENSIONS_SEARCH_3(mlib_u8,
		    mlib_u8,
		    4)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_U8_U8_4(
    const mlib_u8 *src,
    mlib_u8 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;

	switch (s->method) {
#if LUT_BYTE_COLORS_4CHANNELS <= 256
	case LUT_BINARY_TREE_SEARCH:
	    {
		    mlib_s32 bits = s->bits;
		    BINARY_TREE_SEARCH_4(U8, mlib_u8,
			8,
			    (MLIB_U8_MAX + 1),
			0,
			0);

		    break;
	    }

#endif /* LUT_BYTE_COLORS_4CHANNELS <= 256 */
	case LUT_COLOR_CUBE_SEARCH:
	    {
		    COLOR_CUBE_U8_4_SEARCH(mlib_u8);

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
#ifdef MLIB_VIS
		    FIND_NEAREST_U8_4;
#else /* MLIB_VIS */
		    FIND_NEAREST_U8_4_C;
#endif /* MLIB_VIS */
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		DIMENSIONS_SEARCH_4(mlib_u8,
		    mlib_u8)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_U8_S16_3(
    const mlib_u8 *src,
    mlib_s16 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;
	mlib_s32 bits = s->bits;

	switch (s->method) {
	case LUT_BINARY_TREE_SEARCH:
	    {
		    BINARY_TREE_SEARCH_3(U8, mlib_u8,
			8,
			    (MLIB_U8_MAX + 1),
			0,
			0,
			3,
			0);

		    break;
	    }

	case LUT_COLOR_CUBE_SEARCH:
	    {
		    switch (s->indexsize) {
		    case 1:
			{
				COLOR_CUBE_U8_3_SEARCH(mlib_u8,
				    0,
				    3);

				break;
			}

		    case 2:
			{
				COLOR_CUBE_U8_3_SEARCH(mlib_s16,
				    0,
				    3);

				break;
			}
		    }

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
#ifdef MLIB_VIS
		    FIND_NEAREST_U8_3;
#else /* MLIB_VIS */
		    FIND_NEAREST_U8_3_C(0, 3);
#endif /* MLIB_VIS */
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		DIMENSIONS_SEARCH_3(mlib_u8,
		    mlib_s16,
		    3)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_U8_S16_3_in_4(
    const mlib_u8 *src,
    mlib_s16 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;
	mlib_s32 bits = s->bits;

	switch (s->method) {
	case LUT_BINARY_TREE_SEARCH:
	    {
		    BINARY_TREE_SEARCH_3(U8, mlib_u8,
			8,
			    (MLIB_U8_MAX + 1),
			0,
			1,
			4,
			0);

		    break;
	    }

	case LUT_COLOR_CUBE_SEARCH:
	    {
		    switch (s->indexsize) {
		    case 1:
			{
				COLOR_CUBE_U8_3_SEARCH(mlib_u8,
				    1,
				    4);

				break;
			}

		    case 2:
			{
				COLOR_CUBE_U8_3_SEARCH(mlib_s16,
				    1,
				    4);

				break;
			}
		    }

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
#ifdef MLIB_VIS
		    FIND_NEAREST_U8_3_IN4;
#else /* MLIB_VIS */
		    FIND_NEAREST_U8_3_C(1, 4);
#endif /* MLIB_VIS */
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		src++;
		DIMENSIONS_SEARCH_3(mlib_u8,
		    mlib_s16,
		    4)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_U8_S16_4(
    const mlib_u8 *src,
    mlib_s16 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;
	mlib_s32 bits = s->bits;

	switch (s->method) {
	case LUT_BINARY_TREE_SEARCH:
	    {
		    BINARY_TREE_SEARCH_4(U8, mlib_u8,
			8,
			    (MLIB_U8_MAX + 1),
			0,
			0);

		    break;
	    }

	case LUT_COLOR_CUBE_SEARCH:
	    {
		    switch (s->indexsize) {
		    case 1:
			{
				COLOR_CUBE_U8_4_SEARCH(mlib_u8);

				break;
			}

		    case 2:
			{
				COLOR_CUBE_U8_4_SEARCH(mlib_s16);

				break;
			}
		    }

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
#ifdef MLIB_VIS
		    FIND_NEAREST_U8_4;
#else /* MLIB_VIS */
		    FIND_NEAREST_U8_4_C;
#endif /* MLIB_VIS */
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		DIMENSIONS_SEARCH_4(mlib_u8,
		    mlib_s16)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_S16_S16_3(
    const mlib_s16 *src,
    mlib_s16 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;
	mlib_s32 bits = s->bits;

	switch (s->method) {
	case LUT_BINARY_TREE_SEARCH:
	    {
		    BINARY_TREE_SEARCH_3(S16, mlib_s16,
			16,
			    ((MLIB_S16_MAX + 1) * 2),
			MLIB_S16_MIN,
			0,
			3,
			2);

		    break;
	    }

	case LUT_COLOR_CUBE_SEARCH:
	    {
		    switch (s->indexsize) {
		    case 1:
			{
				COLOR_CUBE_S16_3_SEARCH(mlib_u8,
				    0,
				    3);

				break;
			}

		    case 2:
			{
				COLOR_CUBE_S16_3_SEARCH(mlib_s16,
				    0,
				    3);

				break;
			}
		    }

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
		    FIND_NEAREST_S16_3(0, 3);
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		DIMENSIONS_SEARCH_3(mlib_s16,
		    mlib_s16,
		    3)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_S16_S16_3_in_4(
    const mlib_s16 *src,
    mlib_s16 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;
	mlib_s32 bits = s->bits;

	switch (s->method) {
	case LUT_BINARY_TREE_SEARCH:
	    {
		    BINARY_TREE_SEARCH_3(S16, mlib_s16,
			16,
			    ((MLIB_S16_MAX + 1) * 2),
			MLIB_S16_MIN,
			1,
			4,
			2);

		    break;
	    }

	case LUT_COLOR_CUBE_SEARCH:
	    {
		    switch (s->indexsize) {
		    case 1:
			{
				COLOR_CUBE_S16_3_SEARCH(mlib_u8,
				    1,
				    4);

				break;
			}

		    case 2:
			{
				COLOR_CUBE_S16_3_SEARCH(mlib_s16,
				    1,
				    4);

				break;
			}
		    }

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
		    FIND_NEAREST_S16_3(1, 4);
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		src++;
		DIMENSIONS_SEARCH_3(mlib_s16,
		    mlib_s16,
		    4)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_S16_S16_4(
    const mlib_s16 *src,
    mlib_s16 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;
	mlib_s32 bits = s->bits;

	switch (s->method) {
	case LUT_BINARY_TREE_SEARCH:
	    {
		    BINARY_TREE_SEARCH_4(S16, mlib_s16,
			16,
			    ((MLIB_S16_MAX + 1) * 2),
			MLIB_S16_MIN,
			2);

		    break;
	    }

	case LUT_COLOR_CUBE_SEARCH:
	    {
		    switch (s->indexsize) {
		    case 1:
			{
				COLOR_CUBE_S16_4_SEARCH(mlib_u8);

				break;
			}

		    case 2:
			{
				COLOR_CUBE_S16_4_SEARCH(mlib_s16);

				break;
			}
		    }

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
		    FIND_NEAREST_S16_4;
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		DIMENSIONS_SEARCH_4(mlib_s16,
		    mlib_s16)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_S16_U8_3(
    const mlib_s16 *src,
    mlib_u8 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;

	switch (s->method) {
#if LUT_SHORT_COLORS_3CHANNELS <= 256
	case LUT_BINARY_TREE_SEARCH:
	    {
		    mlib_s32 bits = s->bits;
		    BINARY_TREE_SEARCH_3(S16, mlib_s16,
			16,
			    ((MLIB_S16_MAX + 1) * 2),
			MLIB_S16_MIN,
			0,
			3,
			2);

		    break;
	    }

#endif /* LUT_SHORT_COLORS_3CHANNELS <= 256 */
	case LUT_COLOR_CUBE_SEARCH:
	    {
		    COLOR_CUBE_S16_3_SEARCH(mlib_u8,
			0,
			3);

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
		    FIND_NEAREST_S16_3(0, 3);
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		DIMENSIONS_SEARCH_3(mlib_s16,
		    mlib_u8,
		    3)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_S16_U8_3_in_4(
    const mlib_s16 *src,
    mlib_u8 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;

	switch (s->method) {
#if LUT_SHORT_COLORS_3CHANNELS <= 256
	case LUT_BINARY_TREE_SEARCH:
	    {
		    mlib_s32 bits = s->bits;
		    BINARY_TREE_SEARCH_3(S16, mlib_s16,
			16,
			    ((MLIB_S16_MAX + 1) * 2),
			MLIB_S16_MIN,
			1,
			4,
			2);

		    break;
	    }

#endif /* LUT_SHORT_COLORS_3CHANNELS <= 256 */
	case LUT_COLOR_CUBE_SEARCH:
	    {
		    COLOR_CUBE_S16_3_SEARCH(mlib_u8,
			1,
			4);

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
		    FIND_NEAREST_S16_3(1, 4);
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		src++;
		DIMENSIONS_SEARCH_3(mlib_s16,
		    mlib_u8,
		    4)
		    break;
	}
}

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_S16_U8_4(
    const mlib_s16 *src,
    mlib_u8 *dst,
    mlib_s32 length,
    const void *state)
{
	mlib_colormap *s = (mlib_colormap *) state;

	switch (s->method) {
#if LUT_SHORT_COLORS_4CHANNELS <= 256
	case LUT_BINARY_TREE_SEARCH:
	    {
		    mlib_s32 bits = s->bits;
		    BINARY_TREE_SEARCH_4(S16, mlib_s16,
			16,
			    ((MLIB_S16_MAX + 1) * 2),
			MLIB_S16_MIN,
			2);

		    break;
	    }

#endif /* LUT_SHORT_COLORS_4CHANNELS <= 256 */
	case LUT_COLOR_CUBE_SEARCH:
	    {
		    COLOR_CUBE_S16_4_SEARCH(mlib_u8);

		    break;
	    }

	case LUT_STUPID_SEARCH:
	    {
		    FIND_NEAREST_S16_4;
		    break;
	    }

	case LUT_COLOR_DIMENSIONS:
		DIMENSIONS_SEARCH_4(mlib_s16,
		    mlib_u8)
		    break;
	}
}

/* *********************************************************** */

#ifndef MLIB_VIS

#include <mlib_c_ImageThresh1.h>

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_U8_BIT_1(
    const mlib_u8 *src,
    mlib_u8 *dst,
    mlib_s32 bit_offset,
    mlib_s32 length,
    const void *state)
{
	mlib_u8 *lut = ((mlib_colormap *) state)->table;
	mlib_s32 thresh[1];
	mlib_s32 ghigh[1];
	mlib_s32 glow[1];

	thresh[0] = lut[2];

	glow[0] = lut[0] - lut[1];
	ghigh[0] = lut[1] - lut[0];

	mlib_c_ImageThresh1_U81_1B((void *)src, dst, 0, 0, length, 1,
	    thresh, ghigh, glow, bit_offset);
}

#else /* MLIB_VIS */

#include <mlib_v_ImageThreshFunc.h>

/* *********************************************************** */

void
mlib_ImageColorTrue2IndexLine_U8_BIT_1(
    const mlib_u8 *src,
    mlib_u8 *dst,
    mlib_s32 bit_offset,
    mlib_s32 length,
    const void *state)
{
	mlib_u8 *lut = ((mlib_colormap *) state)->table;
	mlib_s32 thresh[4];
	mlib_s32 ghigh[1];
	mlib_s32 glow[1];

	thresh[0] = thresh[1] = thresh[2] = thresh[3] = lut[2];

	glow[0] = (lut[1] < lut[0]) ? 0xFF : 0;
	ghigh[0] = (lut[1] < lut[0]) ? 0 : 0xFF;

	mlib_v_ImageThresh1B_U8_1((void *)src, 0, dst, 0, length, 1,
	    bit_offset, thresh, ghigh[0], glow[0]);
}

/* *********************************************************** */

#endif /* MLIB_VIS */
