Compare commits

...

9 Commits

Author SHA1 Message Date
veclav talica
193ba0b4a5 sorted by date main feed 2024-02-10 20:58:08 +05:00
veclav talica
952a773875 new style, dark style 2024-02-10 20:48:22 +05:00
veclav talica
7807619d58 remove tags from main feed so that it's less crowded 2024-02-10 20:24:09 +05:00
veclav talica
3429e09d15 reworked the footer 2024-02-10 20:20:54 +05:00
veclav talica
ecc283d091 delete the article about introduction of xm player 2024-02-10 20:14:07 +05:00
veclav talica
67ce1832a4 purge xm track player page, it was never good 2024-02-10 20:12:59 +05:00
veclav talica
1098e6551d proper nav 2024-02-10 20:09:30 +05:00
veclav talica
efa3391dbd vector-pi-rotation article 2023-11-09 22:05:37 +05:00
veclav talica
f2020f7463 calling convention notice 2023-11-09 21:59:28 +05:00
8 changed files with 195 additions and 132 deletions

View File

@ -37,7 +37,8 @@ pub fn RectSIMD(comptime T: type) type {
### Assembly ###
This is produced by godbolt, which apparently has AVX512 extensions, so, it's extremely compact.
note: SysV prelude and outro are omitted, with inlining you can expect it looking similarly.
Note: Calling 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:
```asm
@ -148,9 +149,8 @@ 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.
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 ###
- Reordered to use packed vectors without swizzling when possible.
- Eliminated redundant computations.
- Calling convention notice.

View File

@ -0,0 +1,141 @@
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

@ -1,11 +0,0 @@
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,5 +24,3 @@ for d in ./articles/*/; do
done
./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,8 +1,26 @@
@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 {
font-size: 20px;
font-family: "Charter","Georgia",'Times New Roman',serif;
}
body {
background-color: var(--bg-color);
line-height: 1.3;
}
article, .container {
@ -29,7 +47,7 @@ html {
margin: 0.9em 0px 0.9em;
}
pre, code {
background-color: #eeeeff;
background-color: var(--bg-color);
line-height: normal;
overflow: auto;
font-size: 0.8em;
@ -46,7 +64,7 @@ html {
flex-direction: row;
flex-wrap: nowrap;
font-size: 0.8em;
background-color: #f0f0f0;
background-color: var(--bg-color);
border: 1px solid #bbbbdd;
}
nav li:first-child {
@ -66,10 +84,10 @@ html {
background-color: #e0e0e0;
}
nav a:link {
color: #44d;
color: var(--link-color);
}
nav a:visited {
color: #44d;
color: var(--link-color);
}
nav a.here {
background-color: #e0e0e0;

View File

@ -25,18 +25,23 @@ page = f"""Personal blog of one {choice(ADJECTIVES)} Veclav Talica.
"""
# todo: Sort by date first.
artciles = {}
for root, dirs, _ in walk(argv[1]):
for d in dirs:
metadata = parse_metadata(path.abspath(root + '/' + d + "/page.mmd"))
article = urllib.parse.quote(d)
artciles[article] = {
"metadata": metadata
}
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"""
)
if "Tags" in metadata:
page += f""">*{','.join(metadata["Tags"])}*\n---\n"""
break
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"

View File

@ -2,23 +2,21 @@
HEAD_EMBED = """
<div class="container">
<header>
<nav>
<strong>mjestečko</strong> /
<a href="/">main</a> /
<a href="https://git.poto.cafe/veclavtalica/mjestecko">source</a> /
<a href="/tracks.html">tracks</a> /
<a href="/feed.xml">rss</a> /
<a href="/articles/mjestečko.html">about</a>
<nav class="custom-nav">
<ul>
<li><a href="/"><strong>mjestečko</strong></a></li>
<li><a href="https://git.poto.cafe/veclavtalica/mjestecko">source</a></li>
<li><a href="/feed.xml">rss</a></li>
<li><a href="/articles/mjestečko.html">about</a></li>
</ul>
</nav>
</header>
"""
NOTICE = """
---
*Remember, - all you see here is free for use for any purpose benefiting the humanity as a whole.*
<footer>
<a href="#top">Take me home </a>
</footer>
"""
@ -55,5 +53,11 @@ WEEKDAYS = {
6: "Sunday"
}
def mixin_tag(content: str, tag: str) -> str:
return f"""<{tag}>
{content}</{tag}>
"""
def wrap_page(page: str) -> str:
return HEAD_EMBED + page + NOTICE + TAIL_EMBED
return HEAD_EMBED + mixin_tag(page, "main") + NOTICE + TAIL_EMBED

View File

@ -1,92 +0,0 @@
#!/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)