summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jose Colon Rodriguez2024-02-16 21:46:22 -0400
committerGravatar Jose Colon Rodriguez2024-02-16 21:46:22 -0400
commite523efa9f7da1949134af9679876a2bc6bb141d4 (patch)
tree375984495870bd99913acd5cdc868bec5b42607e /src
parentdisplay_width with table (diff)
downloadzg-e523efa9f7da1949134af9679876a2bc6bb141d4.tar.gz
zg-e523efa9f7da1949134af9679876a2bc6bb141d4.tar.xz
zg-e523efa9f7da1949134af9679876a2bc6bb141d4.zip
SIMD strWidth ASCII optimization
Diffstat (limited to 'src')
-rw-r--r--src/display_width.zig37
-rw-r--r--src/main.zig12
2 files changed, 44 insertions, 5 deletions
diff --git a/src/display_width.zig b/src/display_width.zig
index e06aa8f..b96f872 100644
--- a/src/display_width.zig
+++ b/src/display_width.zig
@@ -1,4 +1,5 @@
1const std = @import("std"); 1const std = @import("std");
2const simd = std.simd;
2const testing = std.testing; 3const testing = std.testing;
3 4
4const CodePointIterator = @import("CodePoint").CodePointIterator; 5const CodePointIterator = @import("CodePoint").CodePointIterator;
@@ -14,8 +15,42 @@ pub fn codePointWidth(cp: u21) i3 {
14 return dwp.stage_2[dwp.stage_1[cp >> 8] + (cp & 0xff)]; 15 return dwp.stage_2[dwp.stage_1[cp >> 8] + (cp & 0xff)];
15} 16}
16 17
17fn strWidth(str: []const u8) usize { 18fn isAsciiOnly(str: []const u8) bool {
19 const vec_len = simd.suggestVectorLength(u8) orelse @panic("No SIMD support.");
20 const Vec = @Vector(vec_len, u8);
21 var i: usize = 0;
22
23 while (i < str.len) : (i += vec_len) {
24 if (str[i..].len < vec_len) return for (str[i..]) |b| {
25 if (b > 127) break false;
26 } else true;
27
28 const v1 = str[i..].ptr[0..vec_len].*;
29 const v2: Vec = @splat(127);
30 if (@reduce(.Or, v1 > v2)) return false;
31 }
32
33 return true;
34}
35
36/// strWidth returns the total display width of `str` as the number of cells
37/// required in a fixed-pitch font (i.e. a terminal screen).
38pub fn strWidth(str: []const u8) usize {
18 var total: isize = 0; 39 var total: isize = 0;
40
41 if (isAsciiOnly(str)) {
42 for (str) |b| {
43 // Backspace and delete
44 if (b == 0x8 or b == 0x7f) {
45 total -= 1;
46 } else if (b >= 0x20) {
47 total += 1;
48 }
49 }
50
51 return if (total > 0) @intCast(total) else 0;
52 }
53
19 var giter = GraphemeIterator.init(str); 54 var giter = GraphemeIterator.init(str);
20 55
21 while (giter.next()) |gc| { 56 while (giter.next()) |gc| {
diff --git a/src/main.zig b/src/main.zig
index 3e65c7b..e7c0828 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -3,7 +3,9 @@ const std = @import("std");
3// const GraphemeIterator = @import("ziglyph").GraphemeIterator; 3// const GraphemeIterator = @import("ziglyph").GraphemeIterator;
4// const GraphemeIterator = @import("Grapheme").GraphemeIterator; 4// const GraphemeIterator = @import("Grapheme").GraphemeIterator;
5// const codePointWidth = @import("ziglyph").display_width.codePointWidth; 5// const codePointWidth = @import("ziglyph").display_width.codePointWidth;
6const codePointWidth = @import("display_width").codePointWidth; 6// const codePointWidth = @import("display_width").codePointWidth;
7// const strWidth = @import("ziglyph").display_width.strWidth;
8const strWidth = @import("display_width").strWidth;
7const CodePointIterator = @import("CodePoint").CodePointIterator; 9const CodePointIterator = @import("CodePoint").CodePointIterator;
8 10
9pub fn main() !void { 11pub fn main() !void {
@@ -14,14 +16,16 @@ pub fn main() !void {
14 const input = try std.fs.cwd().readFileAlloc(allocator, "lang_mix.txt", std.math.maxInt(u32)); 16 const input = try std.fs.cwd().readFileAlloc(allocator, "lang_mix.txt", std.math.maxInt(u32));
15 defer allocator.free(input); 17 defer allocator.free(input);
16 18
17 var result: isize = 0; 19 var result: usize = 0;
18 // var iter = GraphemeIterator.init(input); 20 // var iter = GraphemeIterator.init(input);
19 var iter = CodePointIterator{ .bytes = input }; 21 // var iter = CodePointIterator{ .bytes = input };
22 var iter = std.mem.splitScalar(u8, input, '\n');
20 23
21 var timer = try std.time.Timer.start(); 24 var timer = try std.time.Timer.start();
22 25
23 // for (0..50) |_| { 26 // for (0..50) |_| {
24 while (iter.next()) |cp| result += codePointWidth(@intCast(cp.code)); 27 // while (iter.next()) |cp| result += codePointWidth(@intCast(cp.code));
28 while (iter.next()) |line| result += strWidth(line);
25 // iter.cp_iter.i = 0; 29 // iter.cp_iter.i = 0;
26 // } 30 // }
27 31