Compare commits

..

No commits in common. "193ba0b4a5ceb87c28a4da56c200caa457a044cf" and "44b53e409996e8632947645e5621a04af2fad297" have entirely different histories.

8 changed files with 132 additions and 195 deletions

View File

@ -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.

View File

@ -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
```

View 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.

View File

@ -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

View File

@ -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;

View File

@ -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"

View File

@ -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

View 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)