/
Scalars.kt
147 lines (126 loc) · 4.09 KB
/
Scalars.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package org.openrndr.kartifex.utils
import kotlin.math.PI
import kotlin.math.abs
import kotlin.math.pow
/**
* @author ztellman
*/
object Scalars {
const val SIGNIFICAND_WIDTH = 53
const val MIN_EXPONENT = -1022
const val MAX_EXPONENT = 1023
const val EXP_BIT_MASK = 0x7FF0000000000000L
const val EXP_BIAS = 1023
fun getExponent(d: Double): Int {
/*
* Bitwise convert d to long, mask out exponent bits, shift
* to the right and then subtract out double's bias adjust to
* get true exponent value.
*/
return ((d.toRawBits() and EXP_BIT_MASK shr SIGNIFICAND_WIDTH - 1) - EXP_BIAS).toInt()
}
fun powerOfTwoD(exp:Double) : Double {
return 2.0.pow(exp)
}
fun ulp(d: Double): Double {
var exp: Int = getExponent(d)
return when (exp) {
MAX_EXPONENT + 1 -> abs(d)
MIN_EXPONENT - 1 -> Double.MIN_VALUE
else -> {
//assert(exp <= java.lang.Double.MAX_EXPONENT && exp >= java.lang.Double.MIN_EXPONENT)
// ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
exp = exp - (SIGNIFICAND_WIDTH - 1)
if (exp >= MIN_EXPONENT) {
powerOfTwoD(exp.toDouble())
} else {
// return a subnormal result; left shift integer
// representation of Double.MIN_VALUE appropriate
// number of positions
Double.fromBits(
1L shl
exp - (MIN_EXPONENT - (SIGNIFICAND_WIDTH - 1))
)
}
}
}
}
val MACHINE_EPSILON: Double = ulp(1.0)
const val EPSILON = 1e-14
fun equals(a: Double, b: Double, epsilon: Double): Boolean {
return abs(a - b) < epsilon
}
@Suppress("NAME_SHADOWING")
fun angleEquals(t0: Double, t1: Double, epsilon: Double): Boolean {
var t0 = t0
var t1 = t1
if (t1 < t0) {
val tmp = t1
t1 = t0
t0 = tmp
}
var result = t1 - t0 < epsilon
if (!result) {
t1 -= PI * 2
result = t0 - t1 < epsilon
}
return result
}
fun normalize(a: Double, b: Double, n: Double): Double {
return (n - a) / (b - a)
}
fun lerp(a: Double, b: Double, t: Double): Double {
return a + (b - a) * t
}
fun inside(min: Double, n: Double, max: Double): Boolean {
return min < n && n < max
}
fun clamp(min: Double, n: Double, max: Double): Double {
return if (n <= min) {
min
} else if (n >= max) {
max
} else {
n
}
}
fun normalizationFactor(a: Double, b: Double, c: Double, d: Double): Double {
val maxValue = max(max(a, b), max(c, d))
return if (maxValue == 0.0) {
1.0
} else {
val exponent: Double = getExponent(maxValue).toDouble()
if (exponent < -8 || exponent > 8) 2.0.pow(-exponent) else 1.0
}
}
fun normalizationFactor(a: Double, b: Double, c: Double): Double {
val maxValue = max(a, b, c)
return if (maxValue == 0.0) {
1.0
} else {
val exponent = getExponent(maxValue).toDouble()
if (exponent < -8 || exponent > 8) 2.0.pow(-exponent) else 1.0
}
}
fun normalizationFactor(a: Double, b: Double): Double {
val maxValue = max(a,b)
return if (maxValue == 0.0) {
1.0
} else {
val exponent: Double = getExponent(maxValue).toDouble()
if (exponent < -8 || exponent > 8) 2.0.pow(-exponent) else 1.0
}
}
fun max(a: Double, b: Double): Double {
return if (a < b) b else a
}
fun max(a: Double, b: Double, c: Double): Double {
return max(a, max(b, c))
}
fun min(a: Double, b: Double): Double {
return if (a > b) b else a
}
fun min(a: Double, b: Double, c: Double): Double {
return min(a, min(b, c))
}
}