Example #1
0
/**
 * Precompute GCD and bounds transformations
 */
static int
diophantine_precompute(unsigned int n,
                       diophantine_term_t *E,
                       diophantine_term_t *Ep,
                       npy_int64 *Gamma, npy_int64 *Epsilon)
{
    npy_int64 a_gcd, gamma, epsilon, c1, c2;
    unsigned int j;
    char overflow = 0;

    assert(n >= 2);

    euclid(E[0].a, E[1].a, &a_gcd, &gamma, &epsilon);
    Ep[0].a = a_gcd;
    Gamma[0] = gamma;
    Epsilon[0] = epsilon;

    if (n > 2) {
        c1 = E[0].a / a_gcd;
        c2 = E[1].a / a_gcd;

        /* Ep[0].ub = E[0].ub * c1 + E[1].ub * c2; */
        Ep[0].ub = safe_add(safe_mul(E[0].ub, c1, &overflow),
                            safe_mul(E[1].ub, c2, &overflow), &overflow);
        if (overflow) {
            return 1;
        }
    }

    for (j = 2; j < n; ++j) {
        euclid(Ep[j-2].a, E[j].a, &a_gcd, &gamma, &epsilon);
        Ep[j-1].a = a_gcd;
        Gamma[j-1] = gamma;
        Epsilon[j-1] = epsilon;

        if (j < n - 1) {
            c1 = Ep[j-2].a / a_gcd;
            c2 = E[j].a / a_gcd;

            /* Ep[j-1].ub = c1 * Ep[j-2].ub + c2 * E[j].ub; */
            Ep[j-1].ub = safe_add(safe_mul(c1, Ep[j-2].ub, &overflow),
                                  safe_mul(c2, E[j].ub, &overflow), &overflow);

            if (overflow) {
                return 1;
            }
        }
    }

    return 0;
}
int
main()
{
	const double nums[][2] = {
		{1, 2},
		{0.1, 0.2},
		{1e100, 1e-100},
		{1e308, 1e308},
	};
	double ival[2];
	int i;

	for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) {
		/*
		 * Calculate nums[i][0] + nums[i][1].
		 */
		safe_add(ival, nums[i][0], nums[i][1]);

		/*
		 * Print the result. %.17g gives the best output.
		 * %.16g or plain %g gives not enough digits.
		 */
		printf("%.17g + %.17g =\n", nums[i][0], nums[i][1]);
		printf("    [%.17g, %.17g]\n", ival[0], ival[1]);
		printf("    size %.17g\n\n", ival[1] - ival[0]);
	}
	return 0;
}
Example #3
0
int
__glXSeparableFilter2DReqSize(const GLbyte * pc, Bool swap, int reqlen)
{
    __GLXdispatchConvolutionFilterHeader *hdr =
        (__GLXdispatchConvolutionFilterHeader *) pc;

    GLint image1size, image2size;
    GLenum format = hdr->format;
    GLenum type = hdr->type;
    GLint w = hdr->width;
    GLint h = hdr->height;
    GLint rowLength = hdr->rowLength;
    GLint alignment = hdr->alignment;

    if (swap) {
        format = SWAPL(format);
        type = SWAPL(type);
        w = SWAPL(w);
        h = SWAPL(h);
        rowLength = SWAPL(rowLength);
        alignment = SWAPL(alignment);
    }

    /* XXX Should rowLength be used for either or both image? */
    image1size = __glXImageSize(format, type, 0, w, 1, 1,
                                0, rowLength, 0, 0, alignment);
    image2size = __glXImageSize(format, type, 0, h, 1, 1,
                                0, rowLength, 0, 0, alignment);
    return safe_add(safe_pad(image1size), image2size);
}
Example #4
0
/**
 * Simplify Diophantine decision problem.
 *
 * Combine identical coefficients, remove unnecessary variables, and trim
 * bounds.
 *
 * The feasible/infeasible decision result is retained.
 *
 * Returns: 0 (success), -1 (integer overflow).
 */
NPY_VISIBILITY_HIDDEN int
diophantine_simplify(unsigned int *n, diophantine_term_t *E, npy_int64 b)
{
    unsigned int i, j, m;
    char overflow = 0;

    /* Skip obviously infeasible cases */
    for (j = 0; j < *n; ++j) {
        if (E[j].ub < 0) {
            return 0;
        }
    }

    if (b < 0) {
        return 0;
    }

    /* Sort vs. coefficients */
    qsort(E, *n, sizeof(diophantine_term_t), diophantine_sort_A);

    /* Combine identical coefficients */
    m = *n;
    i = 0;
    for (j = 1; j < m; ++j) {
        if (E[i].a == E[j].a) {
            E[i].ub = safe_add(E[i].ub, E[j].ub, &overflow);
            --*n;
        }
        else {
            ++i;
            if (i != j) {
                E[i] = E[j];
            }
        }
    }

    /* Trim bounds and remove unnecessary variables */
    m = *n;
    i = 0;
    for (j = 0; j < m; ++j) {
        E[j].ub = MIN(E[j].ub, b / E[j].a);
        if (E[j].ub == 0) {
            /* If the problem is feasible at all, x[i]=0 */
            --*n;
        }
        else {
            if (i != j) {
                E[i] = E[j];
            }
            ++i;
        }
    }

    if (overflow) {
        return -1;
    }
    else {
        return 0;
    }
}
Example #5
0
/*
 * Allocate and initialize a DexDataMap. Returns NULL on failure.
 */
DexDataMap* dexDataMapAlloc(u4 maxCount) {
    /*
     * Allocate a single chunk for the DexDataMap per se as well as the
     * two arrays.
     */
    size_t size = 0;
    DexDataMap* map = NULL;

    /*
     * Avoiding pulling in safe_iop for safe_iopf.
     */
    if (!safe_mul(&size, maxCount, sizeof(u4) + sizeof(u2)) ||
        !safe_add(&size, size, sizeof(DexDataMap))) {
      return NULL;
    }

    map = (DexDataMap*) malloc(size);

    if (map == NULL) {
        return NULL;
    }

    map->count = 0;
    map->max = maxCount;
    map->offsets = (u4*) (map + 1);
    map->types = (u2*) (map->offsets + maxCount);

    return map;
}
void Graphic_base::Color::add_color(Color& c, bool alpha_enabled) {
	if(alpha_enabled) 
		for(int i = 0; i < 4; i++)
			comp[i] = alpha_mix(comp[i], c.comp[i], c.comp[3]);
	else 
		for(int i = 0; i < 4; i++)
			comp[i] = safe_add(comp[i], c.comp[i]);
}
Example #7
0
void test_safe_add(){

  int32_t a = INT_MAX;
  int32_t b = 1;

  // Should produce error
  int error;
  int result = safe_add(a, b, &error);

  print_result(result, error);

  // Should not result in error
  a = INT_MIN;
  error = 0;
  result = safe_add(a, b, &error);
  print_result(result, error);
}
Example #8
0
unsigned light_lt_manager::get_weight_core(expr const & e) {
    switch (e.kind()) {
    case expr_kind::Var:  case expr_kind::Constant: case expr_kind::Sort:
    case expr_kind::Meta: case expr_kind::Local:
        return 1;
    case expr_kind::Lambda: case expr_kind::Pi:
        return safe_add(1, safe_add(get_weight(binding_domain(e)), get_weight(binding_body(e))));
    case expr_kind::Macro:
        return safe_add(1, add_weight(macro_num_args(e), macro_args(e)));
    case expr_kind::App:
        buffer<expr> args;
        expr fn = get_app_args(e, args);
        if (is_constant(fn)) {
            unsigned const * light_arg = m_lrs.find(const_name(fn));
            if (light_arg && args.size() > *light_arg) return get_weight(args[*light_arg]);
        }
        return safe_add(1, safe_add(get_weight(app_fn(e)), get_weight(app_arg(e))));
    }
    lean_unreachable(); // LCOV_EXCL_LINE
}
Example #9
0
int
__glXPrioritizeTexturesReqSize( const GLbyte * pc, Bool swap, int reqlen )
{
GLsizei n          = *(GLsizei *)(pc + 0);

    if (swap) {
        n = bswap_32(n);
    }

    return safe_pad(safe_add(safe_mul(n , 4), safe_mul(n , 4)));
}
int Graphic_base::Color::add(int dst, int src, bool alpha_enabled, bool opaque_bg) {
	uint8_t* comp_dst = (uint8_t*)&dst;
	uint8_t* comp_src = (uint8_t*)&src;
	int result;
	uint8_t* comp_r = (uint8_t*)&result;
	
	if(alpha_enabled)
		for(int i = 0; i < 4; i++)
			comp_r[i] = alpha_mix(comp_dst[i], comp_src[i], comp_src[3]);
	else 
		for(int i = 0; i < 4; i++)
			comp_r[i] = safe_add(comp_dst[i], comp_src[i]);

	return result;
}
Example #11
0
void test_safe_multiply(){

  int32_t a = INT_MAX;
  int32_t b = 1;

  // Should not result in error
  int error;
  int result = safe_multiply(a, b, &error);

  print_result(result, error);

  // Should result in error
  b = 2;
  error = 0;
  result = safe_add(a, b, &error);
  print_result(result, error);

}
Example #12
0
UInt32
PollingManagerThread::calcSleepTime(bool& rightNow, bool doInit)
{
	rightNow = false;
	DateTime dtm;
	dtm.setToCurrent();
	time_t tm = dtm.get();

	Int32 const int32_max = std::numeric_limits<Int32>::max();
	time_t const time_t_max = std::numeric_limits<time_t>::max();
	time_t leastTime = (time_t_max > int32_max ? int32_max : time_t_max);
	// leastTime is now a large positive time_t value that will fit into an
	// Int32, and hence into a UInt32.

	int checkedCount = 0;
	// LOOP INVARIANT: 0 <= leastTime <= int32_max
	for (size_t i = 0; i < m_triggerRunners.size(); i++)
	{
		if (m_triggerRunners[i]->m_isRunning
			|| m_triggerRunners[i]->m_pollInterval == 0)
		{
			continue;
		}
		if (doInit)
		{
			m_triggerRunners[i]->m_nextPoll =
				safe_add(tm, m_triggerRunners[i]->m_pollInterval);
		}
		else if (m_triggerRunners[i]->m_nextPoll <= tm)
		{
			rightNow = true;
			return 0;
		}
		// GUARANTEED: m_triggerRunners[i]->m_nextPoll >= tm
		checkedCount++;
		time_t diff = m_triggerRunners[i]->m_nextPoll - tm;
		if (diff < leastTime)
		{
			leastTime = diff;
		}
	}
	return (checkedCount == 0) ? 0 : UInt32(leastTime);
}
Example #13
0
void
PollingManagerThread::TriggerRunner::run()
{
	Int32 nextInterval = 0;
	try
	{
		nextInterval = m_itp->poll(createProvEnvRef(m_env));
	}
	catch(std::exception& e)
	{
		OW_LOG_ERROR(m_logger, Format("Caught Exception while running poll: %1",
			e.what()));
	}
	catch(ThreadCancelledException& e)
	{
		throw;
	}
	catch(...)
	{
		OW_LOG_ERROR(m_logger, "Caught Unknown Exception while running poll");
	}
	NonRecursiveMutexLock l(m_pollMan->m_triggerGuard);
	if (nextInterval == 0 || m_pollInterval == 0) // m_pollInterval == 0 means this poller has been instructed to stop
	{
		m_pollInterval = 0;
		m_nextPoll = 0;
	}
	else
	{
		if (nextInterval > 0)
		{
			m_pollInterval = nextInterval;
		}
		DateTime dtm;
		dtm.setToCurrent();
		m_nextPoll = safe_add(dtm.get(), m_pollInterval);
	}
	m_isRunning = false;
	m_pollMan->m_triggerCondition.notifyOne();
}
Example #14
0
void
PollingManagerThread::addPolledProvider(const PolledProviderIFCRef& p)
{
	NonRecursiveMutexLock l(m_triggerGuard);
	if (m_shuttingDown)
		return;
	TriggerRunnerRef tr(new TriggerRunner(this, m_env));
	tr->m_pollInterval = 
		p->getInitialPollingInterval(createProvEnvRef(m_env));
	OW_LOG_DEBUG(m_logger, Format("PollingManager poll interval for provider"
		" %1", tr->m_pollInterval));
	if (!tr->m_pollInterval)
	{
		return;
	}
	DateTime dtm;
	dtm.setToCurrent();
	time_t tm = dtm.get();
	tr->m_nextPoll = safe_add(tm, tr->m_pollInterval);
	tr->m_itp = p;
	m_triggerRunners.append(tr);
	m_triggerCondition.notifyAll();
}
Example #15
0
/**
 * Solve bounded Diophantine equation
 *
 * The problem considered is::
 *
 *     A[0] x[0] + A[1] x[1] + ... + A[n-1] x[n-1] == b
 *     0 <= x[i] <= U[i]
 *     A[i] > 0
 *
 * Solve via depth-first Euclid's algorithm, as explained in [1].
 *
 * If require_ub_nontrivial!=0, look for solutions to the problem
 * where b = A[0]*(U[0]/2) + ... + A[n]*(U[n-1]/2) but ignoring
 * the trivial solution x[i] = U[i]/2. All U[i] must be divisible by 2.
 * The value given for `b` is ignored in this case.
 */
NPY_VISIBILITY_HIDDEN mem_overlap_t
solve_diophantine(unsigned int n, diophantine_term_t *E, npy_int64 b,
                  Py_ssize_t max_work, int require_ub_nontrivial, npy_int64 *x)
{
    mem_overlap_t res;
    unsigned int j;

    for (j = 0; j < n; ++j) {
        if (E[j].a <= 0) {
            return MEM_OVERLAP_ERROR;
        }
        else if (E[j].ub < 0) {
            return MEM_OVERLAP_NO;
        }
    }

    if (require_ub_nontrivial) {
        npy_int64 ub_sum = 0;
        char overflow = 0;
        for (j = 0; j < n; ++j) {
            if (E[j].ub % 2 != 0) {
                return MEM_OVERLAP_ERROR;
            }
            ub_sum = safe_add(ub_sum,
                              safe_mul(E[j].a, E[j].ub/2, &overflow),
                              &overflow);
        }
        if (overflow) {
            return MEM_OVERLAP_ERROR;
        }
        b = ub_sum;
    }

    if (b < 0) {
        return MEM_OVERLAP_NO;
    }

    if (n == 0) {
        if (require_ub_nontrivial) {
            /* Only trivial solution for 0-variable problem */
            return MEM_OVERLAP_NO;
        }
        if (b == 0) {
            return MEM_OVERLAP_YES;
        }
        return MEM_OVERLAP_NO;
    }
    else if (n == 1) {
        if (require_ub_nontrivial) {
            /* Only trivial solution for 1-variable problem */
            return MEM_OVERLAP_NO;
        }
        if (b % E[0].a == 0) {
            x[0] = b / E[0].a;
            if (x[0] >= 0 && x[0] <= E[0].ub) {
                return MEM_OVERLAP_YES;
            }
        }
        return MEM_OVERLAP_NO;
    }
    else {
        Py_ssize_t count = 0;
        diophantine_term_t *Ep = NULL;
        npy_int64 *Epsilon = NULL, *Gamma = NULL;

        Ep = malloc(n * sizeof(diophantine_term_t));
        Epsilon = malloc(n * sizeof(npy_int64));
        Gamma = malloc(n * sizeof(npy_int64));
        if (Ep == NULL || Epsilon == NULL || Gamma == NULL) {
            res = MEM_OVERLAP_ERROR;
        }
        else if (diophantine_precompute(n, E, Ep, Gamma, Epsilon)) {
            res = MEM_OVERLAP_OVERFLOW;
        }
        else {
            res = diophantine_dfs(n, n-1, E, Ep, Gamma, Epsilon, b, max_work,
                                  require_ub_nontrivial, x, &count);
        }
        free(Ep);
        free(Gamma);
        free(Epsilon);
        return res;
    }
}
Example #16
0
static int
GetSeparableFilter(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag)
{
    GLint compsize, compsize2;
    GLenum format, type, target;
    GLboolean swapBytes;
    __GLXcontext *cx;
    ClientPtr client = cl->client;
    int error;

    __GLX_DECLARE_SWAP_VARIABLES;
    char *answer, answerBuffer[200];
    GLint width = 0, height = 0;
    xGLXSingleReply reply = { 0, };

    cx = __glXForceCurrent(cl, tag, &error);
    if (!cx) {
        return error;
    }

    __GLX_SWAP_INT(pc + 0);
    __GLX_SWAP_INT(pc + 4);
    __GLX_SWAP_INT(pc + 8);

    format = *(GLenum *) (pc + 4);
    type = *(GLenum *) (pc + 8);
    target = *(GLenum *) (pc + 0);
    swapBytes = *(GLboolean *) (pc + 12);

    /* target must be SEPARABLE_2D, however I guess we can let the GL
       barf on this one.... */

    glGetConvolutionParameteriv(target, GL_CONVOLUTION_WIDTH, &width);
    glGetConvolutionParameteriv(target, GL_CONVOLUTION_HEIGHT, &height);
    /*
     * The two queries above might fail if we're in a state where queries
     * are illegal, but then width and height would still be zero anyway.
     */
    compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1);
    compsize2 = __glGetTexImage_size(target, 1, format, type, height, 1, 1);

    if ((compsize = safe_pad(compsize)) < 0)
        return BadLength;
    if ((compsize2 = safe_pad(compsize2)) < 0)
        return BadLength;

    glPixelStorei(GL_PACK_SWAP_BYTES, !swapBytes);
    __GLX_GET_ANSWER_BUFFER(answer, cl, safe_add(compsize, compsize2), 1);
    __glXClearErrorOccured();
    glGetSeparableFilter(*(GLenum *) (pc + 0), *(GLenum *) (pc + 4),
                         *(GLenum *) (pc + 8), answer, answer + compsize, NULL);

    if (__glXErrorOccured()) {
        __GLX_BEGIN_REPLY(0);
        __GLX_SWAP_REPLY_HEADER();
    }
    else {
        __GLX_BEGIN_REPLY(compsize + compsize2);
        __GLX_SWAP_REPLY_HEADER();
        __GLX_SWAP_INT(&width);
        __GLX_SWAP_INT(&height);
        ((xGLXGetSeparableFilterReply *) &reply)->width = width;
        ((xGLXGetSeparableFilterReply *) &reply)->height = height;
        __GLX_SEND_VOID_ARRAY(compsize + compsize2);
    }

    return Success;
}
void* VectorImpl::_grow(size_t where, size_t amount)
{
//    ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
//        this, (int)where, (int)amount, (int)mCount, (int)capacity());

    ALOG_ASSERT(where <= mCount,
            "[%p] _grow: where=%d, amount=%d, count=%d",
            this, (int)where, (int)amount, (int)mCount); // caller already checked

    size_t new_size;
    LOG_ALWAYS_FATAL_IF(!safe_add(&new_size, mCount, amount), "new_size overflow");

    if (capacity() < new_size) {
        // NOTE: This implementation used to resize vectors as per ((3*x + 1) / 2)
        // (sigh..). Also note, the " + 1" was necessary to handle the special case
        // where x == 1, where the resized_capacity will be equal to the old
        // capacity without the +1. The old calculation wouldn't work properly
        // if x was zero.
        //
        // This approximates the old calculation, using (x + (x/2) + 1) instead.
        size_t new_capacity = 0;
        LOG_ALWAYS_FATAL_IF(!safe_add(&new_capacity, new_size, (new_size / 2)),
                            "new_capacity overflow");
        LOG_ALWAYS_FATAL_IF(!safe_add(&new_capacity, new_capacity, static_cast<size_t>(1u)),
                            "new_capacity overflow");
        new_capacity = max(kMinVectorCapacity, new_capacity);

        size_t new_alloc_size = 0;
        LOG_ALWAYS_FATAL_IF(!safe_mul(&new_alloc_size, new_capacity, mItemSize),
                            "new_alloc_size overflow");

//        ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
        if ((mStorage) &&
            (mCount==where) &&
            (mFlags & HAS_TRIVIAL_COPY) &&
            (mFlags & HAS_TRIVIAL_DTOR))
        {
            const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
            SharedBuffer* sb = cur_sb->editResize(new_alloc_size);
            if (sb) {
                mStorage = sb->data();
            } else {
                return NULL;
            }
        } else {
            SharedBuffer* sb = SharedBuffer::alloc(new_alloc_size);
            if (sb) {
                void* array = sb->data();
                if (where != 0) {
                    _do_copy(array, mStorage, where);
                }
                if (where != mCount) {
                    const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize;
                    void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
                    _do_copy(dest, from, mCount-where);
                }
                release_storage();
                mStorage = const_cast<void*>(array);
            } else {
                return NULL;
            }
        }
    } else {
        void* array = editArrayImpl();
        if (where != mCount) {
            const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
            void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
            _do_move_forward(to, from, mCount - where);
        }
    }
    mCount = new_size;
    void* free_space = const_cast<void*>(itemLocation(where));
    return free_space;
}
Example #18
0
int
__glXDrawArraysReqSize(const GLbyte * pc, Bool swap, int reqlen)
{
    __GLXdispatchDrawArraysHeader *hdr = (__GLXdispatchDrawArraysHeader *) pc;
    __GLXdispatchDrawArraysComponentHeader *compHeader;
    GLint numVertexes = hdr->numVertexes;
    GLint numComponents = hdr->numComponents;
    GLint arrayElementSize = 0;
    GLint x, size;
    int i;

    if (swap) {
        numVertexes = SWAPL(numVertexes);
        numComponents = SWAPL(numComponents);
    }

    pc += sizeof(__GLXdispatchDrawArraysHeader);
    reqlen -= sizeof(__GLXdispatchDrawArraysHeader);

    size = safe_mul(sizeof(__GLXdispatchDrawArraysComponentHeader),
                    numComponents);
    if (size < 0 || reqlen < 0 || reqlen < size)
        return -1;

    compHeader = (__GLXdispatchDrawArraysComponentHeader *) pc;

    for (i = 0; i < numComponents; i++) {
        GLenum datatype = compHeader[i].datatype;
        GLint numVals = compHeader[i].numVals;
        GLint component = compHeader[i].component;

        if (swap) {
            datatype = SWAPL(datatype);
            numVals = SWAPL(numVals);
            component = SWAPL(component);
        }

        switch (component) {
        case GL_VERTEX_ARRAY:
        case GL_COLOR_ARRAY:
        case GL_TEXTURE_COORD_ARRAY:
            break;
        case GL_SECONDARY_COLOR_ARRAY:
        case GL_NORMAL_ARRAY:
            if (numVals != 3) {
                /* bad size */
                return -1;
            }
            break;
        case GL_FOG_COORD_ARRAY:
        case GL_INDEX_ARRAY:
            if (numVals != 1) {
                /* bad size */
                return -1;
            }
            break;
        case GL_EDGE_FLAG_ARRAY:
            if ((numVals != 1) && (datatype != GL_UNSIGNED_BYTE)) {
                /* bad size or bad type */
                return -1;
            }
            break;
        default:
            /* unknown component type */
            return -1;
        }

        x = safe_pad(safe_mul(numVals, __glXTypeSize(datatype)));
        if ((arrayElementSize = safe_add(arrayElementSize, x)) < 0)
            return -1;

        pc += sizeof(__GLXdispatchDrawArraysComponentHeader);
    }

    return safe_add(size, safe_mul(numVertexes, arrayElementSize));
}
Example #19
0
/**
 * Calculate the size of an image.
 *
 * The size of an image sent to the server from the client or sent from the
 * server to the client is calculated.  The size is based on the dimensions
 * of the image, the type of pixel data, padding in the image, and the
 * alignment requirements of the image.
 *
 * \param format       Format of the pixels.  Same as the \c format parameter
 *                     to \c glTexImage1D
 * \param type         Type of the pixel data.  Same as the \c type parameter
 *                     to \c glTexImage1D
 * \param target       Typically the texture target of the image.  If the
 *                     target is one of \c GL_PROXY_*, the size returned is
 *                     always zero. For uses that do not have a texture target
 *                     (e.g, glDrawPixels), zero should be specified.
 * \param w            Width of the image data.  Must be >= 1.
 * \param h            Height of the image data.  Must be >= 1, even for 1D
 *                     images.
 * \param d            Depth of the image data.  Must be >= 1, even for 1D or
 *                     2D images.
 * \param imageHeight  If non-zero, defines the true height of a volumetric
 *                     image.  This value will be used instead of \c h for
 *                     calculating the size of the image.
 * \param rowLength    If non-zero, defines the true width of an image.  This
 *                     value will be used instead of \c w for calculating the
 *                     size of the image.
 * \param skipImages   Number of extra layers of image data in a volumtric
 *                     image that are to be skipped before the real data.
 * \param skipRows     Number of extra rows of image data in an image that are
 *                     to be skipped before the real data.
 * \param alignment    Specifies the alignment for the start of each pixel row
 *                     in memory.  This value must be one of 1, 2, 4, or 8.
 *
 * \returns
 * The size of the image is returned.  If the specified \c format and \c type
 * are invalid, -1 is returned.  If \c target is one of \c GL_PROXY_*, zero
 * is returned.
 */
int
__glXImageSize(GLenum format, GLenum type, GLenum target,
               GLsizei w, GLsizei h, GLsizei d,
               GLint imageHeight, GLint rowLength,
               GLint skipImages, GLint skipRows, GLint alignment)
{
    GLint bytesPerElement, elementsPerGroup, groupsPerRow;
    GLint groupSize, rowSize, padding, imageSize;

    if (w == 0 || h == 0 || d == 0)
        return 0;

    if (w < 0 || h < 0 || d < 0 ||
        (type == GL_BITMAP &&
         (format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX))) {
        return -1;
    }

    /* proxy targets have no data */
    switch (target) {
    case GL_PROXY_TEXTURE_1D:
    case GL_PROXY_TEXTURE_2D:
    case GL_PROXY_TEXTURE_3D:
    case GL_PROXY_TEXTURE_4D_SGIS:
    case GL_PROXY_TEXTURE_CUBE_MAP:
    case GL_PROXY_TEXTURE_RECTANGLE_ARB:
    case GL_PROXY_HISTOGRAM:
    case GL_PROXY_COLOR_TABLE:
    case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
    case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
    case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
    case GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP:
        return 0;
    }

    /* real data has to have real sizes */
    if (imageHeight < 0 || rowLength < 0 || skipImages < 0 || skipRows < 0)
        return -1;
    if (alignment != 1 && alignment != 2 && alignment != 4 && alignment != 8)
        return -1;

    if (type == GL_BITMAP) {
        if (rowLength > 0) {
            groupsPerRow = rowLength;
        }
        else {
            groupsPerRow = w;
        }
        rowSize = bits_to_bytes(groupsPerRow);
        if (rowSize < 0)
            return -1;
        padding = (rowSize % alignment);
        if (padding) {
            rowSize += alignment - padding;
        }

        return safe_mul(safe_add(h, skipRows), rowSize);
    }
    else {
        switch (format) {
        case GL_COLOR_INDEX:
        case GL_STENCIL_INDEX:
        case GL_DEPTH_COMPONENT:
        case GL_RED:
        case GL_GREEN:
        case GL_BLUE:
        case GL_ALPHA:
        case GL_LUMINANCE:
        case GL_INTENSITY:
        case GL_RED_INTEGER_EXT:
        case GL_GREEN_INTEGER_EXT:
        case GL_BLUE_INTEGER_EXT:
        case GL_ALPHA_INTEGER_EXT:
        case GL_LUMINANCE_INTEGER_EXT:
            elementsPerGroup = 1;
            break;
        case GL_422_EXT:
        case GL_422_REV_EXT:
        case GL_422_AVERAGE_EXT:
        case GL_422_REV_AVERAGE_EXT:
        case GL_DEPTH_STENCIL_NV:
        case GL_DEPTH_STENCIL_MESA:
        case GL_YCBCR_MESA:
        case GL_LUMINANCE_ALPHA:
        case GL_LUMINANCE_ALPHA_INTEGER_EXT:
            elementsPerGroup = 2;
            break;
        case GL_RGB:
        case GL_BGR:
        case GL_RGB_INTEGER_EXT:
        case GL_BGR_INTEGER_EXT:
            elementsPerGroup = 3;
            break;
        case GL_RGBA:
        case GL_BGRA:
        case GL_RGBA_INTEGER_EXT:
        case GL_BGRA_INTEGER_EXT:
        case GL_ABGR_EXT:
            elementsPerGroup = 4;
            break;
        default:
            return -1;
        }
        switch (type) {
        case GL_UNSIGNED_BYTE:
        case GL_BYTE:
            bytesPerElement = 1;
            break;
        case GL_UNSIGNED_BYTE_3_3_2:
        case GL_UNSIGNED_BYTE_2_3_3_REV:
            bytesPerElement = 1;
            elementsPerGroup = 1;
            break;
        case GL_UNSIGNED_SHORT:
        case GL_SHORT:
            bytesPerElement = 2;
            break;
        case GL_UNSIGNED_SHORT_5_6_5:
        case GL_UNSIGNED_SHORT_5_6_5_REV:
        case GL_UNSIGNED_SHORT_4_4_4_4:
        case GL_UNSIGNED_SHORT_4_4_4_4_REV:
        case GL_UNSIGNED_SHORT_5_5_5_1:
        case GL_UNSIGNED_SHORT_1_5_5_5_REV:
        case GL_UNSIGNED_SHORT_8_8_APPLE:
        case GL_UNSIGNED_SHORT_8_8_REV_APPLE:
        case GL_UNSIGNED_SHORT_15_1_MESA:
        case GL_UNSIGNED_SHORT_1_15_REV_MESA:
            bytesPerElement = 2;
            elementsPerGroup = 1;
            break;
        case GL_INT:
        case GL_UNSIGNED_INT:
        case GL_FLOAT:
            bytesPerElement = 4;
            break;
        case GL_UNSIGNED_INT_8_8_8_8:
        case GL_UNSIGNED_INT_8_8_8_8_REV:
        case GL_UNSIGNED_INT_10_10_10_2:
        case GL_UNSIGNED_INT_2_10_10_10_REV:
        case GL_UNSIGNED_INT_24_8_NV:
        case GL_UNSIGNED_INT_24_8_MESA:
        case GL_UNSIGNED_INT_8_24_REV_MESA:
            bytesPerElement = 4;
            elementsPerGroup = 1;
            break;
        default:
            return -1;
        }
        /* known safe by the switches above, not checked */
        groupSize = bytesPerElement * elementsPerGroup;
        if (rowLength > 0) {
            groupsPerRow = rowLength;
        }
        else {
            groupsPerRow = w;
        }

        if ((rowSize = safe_mul(groupsPerRow, groupSize)) < 0)
            return -1;
        padding = (rowSize % alignment);
        if (padding) {
            rowSize += alignment - padding;
        }

        if (imageHeight > 0)
            h = imageHeight;
        h = safe_add(h, skipRows);

        imageSize = safe_mul(h, rowSize);

        return safe_mul(safe_add(d, skipImages), imageSize);
    }
}
Graphic_base::Color& Graphic_base::Color::operator+=(Graphic_base::Color& c) {
	for(int i = 0; i < 4; i++)
		comp[i] = safe_add(comp[i], c.comp[i]);
	return *this;
}