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 
43 namespace 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