1
/*
2
 * $Id$
3
 *
4
 * Copyright (C) 2003-2009 JNode.org
5
 *
6
 * This library is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful, but 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
14
 * License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this library; If not, write to the Free Software Foundation, Inc., 
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
20
21
package org.jnode.vm;
22
23
import org.jnode.annotation.MagicPermission;
24
import org.jnode.annotation.Uninterruptible;
25
26
27
/**
28
 * In MathSupport ldiv and lrem will be used as SoftBytecodes. I.e. normal Java classes that contain ldiv or
29
 * lrem bytecodes will in fact call these Java methods.
30
 *
31
 * @author epr
32
 * @author peda
33
 */
34
@MagicPermission
35
@Uninterruptible
36
public final class MathSupport {
37
38
    /**
39
     * New Implementation
40
     */
41
    public static long ldiv(long num, long den) {
42
        if (num == Long.MIN_VALUE) {
43
            if (den == Long.MIN_VALUE) {
44
                return 1;
45
            } else {
46
                long q = ldiv(num + 1, den);
47
                long r = num + 1 - q * den;
48
                if (Math.abs(r) == Math.abs(den) - 1) {
49
                    return q < 0 ? q - 1 : q + 1;
50
                } else {
51
                    return q;
52
                }
53
            }
54
        }
55
56
        if (den == Long.MIN_VALUE) {
57
            return 0;
58
        }
59
60
        boolean neg = false;
61
        if (num < 0) {
62
            num = -num;
63
            neg = true;
64
        }
65
        if (den < 0) {
66
            den = -den;
67
            neg = !neg;
68
        }
69
        if (num < den) return 0;
70
        if (den == 0) throw new ArithmeticException("Divide by zero");
71
72
        long qBit = 1;
73
        while (den >= 0) {
74
            den = den << 1;
75
            qBit = qBit << 1;
76
        }
77
78
        den >>>= 1;
79
        qBit >>>= 1;
80
81
        long result = 0;
82
        while (qBit != 0) {
83
            if (den <= num) {
84
                result += qBit;
85
                num -= den;
86
            }
87
            den = den >>> 1;
88
            qBit = qBit >>> 1;
89
        }
90
91
        if (neg)
92
            return -result;
93
        return result;
94
    }
95
    /**
96
     * new implementation
97
     */
98
    public static long lrem(long num, long den) {
99
        if (num == Long.MIN_VALUE) {
100
            if (den == Long.MIN_VALUE) {
101
                return 0;
102
            } else {
103
                long r = lrem(num + 1, den);
104
                if (Math.abs(r) == Math.abs(den) - 1) {
105
                    return 0;
106
                } else {
107
                    return r < 0 ? r - 1 : r > 0 ? r + 1 : -1;
108
                }
109
            }
110
        }
111
112
        if (den == Long.MIN_VALUE) {
113
            return num;
114
        }
115
116
        final boolean neg;
117
        if (num < 0) {
118
            num = -num;
119
            neg = true;
120
        } else neg = false;
121
        if (den < 0) {
122
            den = -den;
123
        }
124
        if (num < den) return neg ? -num : num;
125
126
        if (den == 0)
127
            throw new ArithmeticException("Divide by zero");
128
129
        long qBit = 1;
130
        while (den >= 0) {
131
            den <<= 1;
132
            qBit <<= 1;
133
        }
134
135
        den >>>= 1;
136
        qBit >>>= 1;
137
138
        while (qBit != 0) {
139
            if (den <= num) {
140
                num -= den;
141
            }
142
            qBit >>>= 1;
143
            den >>>= 1;
144
        }
145
146
        if (neg)
147
            return -num;
148
        return num;
149
    }
150
}