OpenJPH
Open-source implementation of JPEG2000 Part-15
Loading...
Searching...
No Matches
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 <climits>
39#include <cstddef>
40#include <wasm_simd128.h>
41
42#include "ojph_defs.h"
43
44namespace ojph {
45 namespace local {
46
48 void wasm_mem_clear(void* addr, size_t count)
49 {
50 float* p = (float*)addr;
51 v128_t zero = wasm_i32x4_splat(0);
52 for (size_t i = 0; i < count; i += 16, p += 4)
53 wasm_v128_store(p, zero);
54 }
55
58 {
59 v128_t x1, x0 = wasm_v128_load(address);
60 x1 = wasm_i32x4_shuffle(x0, x0, 2, 3, 2, 3); // x1 = x0[2,3,2,3]
61 x0 = wasm_v128_or(x0, x1);
62 x1 = wasm_i32x4_shuffle(x0, x0, 1, 1, 1, 1); // x1 = x0[1,1,1,1]
63 x0 = wasm_v128_or(x0, x1);
64 ui32 t = (ui32)wasm_i32x4_extract_lane(x0, 0);
65 return t;
66 }
67
70 {
71 v128_t x1, x0 = wasm_v128_load(address);
72 x1 = wasm_i64x2_shuffle(x0, x0, 1, 1); // x1 = x0[2,3,2,3]
73 x0 = wasm_v128_or(x0, x1);
74 ui64 t = (ui64)wasm_i64x2_extract_lane(x0, 0);
75 return t;
76 }
77
79 void wasm_rev_tx_to_cb32(const void *sp, ui32 *dp, ui32 K_max,
80 float delta_inv, ui32 count, ui32* max_val)
81 {
82 ojph_unused(delta_inv);
83
84 // convert to sign and magnitude and keep max_val
85 ui32 shift = 31 - K_max;
86 v128_t m0 = wasm_i32x4_splat(INT_MIN);
87 v128_t zero = wasm_i32x4_splat(0);
88 v128_t one = wasm_i32x4_splat(1);
89 v128_t tmax = wasm_v128_load(max_val);
90 si32 *p = (si32*)sp;
91 for (ui32 i = 0; i < count; i += 4, p += 4, dp += 4)
92 {
93 v128_t v = wasm_v128_load(p);
94 v128_t sign = wasm_i32x4_lt(v, zero);
95 v128_t val = wasm_v128_xor(v, sign); // negate 1's complement
96 v128_t ones = wasm_v128_and(sign, one);
97 val = wasm_i32x4_add(val, ones); // 2's complement
98 sign = wasm_v128_and(sign, m0);
99 val = wasm_i32x4_shl(val, shift);
100 tmax = wasm_v128_or(tmax, val);
101 val = wasm_v128_or(val, sign);
102 wasm_v128_store(dp, val);
103 }
104 wasm_v128_store(max_val, tmax);
105 }
106
108 void wasm_irv_tx_to_cb32(const void *sp, ui32 *dp, ui32 K_max,
109 float delta_inv, ui32 count, ui32* max_val)
110 {
111 ojph_unused(K_max);
112
113 //quantize and convert to sign and magnitude and keep max_val
114
115 v128_t d = wasm_f32x4_splat(delta_inv);
116 v128_t zero = wasm_i32x4_splat(0);
117 v128_t one = wasm_i32x4_splat(1);
118 v128_t tmax = wasm_v128_load(max_val);
119 float *p = (float*)sp;
120 for (ui32 i = 0; i < count; i += 4, p += 4, dp += 4)
121 {
122 v128_t vf = wasm_v128_load(p);
123 vf = wasm_f32x4_mul(vf, d); // multiply
124 v128_t val = wasm_i32x4_trunc_sat_f32x4(vf); // convert to signed int
125 v128_t sign = wasm_i32x4_lt(val, zero); // get sign
126 val = wasm_v128_xor(val, sign); // negate 1's complement
127 v128_t ones = wasm_v128_and(sign, one);
128 val = wasm_i32x4_add(val, ones); // 2's complement
129 tmax = wasm_v128_or(tmax, val);
130 sign = wasm_i32x4_shl(sign, 31);
131 val = wasm_v128_or(val, sign);
132 wasm_v128_store(dp, val);
133 }
134 wasm_v128_store(max_val, tmax);
135 }
136
138 void wasm_rev_tx_from_cb32(const ui32 *sp, void *dp, ui32 K_max,
139 float delta, ui32 count)
140 {
141 ojph_unused(delta);
142 ui32 shift = 31 - K_max;
143 v128_t m1 = wasm_i32x4_splat(INT_MAX);
144 v128_t zero = wasm_i32x4_splat(0);
145 v128_t one = wasm_i32x4_splat(1);
146 si32 *p = (si32*)dp;
147 for (ui32 i = 0; i < count; i += 4, sp += 4, p += 4)
148 {
149 v128_t v = wasm_v128_load((v128_t*)sp);
150 v128_t val = wasm_v128_and(v, m1);
151 val = wasm_i32x4_shr(val, shift);
152 v128_t sign = wasm_i32x4_lt(v, zero);
153 val = wasm_v128_xor(val, sign); // negate 1's complement
154 v128_t ones = wasm_v128_and(sign, one);
155 val = wasm_i32x4_add(val, ones); // 2's complement
156 wasm_v128_store(p, val);
157 }
158 }
159
161 void wasm_irv_tx_from_cb32(const ui32 *sp, void *dp, ui32 K_max,
162 float delta, ui32 count)
163 {
164 ojph_unused(K_max);
165 v128_t m1 = wasm_i32x4_splat(INT_MAX);
166 v128_t d = wasm_f32x4_splat(delta);
167 float *p = (float*)dp;
168 for (ui32 i = 0; i < count; i += 4, sp += 4, p += 4)
169 {
170 v128_t v = wasm_v128_load((v128_t*)sp);
171 v128_t vali = wasm_v128_and(v, m1);
172 v128_t valf = wasm_f32x4_convert_i32x4(vali);
173 valf = wasm_f32x4_mul(valf, d);
174 v128_t sign = wasm_v128_andnot(v, m1);
175 valf = wasm_v128_or(valf, sign);
176 wasm_v128_store(p, valf);
177 }
178 }
179
181 void wasm_rev_tx_to_cb64(const void *sp, ui64 *dp, ui32 K_max,
182 float delta_inv, ui32 count, ui64* max_val)
183 {
184 ojph_unused(delta_inv);
185
186 // convert to sign and magnitude and keep max_val
187 ui32 shift = 63 - K_max;
188 v128_t m0 = wasm_i64x2_splat(LLONG_MIN);
189 v128_t zero = wasm_i64x2_splat(0);
190 v128_t one = wasm_i64x2_splat(1);
191 v128_t tmax = wasm_v128_load(max_val);
192 si64 *p = (si64*)sp;
193 for (ui32 i = 0; i < count; i += 2, p += 2, dp += 2)
194 {
195 v128_t v = wasm_v128_load(p);
196 v128_t sign = wasm_i64x2_lt(v, zero);
197 v128_t val = wasm_v128_xor(v, sign); // negate 1's complement
198 v128_t ones = wasm_v128_and(sign, one);
199 val = wasm_i64x2_add(val, ones); // 2's complement
200 sign = wasm_v128_and(sign, m0);
201 val = wasm_i64x2_shl(val, shift);
202 tmax = wasm_v128_or(tmax, val);
203 val = wasm_v128_or(val, sign);
204 wasm_v128_store(dp, val);
205 }
206 wasm_v128_store(max_val, tmax);
207 }
208
210 void wasm_rev_tx_from_cb64(const ui64 *sp, void *dp, ui32 K_max,
211 float delta, ui32 count)
212 {
213 ojph_unused(delta);
214 ui32 shift = 63 - K_max;
215 v128_t m1 = wasm_i64x2_splat(LLONG_MAX);
216 v128_t zero = wasm_i64x2_splat(0);
217 v128_t one = wasm_i64x2_splat(1);
218 si64 *p = (si64*)dp;
219 for (ui32 i = 0; i < count; i += 2, sp += 2, p += 2)
220 {
221 v128_t v = wasm_v128_load((v128_t*)sp);
222 v128_t val = wasm_v128_and(v, m1);
223 val = wasm_i64x2_shr(val, shift);
224 v128_t sign = wasm_i64x2_lt(v, zero);
225 val = wasm_v128_xor(val, sign); // negate 1's complement
226 v128_t ones = wasm_v128_and(sign, one);
227 val = wasm_i64x2_add(val, ones); // 2's complement
228 wasm_v128_store(p, val);
229 }
230 }
231 }
232}
void wasm_rev_tx_to_cb64(const void *sp, ui64 *dp, ui32 K_max, float delta_inv, ui32 count, ui64 *max_val)
ui32 wasm_find_max_val32(ui32 *address)
void wasm_rev_tx_from_cb32(const ui32 *sp, void *dp, ui32 K_max, float delta, ui32 count)
void wasm_rev_tx_from_cb64(const ui64 *sp, void *dp, ui32 K_max, float delta, ui32 count)
void wasm_irv_tx_to_cb32(const void *sp, ui32 *dp, ui32 K_max, float delta_inv, ui32 count, ui32 *max_val)
ui64 wasm_find_max_val64(ui64 *address)
void wasm_mem_clear(void *addr, size_t count)
void wasm_rev_tx_to_cb32(const void *sp, ui32 *dp, ui32 K_max, float delta_inv, ui32 count, ui32 *max_val)
void wasm_irv_tx_from_cb32(const ui32 *sp, void *dp, ui32 K_max, float delta, ui32 count)
int64_t si64
Definition ojph_defs.h:57
uint64_t ui64
Definition ojph_defs.h:56
int32_t si32
Definition ojph_defs.h:55
uint32_t ui32
Definition ojph_defs.h:54
#define ojph_unused(x)
Definition ojph_defs.h:78