/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.vm; import org.jnode.annotation.MagicPermission; import org.jnode.annotation.Uninterruptible; /** * In MathSupport ldiv and lrem will be used as SoftBytecodes. I.e. normal Java classes that contain ldiv or * lrem bytecodes will in fact call these Java methods. * * @author epr * @author peda */ @MagicPermission @Uninterruptible public final class MathSupport { /** * New Implementation */ public static long ldiv(long num, long den) { if (num == Long.MIN_VALUE) { if (den == Long.MIN_VALUE) { return 1; } else { long q = ldiv(num + 1, den); long r = num + 1 - q * den; if (Math.abs(r) == Math.abs(den) - 1) { return q < 0 ? q - 1 : q + 1; } else { return q; } } } if (den == Long.MIN_VALUE) { return 0; } boolean neg = false; if (num < 0) { num = -num; neg = true; } if (den < 0) { den = -den; neg = !neg; } if (num < den) return 0; if (den == 0) throw new ArithmeticException("Divide by zero"); long qBit = 1; while (den >= 0) { den = den << 1; qBit = qBit << 1; } den >>>= 1; qBit >>>= 1; long result = 0; while (qBit != 0) { if (den <= num) { result += qBit; num -= den; } den = den >>> 1; qBit = qBit >>> 1; } if (neg) return -result; return result; } /** * new implementation */ public static long lrem(long num, long den) { if (num == Long.MIN_VALUE) { if (den == Long.MIN_VALUE) { return 0; } else { long r = lrem(num + 1, den); if (Math.abs(r) == Math.abs(den) - 1) { return 0; } else { return r < 0 ? r - 1 : r > 0 ? r + 1 : -1; } } } if (den == Long.MIN_VALUE) { return num; } final boolean neg; if (num < 0) { num = -num; neg = true; } else neg = false; if (den < 0) { den = -den; } if (num < den) return neg ? -num : num; if (den == 0) throw new ArithmeticException("Divide by zero"); long qBit = 1; while (den >= 0) { den <<= 1; qBit <<= 1; } den >>>= 1; qBit >>>= 1; while (qBit != 0) { if (den <= num) { num -= den; } qBit >>>= 1; den >>>= 1; } if (neg) return -num; return num; } }