/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD
modeler, Finite element mesher, Plugin architecture.
Copyright (C) 2004,2005, by EADS CRC
Copyright (C) 2007, by EADS France
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
package org.jcae.mesh.amibe.patch;
/**
* This class implements a 'long long' type for exact geometrical
* computations. As Java has no unsigned types, this is quite tricky,
* but fortunately integer coordinates are in the range [0;2^30] and
* atomic long values are in [-2^60;2^60]. When LongLong have to be
* added, they must be of opposite sign so that this range is not
* bypassed.
*/
class LongLong
{
private long hi, lo;
// 2^31 - 1
private static final long pow31m1 = 0x7fffffffL;
// 2^62 - 1
private static final long pow62m1 = 0x3fffffffffffffffL;
LongLong(long l1, long l2)
{
assert l1 >= 0L : l1;
assert l1 <= 1L << 61 : l1;
// l1 = l1H31 * 2^31 + l1L31, 0 <= l1L31 < 2^31
long l1H31 = l1 >> 31;
long l1L31 = l1 & pow31m1;
boolean minus = false;
assert l2 >= -(1L << 61) : l2;
assert l2 <= 1L << 61 : l2;
if (l2 < 0L)
{
minus = true;
l2 = -l2;
}
// l2 = l2H31 * 2^31 + l2L31, 0 <= l2L31 < 2^31
long l2H31 = l2 >> 31;
long l2L31 = l2 & pow31m1;
// l1 * l2 = l1H31*l2H31 * 2^62 +
// (l1H31*l2L31+l1L31*l2H31) * 2^31 +
// l1L31 * l2L31
// = hi * 2^62 + lo, 0 <= lo < 2^62
long res = l1H31 * l2L31 + l1L31 * l2H31;
hi = (res >> 31) + l1H31 * l2H31;
lo = ((res & pow31m1) << 31) + l1L31 * l2L31;
if (lo >= (1L << 62))
{
hi++;
lo &= pow62m1;
}
if (minus)
{
hi = - hi;
if (lo > 0L)
{
hi--;
lo = (- lo) & pow62m1;
}
}
assert (lo >= 0L && lo < (1L << 62)) : lo;
}
protected final void add(LongLong that)
{
hi += that.hi;
lo += that.lo;
if (lo >= (1L << 62))
{
hi++;
lo &= pow62m1;
}
}
public final boolean isNegative()
{
return (hi < 0L);
}
public boolean isPositive()
{
return (hi > 0L);
}
@Override
public final String toString()
{
return "hi: "+hi+" lo: "+lo;
}
}