Compare commits
No commits in common. "193ba0b4a5ceb87c28a4da56c200caa457a044cf" and "44b53e409996e8632947645e5621a04af2fad297" have entirely different histories.
193ba0b4a5
...
44b53e4099
@ -37,8 +37,7 @@ pub fn RectSIMD(comptime T: type) type {
|
|||||||
### Assembly ###
|
### Assembly ###
|
||||||
This is produced by godbolt, which apparently has AVX512 extensions, so, it's extremely compact.
|
This is produced by godbolt, which apparently has AVX512 extensions, so, it's extremely compact.
|
||||||
|
|
||||||
Note: Calling prelude and outro are omitted, with inlining you can expect it looking similarly.
|
note: SysV prelude and outro are omitted, with inlining you can expect it looking similarly.
|
||||||
Zig calling convention is used, which is roughly equal to C's static marked procedure.
|
|
||||||
|
|
||||||
For 32bit floating point:
|
For 32bit floating point:
|
||||||
```asm
|
```asm
|
||||||
@ -149,8 +148,9 @@ For 32bit signed integers it fares amazing too:
|
|||||||
|
|
||||||
AVX512 makes it so that there's no big penalty for double precision types, which is nice.
|
AVX512 makes it so that there's no big penalty for double precision types, which is nice.
|
||||||
|
|
||||||
|
Note that permutation masks are also supplied along side code which increase binary size.
|
||||||
|
With inlining it could be quite substantial if per object %rip relative addressing is used.
|
||||||
|
|
||||||
### Edits ###
|
### Edits ###
|
||||||
- Reordered to use packed vectors without swizzling when possible.
|
- Reordered to use packed vectors without swizzling when possible.
|
||||||
- Eliminated redundant computations.
|
- Eliminated redundant computations.
|
||||||
- Calling convention notice.
|
|
||||||
|
|
||||||
|
@ -1,141 +0,0 @@
|
|||||||
Title: Optimized Vector Rotation
|
|
||||||
Brief: Specialized rotation methods over Pi and Pi/2 in 2D and 3D.
|
|
||||||
Date: 1699548646
|
|
||||||
Tags: Programming, Zig, Optimization
|
|
||||||
CSS: /style.css
|
|
||||||
|
|
||||||
Came up with some useful optimization for 90 and 180 degree rotations while making a grid walker,
|
|
||||||
below implementations are given, ripped straight from source, lol.
|
|
||||||
|
|
||||||
Compared to generic cos/sin method of rotation it's magnitudes of times less work in many cases, especially if glibc implementation is used.
|
|
||||||
|
|
||||||
Note: Given example assumes coordinate system where Y grows downwards and X to the right.
|
|
||||||
|
|
||||||
## Two dimensions
|
|
||||||
|
|
||||||
```zig
|
|
||||||
pub fn rotateByHalfPiClockwise(self: Self) Self {
|
|
||||||
return .{ .components = .{ -self.y(), self.x() } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rotateByHalfPiCounterClockwise(self: Self) Self {
|
|
||||||
return .{ .components = .{ self.y(), -self.x() } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rotateByPi(self: Self) Self {
|
|
||||||
return .{ .components = .{ -self.x(), -self.y() } };
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Three dimensions
|
|
||||||
|
|
||||||
```zig
|
|
||||||
pub fn rotateByHalfPiClockwiseAroundAxis(self: Self, axis: Axis3) Self {
|
|
||||||
return .{ .components = switch (axis) {
|
|
||||||
.x => .{ self.x(), -self.z(), self.y() },
|
|
||||||
.y => .{ -self.z(), self.y(), self.x() },
|
|
||||||
.z => .{ -self.y(), self.x(), self.z() },
|
|
||||||
} };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rotateByHalfPiCounterClockwiseAroundAxis(self: Self, axis: Axis3) Self {
|
|
||||||
return .{ .components = switch (axis) {
|
|
||||||
.x => .{ self.x(), self.z(), -self.y() },
|
|
||||||
.y => .{ self.z(), self.y(), -self.x() },
|
|
||||||
.z => .{ self.y(), -self.x(), self.z() },
|
|
||||||
} };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rotateByPiAroundAxis(self: Self, axis: Axis3) Self {
|
|
||||||
return .{ .components = switch (axis) {
|
|
||||||
.x => .{ self.x(), -self.x(), -self.y() },
|
|
||||||
.y => .{ -self.x(), self.y(), -self.z() },
|
|
||||||
.z => .{ -self.x(), -self.y(), self.z() },
|
|
||||||
} };
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Generated amd64 assembly
|
|
||||||
Note: Procedure prelude/epilogue is omitted. Zig's calling convention is used, which is roughly equivalent to C's static marked function in effect.
|
|
||||||
|
|
||||||
Note: It's for vectors stored packed for use in SSE, array/separate scalar passing produces worse result, at least when not inlined.
|
|
||||||
|
|
||||||
### rotateByHalfPiClockwise
|
|
||||||
Notice how it's one instruction longer than coutner-clockwise case,
|
|
||||||
so, choice of coordinate system effects costs of particular direction to rotate around.
|
|
||||||
|
|
||||||
```asm
|
|
||||||
vmovlpd qword ptr [rsp], xmm0
|
|
||||||
vmovshdup xmm1, xmm0
|
|
||||||
vpbroadcastd xmm2, dword ptr [rip + .LCPI2_0]
|
|
||||||
vpxor xmm1, xmm1, xmm2
|
|
||||||
vbroadcastss xmm0, xmm0
|
|
||||||
vblendps xmm0, xmm0, xmm1, 1
|
|
||||||
```
|
|
||||||
### rotateByHalfPiCounterClockwise
|
|
||||||
|
|
||||||
```asm
|
|
||||||
vmovlpd qword ptr [rsp], xmm0
|
|
||||||
vpbroadcastd xmm1, dword ptr [rip + .LCPI1_0]
|
|
||||||
vpxor xmm1, xmm0, xmm1
|
|
||||||
vmovshdup xmm0, xmm0
|
|
||||||
vinsertps xmm0, xmm0, xmm1, 16
|
|
||||||
```
|
|
||||||
|
|
||||||
### rotateByPi
|
|
||||||
```asm
|
|
||||||
vmovlpd qword ptr [rsp], xmm0
|
|
||||||
vpermilps xmm0, xmm0, 212
|
|
||||||
vpbroadcastd xmm1, dword ptr [rip + .LCPI3_0]
|
|
||||||
vpxor xmm0, xmm0, xmm1
|
|
||||||
```
|
|
||||||
|
|
||||||
### rotateByHalfPiClockwiseAroundAxis (X)
|
|
||||||
```asm
|
|
||||||
sub rsp, 24
|
|
||||||
vmovq qword ptr [rsp], xmm0
|
|
||||||
vpermilpd xmm1, xmm0, 1
|
|
||||||
vmovaps xmm2, xmm1
|
|
||||||
vmovss dword ptr [rsp + 8], xmm2
|
|
||||||
vpbroadcastd xmm2, dword ptr [rip + .LCPI4_0]
|
|
||||||
vpxor xmm1, xmm1, xmm2
|
|
||||||
vpermilps xmm0, xmm0, 212
|
|
||||||
vinsertps xmm0, xmm0, xmm1, 16
|
|
||||||
add rsp, 24
|
|
||||||
```
|
|
||||||
|
|
||||||
### rotateByHalfPiCounterClockwiseAroundAxis (X)
|
|
||||||
Again, one instruction shorter.
|
|
||||||
|
|
||||||
```asm
|
|
||||||
sub rsp, 24
|
|
||||||
vextractps dword ptr [rsp + 8], xmm0, 2
|
|
||||||
vmovq qword ptr [rsp], xmm0
|
|
||||||
vmovshdup xmm1, xmm0
|
|
||||||
vpbroadcastd xmm2, dword ptr [rip + .LCPI5_0]
|
|
||||||
vpxor xmm1, xmm1, xmm2
|
|
||||||
vpermilps xmm0, xmm0, 232
|
|
||||||
vinsertps xmm0, xmm0, xmm1, 32
|
|
||||||
add rsp, 24
|
|
||||||
```
|
|
||||||
|
|
||||||
### rotateByPiAroundAxis (X)
|
|
||||||
Now it's more work.
|
|
||||||
|
|
||||||
```asm
|
|
||||||
sub rsp, 24
|
|
||||||
vmovq qword ptr [rsp], xmm0
|
|
||||||
vpermilpd xmm1, xmm0, 1
|
|
||||||
vmovaps xmm2, xmm1
|
|
||||||
vmovss dword ptr [rsp + 8], xmm2
|
|
||||||
vmovshdup xmm2, xmm0
|
|
||||||
vbroadcastss xmm3, dword ptr [rip + .LCPI6_0]
|
|
||||||
vpxor xmm2, xmm2, xmm3
|
|
||||||
vpxor xmm1, xmm1, xmm3
|
|
||||||
vinsertps xmm0, xmm0, xmm2, 16
|
|
||||||
vinsertps xmm0, xmm0, xmm1, 32
|
|
||||||
add rsp, 24
|
|
||||||
```
|
|
||||||
|
|
11
articles/xm-tracks/page.mmd
Normal file
11
articles/xm-tracks/page.mmd
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Title: .xm Tracks
|
||||||
|
Brief: .xm track listing with playback.
|
||||||
|
Date: 1684868476
|
||||||
|
Tags: Meta, Music, Js
|
||||||
|
CSS: /style.css
|
||||||
|
|
||||||
|
Today is the day of .xm archival and in-browser playback addition.
|
||||||
|
It's achieved with help of [jsxm](https://github.com/a1k0n/jsxm).
|
||||||
|
It lacks support for some things though, might need to contribute to it.
|
||||||
|
|
||||||
|
Could be neat to make some small program that would generate waveforms pngs next.
|
@ -24,3 +24,5 @@ for d in ./articles/*/; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
./tools/feed_generator.py ./articles/ https://mjestecko.neocities.org/ > ./html/feed.xml
|
./tools/feed_generator.py ./articles/ https://mjestecko.neocities.org/ > ./html/feed.xml
|
||||||
|
|
||||||
|
./tools/track_listing_generator.py html/tracks > html/tracks.html
|
||||||
|
@ -1,26 +1,8 @@
|
|||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--bg-color: #111;
|
|
||||||
--fg-color: #fff;
|
|
||||||
--link-color: dodgerblue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
color: var(--fg-color);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--link-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-family: "Charter","Georgia",'Times New Roman',serif;
|
font-family: "Charter","Georgia",'Times New Roman',serif;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
background-color: var(--bg-color);
|
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
article, .container {
|
article, .container {
|
||||||
@ -47,7 +29,7 @@ html {
|
|||||||
margin: 0.9em 0px 0.9em;
|
margin: 0.9em 0px 0.9em;
|
||||||
}
|
}
|
||||||
pre, code {
|
pre, code {
|
||||||
background-color: var(--bg-color);
|
background-color: #eeeeff;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
@ -64,7 +46,7 @@ html {
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
background-color: var(--bg-color);
|
background-color: #f0f0f0;
|
||||||
border: 1px solid #bbbbdd;
|
border: 1px solid #bbbbdd;
|
||||||
}
|
}
|
||||||
nav li:first-child {
|
nav li:first-child {
|
||||||
@ -84,10 +66,10 @@ html {
|
|||||||
background-color: #e0e0e0;
|
background-color: #e0e0e0;
|
||||||
}
|
}
|
||||||
nav a:link {
|
nav a:link {
|
||||||
color: var(--link-color);
|
color: #44d;
|
||||||
}
|
}
|
||||||
nav a:visited {
|
nav a:visited {
|
||||||
color: var(--link-color);
|
color: #44d;
|
||||||
}
|
}
|
||||||
nav a.here {
|
nav a.here {
|
||||||
background-color: #e0e0e0;
|
background-color: #e0e0e0;
|
||||||
|
@ -25,24 +25,19 @@ page = f"""Personal blog of one {choice(ADJECTIVES)} Veclav Talica.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
artciles = {}
|
# todo: Sort by date first.
|
||||||
for root, dirs, _ in walk(argv[1]):
|
for root, dirs, _ in walk(argv[1]):
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
metadata = parse_metadata(path.abspath(root + '/' + d + "/page.mmd"))
|
metadata = parse_metadata(path.abspath(root + '/' + d + "/page.mmd"))
|
||||||
article = urllib.parse.quote(d)
|
article = urllib.parse.quote(d)
|
||||||
artciles[article] = {
|
page += (
|
||||||
"metadata": metadata
|
f"""[{metadata.get("Title", "No title given! What a clusterfuck!")}](/articles/{article}.html)\n\n"""
|
||||||
}
|
f""">{metadata.get("Brief", "")}\n\n"""
|
||||||
|
)
|
||||||
|
if "Tags" in metadata:
|
||||||
|
page += f""">*{','.join(metadata["Tags"])}*\n---\n"""
|
||||||
break
|
break
|
||||||
|
|
||||||
for title in sorted(artciles.keys(), key=lambda a: artciles[a]["metadata"].get("Date", time.gmtime(0)), reverse=True):
|
|
||||||
article = artciles[title]
|
|
||||||
metadata = article["metadata"]
|
|
||||||
page += (
|
|
||||||
f"""[{metadata.get("Title", "No title given! What a clusterfuck!")}](/articles/{article}.html)\n\n"""
|
|
||||||
f""">{metadata.get("Brief", "")}\n\n"""
|
|
||||||
)
|
|
||||||
|
|
||||||
curtime = time.gmtime(int(time.time()))
|
curtime = time.gmtime(int(time.time()))
|
||||||
page += f"Last compiled: *{MONTHS[curtime.tm_mon]} {curtime.tm_mday}, {curtime.tm_year} {curtime.tm_hour}:{curtime.tm_min:02d} UTC*\n\n"
|
page += f"Last compiled: *{MONTHS[curtime.tm_mon]} {curtime.tm_mday}, {curtime.tm_year} {curtime.tm_hour}:{curtime.tm_min:02d} UTC*\n\n"
|
||||||
|
|
||||||
|
@ -2,21 +2,23 @@
|
|||||||
HEAD_EMBED = """
|
HEAD_EMBED = """
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<nav class="custom-nav">
|
<header>
|
||||||
<ul>
|
<nav>
|
||||||
<li><a href="/"><strong>mjestečko</strong></a></li>
|
<strong>mjestečko</strong> /
|
||||||
<li><a href="https://git.poto.cafe/veclavtalica/mjestecko">source</a></li>
|
<a href="/">main</a> /
|
||||||
<li><a href="/feed.xml">rss</a></li>
|
<a href="https://git.poto.cafe/veclavtalica/mjestecko">source</a> /
|
||||||
<li><a href="/articles/mjestečko.html">about</a></li>
|
<a href="/tracks.html">tracks</a> /
|
||||||
|
<a href="/feed.xml">rss</a> /
|
||||||
|
<a href="/articles/mjestečko.html">about</a>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
NOTICE = """
|
NOTICE = """
|
||||||
<footer>
|
---
|
||||||
<a href="#top">Take me home ↑</a>
|
*Remember, - all you see here is free for use for any purpose benefiting the humanity as a whole.*
|
||||||
</footer>
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -53,11 +55,5 @@ WEEKDAYS = {
|
|||||||
6: "Sunday"
|
6: "Sunday"
|
||||||
}
|
}
|
||||||
|
|
||||||
def mixin_tag(content: str, tag: str) -> str:
|
|
||||||
return f"""<{tag}>
|
|
||||||
{content}</{tag}>
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def wrap_page(page: str) -> str:
|
def wrap_page(page: str) -> str:
|
||||||
return HEAD_EMBED + mixin_tag(page, "main") + NOTICE + TAIL_EMBED
|
return HEAD_EMBED + page + NOTICE + TAIL_EMBED
|
||||||
|
92
tools/track_listing_generator.py
Executable file
92
tools/track_listing_generator.py
Executable file
@ -0,0 +1,92 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
from sys import argv, exit
|
||||||
|
from os import walk, path
|
||||||
|
|
||||||
|
from page_shares import HEAD_EMBED, TAIL_EMBED
|
||||||
|
|
||||||
|
if len(argv) <= 1:
|
||||||
|
print("No directory was supplied")
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
page = """<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>Tracks</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/style.css"/>
|
||||||
|
<script type="text/javascript" src="/xm.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function (window, document) {
|
||||||
|
if (!window.XMPlayer)
|
||||||
|
window.XMPlayer = {};
|
||||||
|
|
||||||
|
var XMPlayer = window.XMPlayer;
|
||||||
|
var was_init = false
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
|
||||||
|
function b64toBlob(base64) {
|
||||||
|
const decoded = atob(base64);
|
||||||
|
const uInt8Array = new Uint8Array(decoded.length);
|
||||||
|
for (let i = 0; i < decoded.length; ++i)
|
||||||
|
uInt8Array[i] = decoded.charCodeAt(i);
|
||||||
|
return new Blob([uInt8Array]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function decompressGzippedBase64(str) {
|
||||||
|
const ds = new DecompressionStream(`gzip`);
|
||||||
|
const decompressedStream = b64toBlob(str).stream().pipeThrough(ds);
|
||||||
|
return new Response(decompressedStream).blob();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.loadAndPlayTrack = function(url) {
|
||||||
|
if (!was_init) {
|
||||||
|
XMPlayer.init();
|
||||||
|
was_init = true;
|
||||||
|
}
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.responseType = `text`;
|
||||||
|
request.open('GET', url);
|
||||||
|
request.send();
|
||||||
|
request.onload = async(_) => {
|
||||||
|
if (request.readyState === 4 && request.status === 200) {
|
||||||
|
XMPlayer.stop();
|
||||||
|
XMPlayer.load(await (await decompressGzippedBase64(request.response)).arrayBuffer());
|
||||||
|
XMPlayer.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(window, document)
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
"""
|
||||||
|
page += HEAD_EMBED
|
||||||
|
|
||||||
|
page += """
|
||||||
|
<h3 id="articles">Tracks</h3>
|
||||||
|
<p>.xm module tracks of my own. Btw, they're playable in browser :3</p>
|
||||||
|
<p>Note that some files are rendered incorrectly.</p>
|
||||||
|
<hr/>
|
||||||
|
"""
|
||||||
|
|
||||||
|
for _, _, files in walk(argv[1]):
|
||||||
|
files.sort()
|
||||||
|
for f in files:
|
||||||
|
# note: Base64 gzip encoded data is expected.
|
||||||
|
if not f.endswith('.xm.txt'):
|
||||||
|
continue
|
||||||
|
page += (
|
||||||
|
f""" <div><p style="display: inline;">{f[:-4]}</p><button style="float: right;" onclick="window.loadAndPlayTrack('/tracks/{f}')">play</button></div>\n"""
|
||||||
|
" <hr/>\n"
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
|
page += TAIL_EMBED
|
||||||
|
|
||||||
|
page += """</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
print(page)
|
Loading…
Reference in New Issue
Block a user