source: code/trunk/vendor/modernc.org/libc/int128.go@ 822

Last change on this file since 822 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 9.9 KB
RevLine 
[822]1// Copyright 2020 The Libc Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Some code is copied and adjusted from
6// https://github.com/lukechampine/uint128, the original LICENSE file
7// reproduced below in full as of 2021-01-19:
8
9/*
10The MIT License (MIT)
11
12Copyright (c) 2019 Luke Champine
13
14Permission is hereby granted, free of charge, to any person obtaining a copy
15of this software and associated documentation files (the "Software"), to deal
16in the Software without restriction, including without limitation the rights
17to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18copies of the Software, and to permit persons to whom the Software is
19furnished to do so, subject to the following conditions:
20
21The above copyright notice and this permission notice shall be included in
22all copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30THE SOFTWARE.
31*/
32
33package libc // import "modernc.org/libc"
34
35import (
36 mbits "math/bits"
37
38 "modernc.org/mathutil"
39)
40
41type Int128 mathutil.Int128
42
43var (
44 int128Minus1 = Int128{-1, -1}
45 int128Plus1 = Int128{Lo: 1}
46)
47
48func Int128FromFloat32(n float32) Int128 { return Int128(mathutil.NewInt128FromFloat32(n)) }
49func Int128FromFloat64(n float64) Int128 { return Int128(mathutil.NewInt128FromFloat64(n)) }
50func Int128FromInt16(n int16) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
51func Int128FromInt32(n int32) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
52func Int128FromInt64(n int64) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
53func Int128FromInt8(n int8) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
54func Int128FromUint16(n uint16) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
55func Int128FromUint32(n uint32) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
56func Int128FromUint64(n uint64) Int128 { return Int128(mathutil.NewInt128FromUint64(n)) }
57func Int128FromUint8(n uint8) Int128 { return Int128(mathutil.NewInt128FromInt64(int64(n))) }
58func Int128FromUint128(n Uint128) Int128 { return Int128{Lo: int64(n.Lo), Hi: int64(n.Hi)} }
59
60func (n *Int128) LValueDec() { *n = n.Add(int128Minus1) }
61func (n *Int128) LValueInc() { *n = n.Add(int128Plus1) }
62func (n *Int128) LValueShl(c int32) { *n = n.Shl(c) }
63func (n *Int128) LValueShr(c int32) { *n = n.Shr(c) }
64func (n Int128) And(v Int128) Int128 { return Int128{n.Lo & v.Lo, n.Hi & v.Hi} }
65func (n Int128) Cmp(y Int128) int { return mathutil.Int128(n).Cmp(mathutil.Int128(y)) }
66func (n Int128) Int16() int16 { return int16(n.Lo) }
67func (n Int128) Int32() int32 { return int32(n.Lo) }
68func (n Int128) Int64() int64 { return int64(n.Lo) }
69func (n Int128) Int8() int8 { return int8(n.Lo) }
70func (n Int128) Or(v Int128) Int128 { return Int128{n.Lo | v.Lo, n.Hi | v.Hi} }
71func (n Int128) Uint128() (r Uint128) { return Uint128{uint64(n.Lo), uint64(n.Hi)} }
72func (n Int128) Uint16() uint16 { return uint16(n.Lo) }
73func (n Int128) Uint32() uint32 { return uint32(n.Lo) }
74func (n Int128) Uint64() uint64 { return uint64(n.Lo) }
75func (n Int128) Uint8() uint8 { return uint8(n.Lo) }
76func (n Int128) Xor(v Int128) Int128 { return Int128{n.Lo ^ v.Lo, n.Hi ^ v.Hi} }
77
78func (n Int128) Neg() Int128 {
79 n.Lo ^= -1
80 n.Hi ^= -1
81 return n.Add(int128Plus1)
82}
83
84func (n Int128) Float32() float32 {
85 switch n.Hi {
86 case 0:
87 return float32(uint64(n.Lo))
88 case -1:
89 return -float32(uint64(n.Lo))
90 }
91
92 if n.Hi < 0 {
93 n = n.Neg()
94 return -float32(n.Hi)*(1<<64) + float32(uint64(n.Lo))
95 }
96
97 return -float32(n.Hi)*(1<<64) + float32(uint64(n.Lo))
98}
99
100func (n Int128) Float64() float64 {
101 switch n.Hi {
102 case 0:
103 return float64(uint64(n.Lo))
104 case -1:
105 return -float64(uint64(n.Lo))
106 }
107
108 if n.Hi < 0 {
109 n = n.Neg()
110 return -float64(n.Hi)*(1<<64) + float64(uint64(n.Lo))
111 }
112
113 return float64(n.Hi)*(1<<64) + float64(uint64(n.Lo))
114}
115
116func (n Int128) Add(m Int128) (r Int128) {
117 r.Lo = n.Lo + m.Lo
118 r.Hi = n.Hi + m.Hi
119 if uint64(r.Lo) < uint64(n.Lo) {
120 r.Hi++
121 }
122 return r
123}
124
125func (n Int128) Mul(m Int128) Int128 {
126 hi, lo := mbits.Mul64(uint64(n.Lo), uint64(m.Lo))
127 _, p1 := mbits.Mul64(uint64(n.Hi), uint64(m.Lo))
128 _, p3 := mbits.Mul64(uint64(n.Lo), uint64(m.Hi))
129 hi, _ = mbits.Add64(hi, p1, 0)
130 hi, _ = mbits.Add64(hi, p3, 0)
131 return Int128{int64(lo), int64(hi)}
132}
133
134func (n Int128) Shl(c int32) (r Int128) {
135 if c > 64 {
136 r.Lo = 0
137 r.Hi = n.Lo << (c - 64)
138 } else {
139 r.Lo = n.Lo << c
140 r.Hi = n.Hi<<c | n.Lo>>(64-c)
141 }
142 return r
143}
144
145func (n Int128) Shr(c int32) (r Int128) {
146 if c > 64 {
147 r.Lo = n.Hi >> (c - 64)
148 switch {
149 case n.Hi < 0:
150 r.Hi = -1
151 default:
152 r.Hi = 0
153 }
154 } else {
155 r.Lo = n.Lo>>c | n.Hi<<(64-c)
156 r.Hi = n.Hi >> c
157 }
158 return r
159}
160
161type Uint128 mathutil.Uint128
162
163func Uint128FromFloat32(n float32) Uint128 { return Uint128(mathutil.NewUint128FromFloat32(n)) }
164func Uint128FromFloat64(n float64) Uint128 { return Uint128(mathutil.NewUint128FromFloat64(n)) }
165func Uint128FromInt128(n Int128) Uint128 { return Uint128{Lo: uint64(n.Lo), Hi: uint64(n.Hi)} }
166func Uint128FromInt16(n int16) Uint128 { return Uint128FromInt64(int64(n)) }
167func Uint128FromInt32(n int32) Uint128 { return Uint128FromInt64(int64(n)) }
168func Uint128FromInt8(n int8) Uint128 { return Uint128FromInt64(int64(n)) }
169func Uint128FromUint16(n uint16) Uint128 { return Uint128{Lo: uint64(n)} }
170func Uint128FromUint32(n uint32) Uint128 { return Uint128{Lo: uint64(n)} }
171func Uint128FromUint64(n uint64) Uint128 { return Uint128{Lo: n} }
172func Uint128FromUint8(n uint8) Uint128 { return Uint128{Lo: uint64(n)} }
173
174func Uint128FromInt64(n int64) (r Uint128) {
175 r.Lo = uint64(n)
176 if n < 0 {
177 r.Hi = ^uint64(0)
178 }
179 return r
180}
181
182func (n *Uint128) LValueShl(c int32) { *n = n.Shl(c) }
183func (n *Uint128) LValueShr(c int32) { *n = n.Shr(c) }
184func (n Uint128) And(m Uint128) Uint128 { return Uint128{n.Lo & m.Lo, n.Hi & m.Hi} }
185func (n Uint128) Int128() Int128 { return Int128{int64(n.Lo), int64(n.Hi)} }
186func (n Uint128) Int16() int16 { return int16(n.Lo) }
187func (n Uint128) Int32() int32 { return int32(n.Lo) }
188func (n Uint128) Int64() int64 { return int64(n.Lo) }
189func (n Uint128) Int8() int8 { return int8(n.Lo) }
190func (n Uint128) Or(m Uint128) Uint128 { return Uint128{n.Lo | m.Lo, n.Hi | m.Hi} }
191func (n Uint128) Uint16() uint16 { return uint16(n.Lo) }
192func (n Uint128) Uint32() uint32 { return uint32(n.Lo) }
193func (n Uint128) Uint64() uint64 { return n.Lo }
194func (n Uint128) Uint8() uint8 { return uint8(n.Lo) }
195func (n Uint128) Xor(m Uint128) Uint128 { return Uint128{n.Lo ^ m.Lo, n.Hi ^ m.Hi} }
196
197func (n Uint128) Add(m Uint128) (r Uint128) {
198 var carry uint64
199 r.Lo, carry = mbits.Add64(n.Lo, m.Lo, 0)
200 r.Hi, _ = mbits.Add64(n.Hi, m.Hi, carry)
201 return r
202}
203
204func (n Uint128) Mul(m Uint128) Uint128 {
205 hi, lo := mbits.Mul64(n.Lo, m.Lo)
206 _, p1 := mbits.Mul64(n.Hi, m.Lo)
207 _, p3 := mbits.Mul64(n.Lo, m.Hi)
208 hi, _ = mbits.Add64(hi, p1, 0)
209 hi, _ = mbits.Add64(hi, p3, 0)
210 return Uint128{lo, hi}
211}
212
213func (n Uint128) Shr(c int32) (r Uint128) {
214 if c > 64 {
215 r.Lo = n.Hi >> (c - 64)
216 r.Hi = 0
217 } else {
218 r.Lo = n.Lo>>c | n.Hi<<(64-c)
219 r.Hi = n.Hi >> c
220 }
221 return r
222}
223
224func (n Uint128) mulOvf(m Uint128) (_ Uint128, ovf bool) {
225 hi, lo := mbits.Mul64(n.Lo, m.Lo)
226 p0, p1 := mbits.Mul64(n.Hi, m.Lo)
227 p2, p3 := mbits.Mul64(n.Lo, m.Hi)
228 hi, c0 := mbits.Add64(hi, p1, 0)
229 hi, c1 := mbits.Add64(hi, p3, 0)
230 ovf = p0 != 0 || p2 != 0 || c0 != 0 || c1 != 0
231 return Uint128{lo, hi}, ovf
232}
233
234func (n Uint128) quoRem(m Uint128) (q, r Uint128) {
235 if m.Hi == 0 {
236 var r64 uint64
237 q, r64 = n.quoRem64(m.Lo)
238 r = Uint128FromUint64(r64)
239 } else {
240 // generate a "trial quotient," guaranteed to be within 1 of the actual
241 // quotient, then adjust.
242 nz := mbits.LeadingZeros64(m.Hi)
243 v1 := m.Shl(int32(nz))
244 u1 := n.Shr(1)
245 tq, _ := mbits.Div64(u1.Hi, u1.Lo, v1.Hi)
246 tq >>= 63 - nz
247 if tq != 0 {
248 tq--
249 }
250 q = Uint128FromUint64(tq)
251 // calculate remainder using trial quotient, then adjust if remainder is
252 // greater than divisor
253 r = n.Sub(m.mul64(tq))
254 if r.Cmp(m) >= 0 {
255 q = q.add64(1)
256 r = r.Sub(m)
257 }
258 }
259 return
260}
261
262func (n Uint128) quoRem64(m uint64) (q Uint128, r uint64) {
263 if n.Hi < m {
264 q.Lo, r = mbits.Div64(n.Hi, n.Lo, m)
265 } else {
266 q.Hi, r = mbits.Div64(0, n.Hi, m)
267 q.Lo, r = mbits.Div64(r, n.Lo, m)
268 }
269 return
270}
271
272func (n Uint128) Div(m Uint128) (r Uint128) {
273 r, _ = n.quoRem(m)
274 return r
275}
276
277func (n Uint128) Shl(c int32) (r Uint128) {
278 if c > 64 {
279 r.Lo = 0
280 r.Hi = n.Lo << (c - 64)
281 } else {
282 r.Lo = n.Lo << c
283 r.Hi = n.Hi<<c | n.Lo>>(64-c)
284 }
285 return
286}
287
288func (n Uint128) Sub(m Uint128) Uint128 {
289 lo, borrow := mbits.Sub64(n.Lo, m.Lo, 0)
290 hi, _ := mbits.Sub64(n.Hi, m.Hi, borrow)
291 return Uint128{lo, hi}
292}
293
294func (n Uint128) mul64(m uint64) Uint128 {
295 hi, lo := mbits.Mul64(n.Lo, m)
296 _, p1 := mbits.Mul64(n.Hi, m)
297 hi, _ = mbits.Add64(hi, p1, 0)
298 return Uint128{lo, hi}
299}
300
301func (n Uint128) Cmp(m Uint128) int {
302 if n == m {
303 return 0
304 } else if n.Hi < m.Hi || (n.Hi == m.Hi && n.Lo < m.Lo) {
305 return -1
306 } else {
307 return 1
308 }
309}
310
311func (n Uint128) add64(m uint64) Uint128 {
312 lo, carry := mbits.Add64(n.Lo, m, 0)
313 hi, _ := mbits.Add64(n.Hi, 0, carry)
314 return Uint128{lo, hi}
315}
316
317func (n Uint128) Float32() float32 {
318 if n.Hi == 0 {
319 return float32(uint64(n.Lo))
320 }
321
322 return float32(n.Hi)*(1<<64) + float32(uint64(n.Lo))
323}
324
325func (n Uint128) Float64() float64 {
326 if n.Hi == 0 {
327 return float64(uint64(n.Lo))
328 }
329
330 return float64(n.Hi)*(1<<64) + float64(uint64(n.Lo))
331}
Note: See TracBrowser for help on using the repository browser.