OpenJPH
Open-source implementation of JPEG2000 Part-15
ojph_codestream_wasm.cpp
Go to the documentation of this file.
1//***************************************************************************/
2// This software is released under the 2-Clause BSD license, included
3// below.
4//
5// Copyright (c) 2022, Aous Naman
6// Copyright (c) 2022, Kakadu Software Pty Ltd, Australia
7// Copyright (c) 2022, The University of New South Wales, Australia
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// 1. Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15//
16// 2. Redistributions in binary form must reproduce the above copyright
17// notice, this list of conditions and the following disclaimer in the
18// documentation and/or other materials provided with the distribution.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31//***************************************************************************/
32// This file is part of the OpenJPH software implementation.
33// File: ojph_codestream_wasm.cpp
34// Author: Aous Naman
35// Date: 15 May 2022
36//***************************************************************************/
37
38#include <cstddef>
39#include <wasm_simd128.h>
40
41#include "ojph_defs.h"
42
43namespace ojph {
44 namespace local {
45
47 #define REPEAT(a) a,a,a,a
48
50 void wasm_mem_clear(void* addr, size_t count)
51 {
52 float* p = (float*)addr;
53 v128_t zero = wasm_i32x4_const(REPEAT(0));
54 for (size_t i = 0; i < count; i += 16, p += 4)
55 wasm_v128_store(p, zero);
56 }
57
60 {
61 v128_t x1, x0 = wasm_v128_load(address);
62 x1 = wasm_i32x4_shuffle(x0, x0, 2, 3, 2, 3); // x1 = x0[2,3,2,3]
63 x0 = wasm_v128_or(x0, x1);
64 x1 = wasm_i32x4_shuffle(x0, x0, 1, 1, 1, 1); // x1 = x0[1,1,1,1]
65 x0 = wasm_v128_or(x0, x1);
66 ui32 t = (ui32)wasm_i32x4_extract_lane(x0, 0);
67 return t;
68 }
69
71 void wasm_rev_tx_to_cb(const void *sp, ui32 *dp, ui32 K_max,
72 float delta_inv, ui32 count, ui32* max_val)
73 {
74 ojph_unused(delta_inv);
75
76 // convert to sign and magnitude and keep max_val
77 ui32 shift = 31 - K_max;
78 v128_t m0 = wasm_i32x4_const(REPEAT((int)0x80000000));
79 v128_t zero = wasm_i32x4_const(REPEAT(0));
80 v128_t one = wasm_i32x4_const(REPEAT(1));
81 v128_t tmax = wasm_v128_load(max_val);
82 v128_t *p = (v128_t*)sp;
83 for (ui32 i = 0; i < count; i += 4, p += 1, dp += 4)
84 {
85 v128_t v = wasm_v128_load(p);
86 v128_t sign = wasm_i32x4_lt(v, zero);
87 v128_t val = wasm_v128_xor(v, sign); // negate 1's complement
88 v128_t ones = wasm_v128_and(sign, one);
89 val = wasm_i32x4_add(val, ones); // 2's complement
90 sign = wasm_v128_and(sign, m0);
91 val = wasm_i32x4_shl(val, shift);
92 tmax = wasm_v128_or(tmax, val);
93 val = wasm_v128_or(val, sign);
94 wasm_v128_store(dp, val);
95 }
96 wasm_v128_store(max_val, tmax);
97 }
98
100 void wasm_irv_tx_to_cb(const void *sp, ui32 *dp, ui32 K_max,
101 float delta_inv, ui32 count, ui32* max_val)
102 {
103 ojph_unused(K_max);
104
105 //quantize and convert to sign and magnitude and keep max_val
106
107 v128_t d = wasm_f32x4_splat(delta_inv);
108 v128_t zero = wasm_i32x4_const(REPEAT(0));
109 v128_t one = wasm_i32x4_const(REPEAT(1));
110 v128_t tmax = wasm_v128_load(max_val);
111 float *p = (float*)sp;
112 for (ui32 i = 0; i < count; i += 4, p += 4, dp += 4)
113 {
114 v128_t vf = wasm_v128_load(p);
115 vf = wasm_f32x4_mul(vf, d); // multiply
116 v128_t val = wasm_i32x4_trunc_sat_f32x4(vf); // convert to signed int
117 v128_t sign = wasm_i32x4_lt(val, zero); // get sign
118 val = wasm_v128_xor(val, sign); // negate 1's complement
119 v128_t ones = wasm_v128_and(sign, one);
120 val = wasm_i32x4_add(val, ones); // 2's complement
121 tmax = wasm_v128_or(tmax, val);
122 sign = wasm_i32x4_shl(sign, 31);
123 val = wasm_v128_or(val, sign);
124 wasm_v128_store(dp, val);
125 }
126 wasm_v128_store(max_val, tmax);
127 }
128
130 void wasm_rev_tx_from_cb(const ui32 *sp, void *dp, ui32 K_max,
131 float delta, ui32 count)
132 {
133 ojph_unused(delta);
134 ui32 shift = 31 - K_max;
135 v128_t m1 = wasm_i32x4_const(REPEAT(0x7FFFFFFF));
136 v128_t zero = wasm_i32x4_const(REPEAT(0));
137 v128_t one = wasm_i32x4_const(REPEAT(1));
138 si32 *p = (si32*)dp;
139 for (ui32 i = 0; i < count; i += 4, sp += 4, p += 4)
140 {
141 v128_t v = wasm_v128_load((v128_t*)sp);
142 v128_t val = wasm_v128_and(v, m1);
143 val = wasm_i32x4_shr(val, shift);
144 v128_t sign = wasm_i32x4_lt(v, zero);
145 val = wasm_v128_xor(val, sign); // negate 1's complement
146 v128_t ones = wasm_v128_and(sign, one);
147 val = wasm_i32x4_add(val, ones); // 2's complement
148 wasm_v128_store(p, val);
149 }
150 }
151
153 void wasm_irv_tx_from_cb(const ui32 *sp, void *dp, ui32 K_max,
154 float delta, ui32 count)
155 {
156 ojph_unused(K_max);
157 v128_t m1 = wasm_i32x4_const(REPEAT(0x7FFFFFFF));
158 v128_t d = wasm_f32x4_splat(delta);
159 float *p = (float*)dp;
160 for (ui32 i = 0; i < count; i += 4, sp += 4, p += 4)
161 {
162 v128_t v = wasm_v128_load((v128_t*)sp);
163 v128_t vali = wasm_v128_and(v, m1);
164 v128_t valf = wasm_f32x4_convert_i32x4(vali);
165 valf = wasm_f32x4_mul(valf, d);
166 v128_t sign = wasm_v128_andnot(v, m1);
167 valf = wasm_v128_or(valf, sign);
168 wasm_v128_store(p, valf);
169 }
170 }
171 }
172}
void wasm_irv_tx_from_cb(const ui32 *sp, void *dp, ui32 K_max, float delta, ui32 count)
void wasm_irv_tx_to_cb(const void *sp, ui32 *dp, ui32 K_max, float delta_inv, ui32 count, ui32 *max_val)
void wasm_rev_tx_to_cb(const void *sp, ui32 *dp, ui32 K_max, float delta_inv, ui32 count, ui32 *max_val)
void wasm_mem_clear(void *addr, size_t count)
void wasm_rev_tx_from_cb(const ui32 *sp, void *dp, ui32 K_max, float delta, ui32 count)
ui32 wasm_find_max_val(ui32 *address)
int32_t si32
Definition: ojph_defs.h:55
uint32_t ui32
Definition: ojph_defs.h:54
#define REPEAT(a)
#define ojph_unused(x)
Definition: ojph_defs.h:78