Compare commits
12 Commits
Version_1.
...
master
Author | SHA1 | Date |
---|---|---|
Robinson | 23b9a4f7ff | |
Robinson | bc5c28ef08 | |
Robinson | 81588e2a8e | |
Robinson | da9c34b538 | |
Robinson | efcdbf9559 | |
Robinson | e13205166a | |
Robinson | 0ce4bb2e2e | |
Robinson | dc1bfb8371 | |
Robinson | 3bf845f355 | |
Robinson | 0ff5f377d1 | |
Robinson | 5fa2e2aff6 | |
Robinson | db0be638b4 |
7
LICENSE
7
LICENSE
|
@ -21,13 +21,6 @@
|
|||
Lightweight Java Game Library Project
|
||||
Riven
|
||||
|
||||
- Modified hex conversion utility methods -
|
||||
[The Apache Software License, Version 2.0]
|
||||
https://git.dorkbox.com/dorkbox/Utilities
|
||||
https://netty.io
|
||||
Copyright 2014
|
||||
The Netty Project
|
||||
|
||||
- Retrofit - A type-safe HTTP client for Android and Java
|
||||
[The Apache Software License, Version 2.0]
|
||||
https://github.com/square/retrofit
|
||||
|
|
|
@ -17,7 +17,7 @@ Maven Info
|
|||
<dependency>
|
||||
<groupId>com.dorkbox</groupId>
|
||||
<artifactId>Utilities</artifactId>
|
||||
<version>1.45</version>
|
||||
<version>1.48</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
@ -27,7 +27,7 @@ Gradle Info
|
|||
```
|
||||
dependencies {
|
||||
...
|
||||
compile "com.dorkbox:Utilities:1.45"
|
||||
compile "com.dorkbox:Utilities:1.48"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -23,19 +23,19 @@
|
|||
gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS // always show the stacktrace!
|
||||
|
||||
plugins {
|
||||
id("com.dorkbox.GradleUtils") version "3.17"
|
||||
id("com.dorkbox.Licensing") version "2.24"
|
||||
id("com.dorkbox.GradleUtils") version "3.18"
|
||||
id("com.dorkbox.Licensing") version "2.28"
|
||||
id("com.dorkbox.VersionUpdate") version "2.8"
|
||||
id("com.dorkbox.GradlePublish") version "1.18"
|
||||
id("com.dorkbox.GradlePublish") version "1.20"
|
||||
|
||||
kotlin("jvm") version "1.8.0"
|
||||
kotlin("jvm") version "1.9.0"
|
||||
}
|
||||
|
||||
object Extras {
|
||||
// set for the project
|
||||
const val description = "Utilities for use within Java projects"
|
||||
const val group = "com.dorkbox"
|
||||
const val version = "1.45"
|
||||
const val version = "1.48"
|
||||
|
||||
// set as project.ext
|
||||
const val name = "Utilities"
|
||||
|
@ -75,12 +75,6 @@ licensing {
|
|||
author("Riven")
|
||||
}
|
||||
|
||||
extra("Modified hex conversion utility methods", License.APACHE_2) {
|
||||
url(Extras.url)
|
||||
url("https://netty.io")
|
||||
copyright(2014)
|
||||
author("The Netty Project")
|
||||
}
|
||||
extra("Retrofit", License.APACHE_2) {
|
||||
copyright(2020)
|
||||
description("A type-safe HTTP client for Android and Java")
|
||||
|
@ -142,8 +136,6 @@ dependencies {
|
|||
// api("org.slf4j:slf4j-api:2.0.7")
|
||||
|
||||
|
||||
compileOnly("com.fasterxml.uuid:java-uuid-generator:4.1.0")
|
||||
|
||||
// api "com.koloboke:koloboke-api-jdk8:1.0.0"
|
||||
// runtime "com.koloboke:koloboke-impl-jdk8:1.0.0"
|
||||
|
||||
|
|
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
@ -80,10 +80,10 @@ do
|
|||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
@ -143,12 +143,16 @@ fi
|
|||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
|
|
|
@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
|
|||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
|
|
|
@ -138,11 +138,10 @@ class CacheUtil(private val tempDir: String = "cache") {
|
|||
@Throws(IOException::class)
|
||||
fun save(cacheName: String?, fileName: String): File {
|
||||
// if we already have this fileName, reuse it
|
||||
val newFile = if (cacheName == null) {
|
||||
makeCacheFile(fileName)
|
||||
} else {
|
||||
makeCacheFile(cacheName)
|
||||
}
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val cacheName = cacheName ?: fileName
|
||||
|
||||
val newFile = makeCacheFile(cacheName)
|
||||
|
||||
// if this file already exists (via HASH), we just reuse what is saved on disk.
|
||||
if (newFile.canRead() && newFile.isFile) {
|
||||
|
@ -184,11 +183,10 @@ class CacheUtil(private val tempDir: String = "cache") {
|
|||
@Throws(IOException::class)
|
||||
fun save(cacheName: String?, fileResource: URL): File {
|
||||
// if we already have this fileName, reuse it
|
||||
val newFile = if (cacheName == null) {
|
||||
makeCacheFile(fileResource.path)
|
||||
} else {
|
||||
makeCacheFile(cacheName)
|
||||
}
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val cacheName = cacheName ?: fileResource.path
|
||||
|
||||
val newFile = makeCacheFile(cacheName)
|
||||
|
||||
// if this file already exists (via HASH), we just reuse what is saved on disk.
|
||||
if (newFile.canRead() && newFile.isFile) {
|
||||
|
@ -218,11 +216,10 @@ class CacheUtil(private val tempDir: String = "cache") {
|
|||
@Throws(IOException::class)
|
||||
fun save(cacheName: String?, fileStream: InputStream): File {
|
||||
// if we already have this fileName, reuse it
|
||||
val newFile = if (cacheName == null) {
|
||||
makeCacheFile(createNameAsHash(fileStream))
|
||||
} else {
|
||||
makeCacheFile(cacheName)
|
||||
}
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val cacheName = cacheName ?: createNameAsHash(fileStream)
|
||||
|
||||
val newFile = makeCacheFile(cacheName)
|
||||
|
||||
// if this file already exists (via HASH), we just reuse what is saved on disk.
|
||||
return if (newFile.canRead() && newFile.isFile) {
|
||||
|
@ -239,13 +236,7 @@ class CacheUtil(private val tempDir: String = "cache") {
|
|||
* @return the full path of the resource copied to disk, or NULL if invalid
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
private fun makeFileViaStream(cacheName: String?, resourceStream: InputStream?): File {
|
||||
if (resourceStream == null) {
|
||||
throw NullPointerException("resourceStream")
|
||||
}
|
||||
if (cacheName == null) {
|
||||
throw NullPointerException("cacheName")
|
||||
}
|
||||
private fun makeFileViaStream(cacheName: String, resourceStream: InputStream): File {
|
||||
val newFile = makeCacheFile(cacheName)
|
||||
|
||||
// if this file already exists (via HASH), we just reuse what is saved on disk.
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package dorkbox.util
|
||||
|
||||
import dorkbox.os.OS.LINE_SEPARATOR
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
@ -27,7 +26,7 @@ object Sys {
|
|||
/**
|
||||
* Gets the version number.
|
||||
*/
|
||||
val version = "1.45"
|
||||
val version = "1.48"
|
||||
|
||||
init {
|
||||
// Add this project to the updates system, which verifies this class + UUID + version information
|
||||
|
@ -39,52 +38,7 @@ object Sys {
|
|||
const val MEGABYTE = 1024 * KILOBYTE
|
||||
const val GIGABYTE = 1024 * MEGABYTE
|
||||
const val TERABYTE = 1024L * GIGABYTE
|
||||
val HEX_CHARS = charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')
|
||||
|
||||
fun convertStringToChars(string: String): CharArray {
|
||||
val charArray = string.toCharArray()
|
||||
eraseString(string)
|
||||
return charArray
|
||||
}
|
||||
|
||||
fun eraseString(string: String?) {
|
||||
// You can change the value of the inner char[] using reflection.
|
||||
//
|
||||
// You must be careful to either change it with an array of the same length,
|
||||
// or to also update the count field.
|
||||
//
|
||||
// If you want to be able to use it as an entry in a set or as a value in map,
|
||||
// you will need to recalculate the hash code and set the value of the hashCode field.
|
||||
try {
|
||||
val valueField = String::class.java.getDeclaredField("value")
|
||||
valueField.isAccessible = true
|
||||
val chars = valueField[string] as CharArray
|
||||
Arrays.fill(chars, '*') // asterisk it out in case of GC not picking up the old char array.
|
||||
valueField[string] = CharArray(0) // replace it.
|
||||
|
||||
// set count to 0
|
||||
try {
|
||||
// newer versions of java don't have this field
|
||||
val countField = String::class.java.getDeclaredField("count")
|
||||
countField.isAccessible = true
|
||||
countField[string] = 0
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
|
||||
// set hash to 0
|
||||
val hashField = String::class.java.getDeclaredField("hash")
|
||||
hashField.isAccessible = true
|
||||
hashField[string] = 0
|
||||
} catch (e: SecurityException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: NoSuchFieldException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: IllegalArgumentException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: IllegalAccessException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FROM: https://www.cqse.eu/en/blog/string-replace-performance/
|
||||
|
@ -163,22 +117,22 @@ object Sys {
|
|||
fun getTimePretty(nanoSeconds: Long): String {
|
||||
val unit: TimeUnit
|
||||
val text: String
|
||||
if (TimeUnit.DAYS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
if (TimeUnit.DAYS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.DAYS
|
||||
text = "d"
|
||||
} else if (TimeUnit.HOURS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
} else if (TimeUnit.HOURS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.HOURS
|
||||
text = "h"
|
||||
} else if (TimeUnit.MINUTES.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
} else if (TimeUnit.MINUTES.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.MINUTES
|
||||
text = "min"
|
||||
} else if (TimeUnit.SECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
text = "m"
|
||||
} else if (TimeUnit.SECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.SECONDS
|
||||
text = "s"
|
||||
} else if (TimeUnit.MILLISECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
} else if (TimeUnit.MILLISECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.MILLISECONDS
|
||||
text = "ms"
|
||||
} else if (TimeUnit.MICROSECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
} else if (TimeUnit.MICROSECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.MICROSECONDS
|
||||
text = "\u03bcs" // μs
|
||||
} else {
|
||||
|
@ -188,7 +142,16 @@ object Sys {
|
|||
|
||||
// convert the unit into the largest time unit possible (since that is often what makes sense)
|
||||
val value = nanoSeconds.toDouble() / TimeUnit.NANOSECONDS.convert(1, unit)
|
||||
return String.format("%.4g$text", value)
|
||||
|
||||
return if (value < 10) {
|
||||
String.format("%.1g $text", value)
|
||||
} else if (value < 100) {
|
||||
String.format("%.2g $text", value)
|
||||
} else if (value < 1000) {
|
||||
String.format("%.3g $text", value)
|
||||
} else {
|
||||
String.format("%.4g $text", value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,22 +160,22 @@ object Sys {
|
|||
fun getTimePrettyFull(nanoSeconds: Long): String {
|
||||
val unit: TimeUnit
|
||||
var text: String
|
||||
if (TimeUnit.DAYS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
if (TimeUnit.DAYS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.DAYS
|
||||
text = "day"
|
||||
} else if (TimeUnit.HOURS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
} else if (TimeUnit.HOURS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.HOURS
|
||||
text = "hour"
|
||||
} else if (TimeUnit.MINUTES.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
} else if (TimeUnit.MINUTES.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.MINUTES
|
||||
text = "minute"
|
||||
} else if (TimeUnit.SECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
} else if (TimeUnit.SECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.SECONDS
|
||||
text = "second"
|
||||
} else if (TimeUnit.MILLISECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
} else if (TimeUnit.MILLISECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.MILLISECONDS
|
||||
text = "milli-second"
|
||||
} else if (TimeUnit.MICROSECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0) {
|
||||
} else if (TimeUnit.MICROSECONDS.convert(nanoSeconds, TimeUnit.NANOSECONDS) > 0L) {
|
||||
unit = TimeUnit.MICROSECONDS
|
||||
text = "micro-second"
|
||||
} else {
|
||||
|
@ -225,7 +188,16 @@ object Sys {
|
|||
if (value > 1.0) {
|
||||
text += "s"
|
||||
}
|
||||
return String.format("%.4g $text", value)
|
||||
|
||||
return if (value < 10) {
|
||||
String.format("%.1g $text", value)
|
||||
} else if (value < 100) {
|
||||
String.format("%.2g $text", value)
|
||||
} else if (value < 1000) {
|
||||
String.format("%.3g $text", value)
|
||||
} else {
|
||||
String.format("%.4g $text", value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Throwable> throwException0(t: Throwable) {
|
||||
|
@ -245,6 +217,7 @@ object Sys {
|
|||
*
|
||||
* @return "" if there is no extension
|
||||
*/
|
||||
@Deprecated("Use kotlin")
|
||||
fun getExtension(fileName: String): String {
|
||||
val dot = fileName.lastIndexOf('.')
|
||||
return if (dot > -1) {
|
||||
|
@ -254,10 +227,10 @@ object Sys {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the contents of the input stream to a byte array.
|
||||
*/
|
||||
@Deprecated("Use kotlin")
|
||||
@Throws(IOException::class)
|
||||
fun getBytesFromStream(inputStream: InputStream): ByteArray {
|
||||
val baos = ByteArrayOutputStream(8192)
|
||||
|
@ -271,6 +244,7 @@ object Sys {
|
|||
return baos.toByteArray()
|
||||
}
|
||||
|
||||
@Deprecated("Use kotlin")
|
||||
@JvmOverloads
|
||||
fun copyBytes(src: ByteArray, position: Int = 0): ByteArray {
|
||||
val length = src.size - position
|
||||
|
@ -279,6 +253,7 @@ object Sys {
|
|||
return b
|
||||
}
|
||||
|
||||
@Deprecated("Use kotlin")
|
||||
fun concatBytes(vararg arrayBytes: ByteArray): ByteArray {
|
||||
var length = 0
|
||||
for (bytes in arrayBytes) {
|
||||
|
@ -292,272 +267,46 @@ object Sys {
|
|||
}
|
||||
return concatBytes
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun bytesToHex(bytes: ByteArray, startPosition: Int = 0, length: Int = bytes.size, padding: Boolean = false): String {
|
||||
val endPosition = startPosition + length
|
||||
return if (padding) {
|
||||
val hexString = CharArray(3 * length)
|
||||
var j = 0
|
||||
for (i in startPosition until endPosition) {
|
||||
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0xF0 shr 4]
|
||||
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0x0F]
|
||||
hexString[j++] = ' '
|
||||
}
|
||||
String(hexString)
|
||||
} else {
|
||||
val hexString = CharArray(2 * length)
|
||||
var j = 0
|
||||
for (i in startPosition until endPosition) {
|
||||
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0xF0 shr 4]
|
||||
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0x0F]
|
||||
}
|
||||
String(hexString)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an ASCII character representing a hexadecimal
|
||||
* value into its integer equivalent.
|
||||
*/
|
||||
fun hexByteToInt(b: Byte): Int {
|
||||
return when (b.toInt()) {
|
||||
'0'.code -> 0
|
||||
'1'.code -> 1
|
||||
'2'.code -> 2
|
||||
'3'.code -> 3
|
||||
'4'.code -> 4
|
||||
'5'.code -> 5
|
||||
'6'.code -> 6
|
||||
'7'.code -> 7
|
||||
'8'.code -> 8
|
||||
'9'.code -> 9
|
||||
'A'.code, 'a'.code -> 10
|
||||
'B'.code, 'b'.code -> 11
|
||||
'C'.code, 'c'.code -> 12
|
||||
'D'.code, 'd'.code -> 13
|
||||
'E'.code, 'e'.code -> 14
|
||||
'F'.code, 'f'.code -> 15
|
||||
else -> throw IllegalArgumentException("Error decoding byte")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an ASCII character representing a hexadecimal
|
||||
* value into its integer equivalent.
|
||||
*/
|
||||
fun hexCharToInt(b: Char): Int {
|
||||
return when (b) {
|
||||
'0' -> 0
|
||||
'1' -> 1
|
||||
'2' -> 2
|
||||
'3' -> 3
|
||||
'4' -> 4
|
||||
'5' -> 5
|
||||
'6' -> 6
|
||||
'7' -> 7
|
||||
'8' -> 8
|
||||
'9' -> 9
|
||||
'A', 'a' -> 10
|
||||
'B', 'b' -> 11
|
||||
'C', 'c' -> 12
|
||||
'D', 'd' -> 13
|
||||
'E', 'e' -> 14
|
||||
'F', 'f' -> 15
|
||||
else -> throw IllegalArgumentException("Error decoding byte")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A 4-digit hex result.
|
||||
*/
|
||||
fun hex4(c: Char, sb: StringBuilder) {
|
||||
sb.append(HEX_CHARS[c.code and 0xF000 shr 12])
|
||||
sb.append(HEX_CHARS[c.code and 0x0F00 shr 8])
|
||||
sb.append(HEX_CHARS[c.code and 0x00F0 shr 4])
|
||||
sb.append(HEX_CHARS[c.code and 0x000F])
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the byte array as a series of
|
||||
* hexadecimal characters.
|
||||
*
|
||||
* @param bytes byte array to convert
|
||||
* @return a string representation of the byte array as a series of
|
||||
* hexadecimal characters
|
||||
*/
|
||||
fun toHexString(bytes: ByteArray): String {
|
||||
val hexString = CharArray(2 * bytes.size)
|
||||
var j = 0
|
||||
for (i in bytes.indices) {
|
||||
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0xF0 shr 4]
|
||||
hexString[j++] = HEX_CHARS[bytes[i].toInt() and 0x0F]
|
||||
}
|
||||
return String(hexString)
|
||||
}
|
||||
|
||||
/**
|
||||
* from netty 4.1, apache 2.0, https://netty.io
|
||||
*/
|
||||
fun hexToByte(s: CharSequence, pos: Int): Byte {
|
||||
val hi = hexCharToInt(s[pos])
|
||||
val lo = hexCharToInt(s[pos + 1])
|
||||
require(!(hi == -1 || lo == -1)) {
|
||||
String.format(
|
||||
"invalid hex byte '%s' at index %d of '%s'", s.subSequence(pos, pos + 2), pos, s
|
||||
)
|
||||
}
|
||||
return ((hi shl 4) + lo).toByte()
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a string with [hex dump](http://en.wikipedia.org/wiki/Hex_dump)
|
||||
*
|
||||
* @param hex a [CharSequence] which contains the hex dump
|
||||
*/
|
||||
fun hexToBytes(hex: CharSequence): ByteArray {
|
||||
return hexToBytes(hex, 0, hex.length)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes part of a string with [hex dump](http://en.wikipedia.org/wiki/Hex_dump)
|
||||
*
|
||||
* from netty 4.1, apache 2.0, https://netty.io
|
||||
*
|
||||
* @param hexDump a [CharSequence] which contains the hex dump
|
||||
* @param fromIndex start of hex dump in `hexDump`
|
||||
* @param length hex string length
|
||||
*/
|
||||
fun hexToBytes(hexDump: CharSequence, fromIndex: Int, length: Int): ByteArray {
|
||||
require(!(length < 0 || length and 1 != 0)) { "length: $length" }
|
||||
if (length == 0) {
|
||||
return ByteArray(0)
|
||||
}
|
||||
val bytes = ByteArray(length ushr 1)
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
bytes[i ushr 1] = hexToByte(hexDump, fromIndex + i)
|
||||
i += 2
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun encodeStringArray(array: List<String>): ByteArray {
|
||||
var length = 0
|
||||
for (s in array) {
|
||||
val bytes = s.toByteArray()
|
||||
length += bytes.size
|
||||
}
|
||||
if (length == 0) {
|
||||
return ByteArray(0)
|
||||
}
|
||||
val bytes = ByteArray(length + array.size)
|
||||
length = 0
|
||||
for (s in array) {
|
||||
val sBytes = s.toByteArray()
|
||||
System.arraycopy(sBytes, 0, bytes, length, sBytes.size)
|
||||
length += sBytes.size
|
||||
bytes[length++] = 0x01.toByte()
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
|
||||
fun decodeStringArray(bytes: ByteArray): ArrayList<String> {
|
||||
val length = bytes.size
|
||||
var position = 0
|
||||
val token = 0x01.toByte()
|
||||
val list = ArrayList<String>(0)
|
||||
var last = 0
|
||||
while (last + position < length) {
|
||||
val b = bytes[last + position++]
|
||||
if (b == token) {
|
||||
val xx = ByteArray(position - 1)
|
||||
System.arraycopy(bytes, last, xx, 0, position - 1)
|
||||
list.add(String(xx))
|
||||
last += position
|
||||
position = 0
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun printArrayRaw(bytes: ByteArray, lineLength: Int = 0): String {
|
||||
return if (lineLength > 0) {
|
||||
val length = bytes.size
|
||||
val comma = length - 1
|
||||
val builder = StringBuilder(length + length / lineLength)
|
||||
for (i in 0 until length) {
|
||||
builder.append(bytes[i].toInt())
|
||||
if (i < comma) {
|
||||
builder.append(",")
|
||||
}
|
||||
if (i > 0 && i % lineLength == 0) {
|
||||
builder.append(LINE_SEPARATOR)
|
||||
}
|
||||
}
|
||||
builder.toString()
|
||||
} else {
|
||||
val length = bytes.size
|
||||
val comma = length - 1
|
||||
val builder = StringBuilder(length + length)
|
||||
for (i in 0 until length) {
|
||||
builder.append(bytes[i].toInt())
|
||||
if (i < comma) {
|
||||
builder.append(",")
|
||||
}
|
||||
}
|
||||
builder.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun printArray(bytes: ByteArray, length: Int = bytes.size, includeByteCount: Boolean = true) {
|
||||
printArray(bytes, 0, length, includeByteCount, 40, null)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun printArray(
|
||||
bytes: ByteArray,
|
||||
inputOffset: Int,
|
||||
length: Int,
|
||||
includeByteCount: Boolean,
|
||||
lineLength: Int = 40,
|
||||
header: String? = null
|
||||
) {
|
||||
val comma = length - 1
|
||||
var builderLength = length + comma + 2
|
||||
if (includeByteCount) {
|
||||
builderLength += 7 + Integer.toString(length).length
|
||||
}
|
||||
if (lineLength > 0) {
|
||||
builderLength += length / lineLength
|
||||
}
|
||||
if (header != null) {
|
||||
builderLength += header.length + 2
|
||||
}
|
||||
val builder = StringBuilder(builderLength)
|
||||
if (header != null) {
|
||||
builder.append(header).append(LINE_SEPARATOR)
|
||||
}
|
||||
if (includeByteCount) {
|
||||
builder.append("Bytes: ").append(length).append(LINE_SEPARATOR)
|
||||
}
|
||||
builder.append("{")
|
||||
for (i in inputOffset until length) {
|
||||
builder.append(bytes[i].toInt())
|
||||
if (i < comma) {
|
||||
builder.append(",")
|
||||
}
|
||||
if (i > inputOffset && lineLength > 0 && i % lineLength == 0) {
|
||||
builder.append(LINE_SEPARATOR)
|
||||
}
|
||||
}
|
||||
builder.append("}")
|
||||
System.err.println(builder.toString())
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase the contents of a string, in-memory. This has no effect if the string has been interned.
|
||||
*/
|
||||
fun String.eraseString() {
|
||||
// You can change the value of the inner char[] using reflection.
|
||||
//
|
||||
// You must be careful to either change it with an array of the same length,
|
||||
// or to also update the count field.
|
||||
//
|
||||
// If you want to be able to use it as an entry in a set or as a value in map,
|
||||
// you will need to recalculate the hash code and set the value of the hashCode field.
|
||||
try {
|
||||
val valueField = String::class.java.getDeclaredField("value")
|
||||
valueField.isAccessible = true
|
||||
val chars = valueField[this] as CharArray
|
||||
Arrays.fill(chars, '*') // asterisk it out in case of GC not picking up the old char array.
|
||||
valueField[this] = CharArray(0) // replace it.
|
||||
|
||||
// set count to 0
|
||||
try {
|
||||
// newer versions of java don't have this field
|
||||
val countField = String::class.java.getDeclaredField("count")
|
||||
countField.isAccessible = true
|
||||
countField[this] = 0
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
|
||||
// set hash to 0
|
||||
val hashField = String::class.java.getDeclaredField("hash")
|
||||
hashField.isAccessible = true
|
||||
hashField[this] = 0
|
||||
} catch (e: SecurityException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: NoSuchFieldException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: IllegalArgumentException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: IllegalAccessException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,277 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class MersenneTwisterFastTest {
|
||||
|
||||
@Test
|
||||
public void mersenneTwisterTest() throws IOException {
|
||||
int j;
|
||||
|
||||
MersenneTwisterFast r;
|
||||
|
||||
// CORRECTNESS TEST
|
||||
// COMPARE WITH
|
||||
// http://www.math.keio.ac.jp/matumoto/CODES/MT2002/mt19937ar.out
|
||||
|
||||
r = new MersenneTwisterFast(new int[] {0x123,0x234,0x345,0x456});
|
||||
// System.out.println("Output of MersenneTwisterFast with new (2002/1/26) seeding mechanism");
|
||||
for (j = 0; j < 1000; j++) {
|
||||
// first, convert the int from signed to "unsigned"
|
||||
long l = r.nextInt();
|
||||
if (l < 0) {
|
||||
l += 4294967296L; // max int value
|
||||
}
|
||||
String s = String.valueOf(l);
|
||||
while (s.length() < 10) {
|
||||
s = " " + s; // buffer
|
||||
}
|
||||
System.out.print(s + " ");
|
||||
if (j % 5 == 4) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
// SPEED TEST
|
||||
|
||||
final long SEED = 4357;
|
||||
|
||||
int xx;
|
||||
long ms;
|
||||
System.out.println("\nTime to test grabbing 100000000 ints");
|
||||
|
||||
Random rr = new Random(SEED);
|
||||
xx = 0;
|
||||
ms = System.currentTimeMillis();
|
||||
for (j = 0; j < 100000000; j++) {
|
||||
xx += rr.nextInt();
|
||||
}
|
||||
System.out.println("java.util.Random: " + (System.currentTimeMillis() - ms) + " Ignore this: " + xx);
|
||||
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
ms = System.currentTimeMillis();
|
||||
xx = 0;
|
||||
for (j = 0; j < 100000000; j++) {
|
||||
xx += r.nextInt();
|
||||
}
|
||||
System.out.println("Mersenne Twister Fast: " + (System.currentTimeMillis() - ms) + " Ignore this: "
|
||||
+ xx);
|
||||
|
||||
// TEST TO COMPARE TYPE CONVERSION BETWEEN
|
||||
// MersenneTwisterFast.java AND MersenneTwister.java
|
||||
|
||||
boolean test = false;
|
||||
System.out.println("\nGrab the first 1000 booleans");
|
||||
ms = System.currentTimeMillis();
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
for (j = 0; j < 1000; j++) {
|
||||
// System.out.print(r.nextBoolean() + " ");
|
||||
test = r.nextBoolean();
|
||||
if (j % 8 == 7) {
|
||||
// System.out.println();
|
||||
test = false;
|
||||
}
|
||||
}
|
||||
if (!(j % 8 == 7)) {
|
||||
// System.out.println();
|
||||
test = true;
|
||||
}
|
||||
|
||||
System.out.println("Mersenne Twister Fast: " + (System.currentTimeMillis() - ms) + " Ignore this: "
|
||||
+ xx + "" + test);
|
||||
|
||||
System.out.println("\nGrab 1000 booleans of increasing probability using nextBoolean(double)");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
ms = System.currentTimeMillis();
|
||||
for (j = 0; j < 1000; j++) {
|
||||
// System.out.print(r.nextBoolean(j / 999.0) + " ");
|
||||
test = r.nextBoolean(j / 999.0);
|
||||
if (j % 8 == 7) {
|
||||
// System.out.println();
|
||||
test = false;
|
||||
}
|
||||
}
|
||||
if (!(j % 8 == 7)) {
|
||||
// System.out.println();
|
||||
test = true;
|
||||
}
|
||||
|
||||
System.out.println("Mersenne Twister Fast: " + (System.currentTimeMillis() - ms) + " Ignore this: "
|
||||
+ xx + "" + test);
|
||||
|
||||
System.out.println("\nGrab 1000 booleans of increasing probability using nextBoolean(float)");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
ms = System.currentTimeMillis();
|
||||
for (j = 0; j < 1000; j++) {
|
||||
// System.out.print(r.nextBoolean(j / 999.0f) + " ");
|
||||
test = r.nextBoolean(j / 999.0f);
|
||||
if (j % 8 == 7) {
|
||||
test = false;
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 8 == 7)) {
|
||||
// System.out.println();
|
||||
test = true;
|
||||
}
|
||||
|
||||
System.out.println("Mersenne Twister Fast: " + (System.currentTimeMillis() - ms) + " Ignore this: "
|
||||
+ xx + "" + test);
|
||||
|
||||
|
||||
byte[] bytes = new byte[1000];
|
||||
System.out.println("\nGrab the first 1000 bytes using nextBytes");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
r.nextBytes(bytes);
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print(bytes[j] + " ");
|
||||
if (j % 16 == 15) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 16 == 15)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
byte b;
|
||||
System.out.println("\nGrab the first 1000 bytes -- must be same as nextBytes");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print((b = r.nextByte()) + " ");
|
||||
if (b != bytes[j]) {
|
||||
System.out.print("BAD ");
|
||||
}
|
||||
if (j % 16 == 15) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 16 == 15)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("\nGrab the first 1000 shorts");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print(r.nextShort() + " ");
|
||||
if (j % 8 == 7) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 8 == 7)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("\nGrab the first 1000 ints");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print(r.nextInt() + " ");
|
||||
if (j % 4 == 3) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 4 == 3)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("\nGrab the first 1000 ints of different sizes");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
int max = 1;
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print(r.nextInt(max) + " ");
|
||||
max *= 2;
|
||||
if (max <= 0) {
|
||||
max = 1;
|
||||
}
|
||||
if (j % 4 == 3) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 4 == 3)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("\nGrab the first 1000 longs");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print(r.nextLong() + " ");
|
||||
if (j % 3 == 2) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 3 == 2)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("\nGrab the first 1000 longs of different sizes");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
long max2 = 1;
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print(r.nextLong(max2) + " ");
|
||||
max2 *= 2;
|
||||
if (max2 <= 0) {
|
||||
max2 = 1;
|
||||
}
|
||||
if (j % 4 == 3) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 4 == 3)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("\nGrab the first 1000 floats");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print(r.nextFloat() + " ");
|
||||
if (j % 4 == 3) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 4 == 3)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("\nGrab the first 1000 doubles");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print(r.nextDouble() + " ");
|
||||
if (j % 3 == 2) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 3 == 2)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("\nGrab the first 1000 gaussian doubles");
|
||||
r = new MersenneTwisterFast(SEED);
|
||||
for (j = 0; j < 1000; j++) {
|
||||
System.out.print(r.nextGaussian() + " ");
|
||||
if (j % 3 == 2) {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
if (!(j % 3 == 2)) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* Copyright 2015 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.util
|
||||
|
||||
import org.junit.Test
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
class MersenneTwisterFastTest {
|
||||
@Test
|
||||
@Throws(IOException::class)
|
||||
fun mersenneTwisterTest() {
|
||||
var j: Int
|
||||
var r: MersenneTwisterFast
|
||||
|
||||
// CORRECTNESS TEST
|
||||
// COMPARE WITH
|
||||
// http://www.math.keio.ac.jp/matumoto/CODES/MT2002/mt19937ar.out
|
||||
r = MersenneTwisterFast(intArrayOf(0x123, 0x234, 0x345, 0x456))
|
||||
// System.out.println("Output of MersenneTwisterFast with new (2002/1/26) seeding mechanism");
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
|
||||
// first, convert the int from signed to "unsigned"
|
||||
var l = r.nextInt().toLong()
|
||||
if (l < 0) {
|
||||
l += 4294967296L // max int value
|
||||
}
|
||||
var s = l.toString()
|
||||
while (s.length < 10) {
|
||||
s = " $s" // buffer
|
||||
}
|
||||
print("$s ")
|
||||
if (j % 5 == 4) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
|
||||
// SPEED TEST
|
||||
val SEED: Long = 4357
|
||||
var xx: Int
|
||||
var ms: Long
|
||||
println("\nTime to test grabbing 100000000 ints")
|
||||
val rr = Random(SEED)
|
||||
xx = 0
|
||||
ms = System.currentTimeMillis()
|
||||
j = 0
|
||||
while (j < 100000000) {
|
||||
xx += rr.nextInt()
|
||||
j++
|
||||
}
|
||||
println("java.util.Random: " + (System.currentTimeMillis() - ms) + " Ignore this: " + xx)
|
||||
r = MersenneTwisterFast(SEED)
|
||||
ms = System.currentTimeMillis()
|
||||
xx = 0
|
||||
j = 0
|
||||
while (j < 100000000) {
|
||||
xx += r.nextInt()
|
||||
j++
|
||||
}
|
||||
println(
|
||||
"Mersenne Twister Fast: " + (System.currentTimeMillis() - ms) + " Ignore this: " + xx
|
||||
)
|
||||
|
||||
// TEST TO COMPARE TYPE CONVERSION BETWEEN
|
||||
// MersenneTwisterFast.java AND MersenneTwister.java
|
||||
var test = false
|
||||
println("\nGrab the first 1000 booleans")
|
||||
ms = System.currentTimeMillis()
|
||||
r = MersenneTwisterFast(SEED)
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
|
||||
// System.out.print(r.nextBoolean() + " ");
|
||||
test = r.nextBoolean()
|
||||
if (j % 8 == 7) {
|
||||
// System.out.println();
|
||||
test = false
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 8 != 7) {
|
||||
// System.out.println();
|
||||
test = true
|
||||
}
|
||||
println(
|
||||
"Mersenne Twister Fast: " + (System.currentTimeMillis() - ms) + " Ignore this: " + xx + "" + test
|
||||
)
|
||||
println("\nGrab 1000 booleans of increasing probability using nextBoolean(double)")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
ms = System.currentTimeMillis()
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
|
||||
// System.out.print(r.nextBoolean(j / 999.0) + " ");
|
||||
test = r.nextBoolean(j / 999.0)
|
||||
if (j % 8 == 7) {
|
||||
// System.out.println();
|
||||
test = false
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 8 != 7) {
|
||||
// System.out.println();
|
||||
test = true
|
||||
}
|
||||
println(
|
||||
"Mersenne Twister Fast: " + (System.currentTimeMillis() - ms) + " Ignore this: " + xx + "" + test
|
||||
)
|
||||
println("\nGrab 1000 booleans of increasing probability using nextBoolean(float)")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
ms = System.currentTimeMillis()
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
|
||||
// System.out.print(r.nextBoolean(j / 999.0f) + " ");
|
||||
test = r.nextBoolean(j / 999.0f)
|
||||
if (j % 8 == 7) {
|
||||
test = false
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 8 != 7) {
|
||||
// System.out.println();
|
||||
test = true
|
||||
}
|
||||
println(
|
||||
"Mersenne Twister Fast: " + (System.currentTimeMillis() - ms) + " Ignore this: " + xx + "" + test
|
||||
)
|
||||
val bytes = ByteArray(1000)
|
||||
println("\nGrab the first 1000 bytes using nextBytes")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
r.nextBytes(bytes)
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(bytes[j].toString() + " ")
|
||||
if (j % 16 == 15) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 16 != 15) {
|
||||
println()
|
||||
}
|
||||
var b: Byte
|
||||
println("\nGrab the first 1000 bytes -- must be same as nextBytes")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(r.nextByte().also { b = it }.toString() + " ")
|
||||
if (b != bytes[j]) {
|
||||
print("BAD ")
|
||||
}
|
||||
if (j % 16 == 15) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 16 != 15) {
|
||||
println()
|
||||
}
|
||||
println("\nGrab the first 1000 shorts")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(r.nextShort().toString() + " ")
|
||||
if (j % 8 == 7) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 8 != 7) {
|
||||
println()
|
||||
}
|
||||
println("\nGrab the first 1000 ints")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(r.nextInt().toString() + " ")
|
||||
if (j % 4 == 3) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 4 != 3) {
|
||||
println()
|
||||
}
|
||||
println("\nGrab the first 1000 ints of different sizes")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
var max = 1
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(r.nextInt(max).toString() + " ")
|
||||
max *= 2
|
||||
if (max <= 0) {
|
||||
max = 1
|
||||
}
|
||||
if (j % 4 == 3) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 4 != 3) {
|
||||
println()
|
||||
}
|
||||
println("\nGrab the first 1000 longs")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(r.nextLong().toString() + " ")
|
||||
if (j % 3 == 2) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 3 != 2) {
|
||||
println()
|
||||
}
|
||||
println("\nGrab the first 1000 longs of different sizes")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
var max2: Long = 1
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(r.nextLong(max2).toString() + " ")
|
||||
max2 *= 2
|
||||
if (max2 <= 0) {
|
||||
max2 = 1
|
||||
}
|
||||
if (j % 4 == 3) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 4 != 3) {
|
||||
println()
|
||||
}
|
||||
println("\nGrab the first 1000 floats")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(r.nextFloat().toString() + " ")
|
||||
if (j % 4 == 3) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 4 != 3) {
|
||||
println()
|
||||
}
|
||||
println("\nGrab the first 1000 doubles")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(r.nextDouble().toString() + " ")
|
||||
if (j % 3 == 2) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 3 != 2) {
|
||||
println()
|
||||
}
|
||||
println("\nGrab the first 1000 gaussian doubles")
|
||||
r = MersenneTwisterFast(SEED)
|
||||
j = 0
|
||||
while (j < 1000) {
|
||||
print(r.nextGaussian().toString() + " ")
|
||||
if (j % 3 == 2) {
|
||||
println()
|
||||
}
|
||||
j++
|
||||
}
|
||||
if (j % 3 != 2) {
|
||||
println()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2023 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.util
|
||||
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.*
|
||||
|
||||
class TimeTest {
|
||||
@Test
|
||||
fun time() {
|
||||
TimeUnit.DAYS.toNanos(3).also {
|
||||
Assert.assertEquals("3 days", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
TimeUnit.DAYS.toNanos(30).also {
|
||||
Assert.assertEquals("30 days", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
TimeUnit.DAYS.toNanos(300).also {
|
||||
Assert.assertEquals("300 days", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
TimeUnit.DAYS.toNanos(3000).also {
|
||||
Assert.assertEquals("3000 days", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
|
||||
|
||||
TimeUnit.HOURS.toNanos(3).also {
|
||||
Assert.assertEquals("3 hours", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
TimeUnit.MINUTES.toNanos(3).also {
|
||||
Assert.assertEquals("3 minutes", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
TimeUnit.SECONDS.toNanos(3).also {
|
||||
Assert.assertEquals("3 seconds", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
TimeUnit.MILLISECONDS.toNanos(3).also {
|
||||
Assert.assertEquals("3 milli-seconds", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
TimeUnit.MICROSECONDS.toNanos(3).also {
|
||||
Assert.assertEquals("3 micro-seconds", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
TimeUnit.NANOSECONDS.toNanos(3).also {
|
||||
Assert.assertEquals("3 nano-seconds", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
|
||||
|
||||
TimeUnit.NANOSECONDS.toNanos(1).also {
|
||||
Assert.assertEquals("1 nano-second", Sys.getTimePrettyFull(it))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue