spinn_common 7.2.2
Support code for SpiNNaker applications.
Loading...
Searching...
No Matches
round.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 The University of Manchester
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
31#ifndef __ROUND_H__
32#define __ROUND_H__
33
34#include <stdfix-full-iso.h>
35#include <random.h>
36#include <sark.h>
37#include "utils.h"
38
39#include <stdfix.h>
40
43#if 0
44#define RANDOM() mars_kiss64_simp()
45#elif 0
46#define RANDOM() mars_kiss32()
47#elif 1
48#define RANDOM() sark_rand()
49#else
50#define RANDOM() cheap_generator()
51#endif
52
54#ifdef FLOATING_POINT
55#define ROUNDING_NONE_GCC
56#else
57//#define ROUNDING_NONE_GCC
58//#define ROUNDING_NONE_CUSTOM
59//#define ROUNDING_NEAREST
60#define ROUNDING_STOCHASTIC
61#endif
62
71#ifdef ROUNDING_NONE_GCC
72 #define FX_MUL(x, y) MULT_NO_ROUND_GCC(x, y)
73 #define FX_MUL_SHORT_ACCUM(x, y) MULT_NO_ROUND_GCC(x, y)
74 #define FX_MUL_FRACT32(x, y) MULT_NO_ROUND_GCC(x, y)
75 #define FX_MUL_FRACT16(x, y) MULT_NO_ROUND_GCC(x, y)
76#elif defined ROUNDING_NONE_CUSTOM
77 #define FX_MUL(x, y) MULT_NO_ROUND_CUSTOM_ACCUM(x, y)
78 #define FX_MUL_SHORT_ACCUM(x, y) MULT_NO_ROUND_CUSTOM_SHORT_ACCUM(x, y)
79 #define FX_MUL_FRACT32(x, y) MULT_NO_ROUND_CUSTOM_FRACT32(x, y)
80 #define FX_MUL_FRACT16(x, y) MULT_NO_ROUND_CUSTOM_FRACT16(x, y)
81#elif defined ROUNDING_NEAREST
82 #define FX_MUL(x, y) MULT_ROUND_NEAREST_ACCUM(x, y)
83 #define FX_MUL_SHORT_ACCUM(x, y) MULT_ROUND_NEAREST_SHORT_ACCUM(x, y)
84 #define FX_MUL_FRACT32(x, y) MULT_ROUND_NEAREST_FRACT32(x, y)
85 #define FX_MUL_FRACT16(x, y) MULT_ROUND_NEAREST_FRACT16(x, y)
86#elif defined ROUNDING_STOCHASTIC
88 #define FX_MUL(x, y) MULT_ROUND_STOCHASTIC_ACCUM(x, y)
90 #define FX_MUL_SHORT_ACCUM(x, y) MULT_ROUND_STOCHASTIC_SHORT_ACCUM(x, y)
92 #define FX_MUL_FRACT32(x, y) MULT_ROUND_STOCHASTIC_FRACT32(x, y)
94 #define FX_MUL_FRACT16(x, y) MULT_ROUND_STOCHASTIC_FRACT16(x, y)
95#endif
97
103
109#define MULT_NO_ROUND_GCC(x, y) ((x) * (y))
110
116#define MULT_NO_ROUND_CUSTOM_ACCUM(x, y) \
117 ({ \
118 __typeof__(x) temp0 = (x); \
119 __typeof__(y) temp1 = (y); \
120 s1615 result; \
121 if (__builtin_types_compatible_p(__typeof__(x), s1615) && \
122 __builtin_types_compatible_p(__typeof__(y), s1615)) { \
123 result = kbits(__stdfix_smul_k(bitsk(temp0), bitsk(temp1))); \
124 } else if ((__builtin_types_compatible_p(__typeof__(x), s1615) && \
125 __builtin_types_compatible_p(__typeof__(y), s031))) { \
126 result = accum_times_long_fract(temp0, temp1); \
127 } else if (__builtin_types_compatible_p(__typeof__(x), s031) && \
128 __builtin_types_compatible_p(__typeof__(y), s1615)) { \
129 result = accum_times_long_fract(temp1, temp0); \
130 } else if ((__builtin_types_compatible_p(__typeof__(x), s1615) && \
131 __builtin_types_compatible_p(__typeof__(y), u032))) { \
132 result = accum_times_u_long_fract(temp0, temp1); \
133 } else if (__builtin_types_compatible_p(__typeof__(x), u032) && \
134 __builtin_types_compatible_p(__typeof__(y), s1615)) { \
135 result = accum_times_u_long_fract(temp1, temp0); \
136 } else { \
137 __builtin_trap(); \
138 } \
139 result; \
140 })
141
147#define MULT_NO_ROUND_CUSTOM_SHORT_ACCUM(x, y) \
148 ({ \
149 __typeof__(x) temp0 = (x); \
150 __typeof__(y) temp1 = (y); \
151 s87 result; \
152 if (__builtin_types_compatible_p(__typeof__(x), s87) && \
153 __builtin_types_compatible_p(__typeof__(y), s87)) { \
154 result = hkbits(__stdfix_smul_hk(bitshk(temp0), bitshk(temp1))); \
155 } else if ((__builtin_types_compatible_p(__typeof__(x), s87) && \
156 __builtin_types_compatible_p(__typeof__(y), s015))) { \
157 result = short_accum_times_fract(temp0, temp1); \
158 } else if (__builtin_types_compatible_p(__typeof__(x), s015) && \
159 __builtin_types_compatible_p(__typeof__(y), s87)) { \
160 result = short_accum_times_fract(temp1, temp0); \
161 } else if ((__builtin_types_compatible_p(__typeof__(x), s87) && \
162 __builtin_types_compatible_p(__typeof__(y), u016))) { \
163 result = short_accum_times_u_fract(temp0, temp1); \
164 } else if (__builtin_types_compatible_p(__typeof__(x), u016) && \
165 __builtin_types_compatible_p(__typeof__(y), s87)) { \
166 result = short_accum_times_u_fract(temp1, temp0); \
167 } else { \
168 __builtin_trap(); \
169 } \
170 result; \
171 })
172
178#define MULT_NO_ROUND_CUSTOM_FRACT32(x, y) \
179 ({ \
180 __typeof__(x) temp0 = (x); \
181 __typeof__(y) temp1 = (y); \
182 s031 result; \
183 if (__builtin_types_compatible_p(__typeof__(x), u032) && \
184 __builtin_types_compatible_p(__typeof__(y), u032)) { \
185 result = ulrbits(__stdfix_smul_ulr(bitsulr(temp0), bitsulr(temp1))); \
186 } else if (__builtin_types_compatible_p(__typeof__(x), s031) && \
187 __builtin_types_compatible_p(__typeof__(y), u032)) { \
188 result = long_fract_times_u_long_fract(temp0, temp1); \
189 } else if (__builtin_types_compatible_p(__typeof__(x), u032) && \
190 __builtin_types_compatible_p(__typeof__(y), s031)) { \
191 result = long_fract_times_u_long_fract(temp1, temp0); \
192 } else { \
193 __builtin_trap(); \
194 } \
195 result; \
196 })
197
203#define MULT_NO_ROUND_CUSTOM_FRACT16(x, y) \
204 ({ \
205 __typeof__(x) temp0 = (x); \
206 __typeof__(y) temp1 = (y); \
207 s015 result; \
208 if (__builtin_types_compatible_p(__typeof__(x), u016) && \
209 __builtin_types_compatible_p(__typeof__(y), u016)) { \
210 result = urbits(__stdfix_smul_ur(bitsur(temp0), bitsur(temp1))); \
211 } else if (__builtin_types_compatible_p(__typeof__(x), s015) && \
212 __builtin_types_compatible_p(__typeof__(y), u016)) { \
213 result = fract_times_u_fract(temp0, temp1); \
214 } else if (__builtin_types_compatible_p(__typeof__(x), u016) && \
215 __builtin_types_compatible_p(__typeof__(y), s015)) { \
216 result = fract_times_u_fract(temp1, temp0); \
217 } else { \
218 __builtin_trap(); \
219 } \
220 result; \
221 })
222
228#define MULT_ROUND_NEAREST_ACCUM(x, y) \
229 ({ \
230 __typeof__(x) temp0 = (x); \
231 __typeof__(y) temp1 = (y); \
232 s1615 result; \
233 if (__builtin_types_compatible_p(__typeof__(x), s1615) && \
234 __builtin_types_compatible_p(__typeof__(y), s1615)) { \
235 result = kbits(__stdfix_smul_k_round_nearest(bitsk(temp0), \
236 bitsk(temp1))); \
237 } else if ((__builtin_types_compatible_p(__typeof__(x), s1615) && \
238 __builtin_types_compatible_p(__typeof__(y), s031))) { \
239 result = accum_times_long_fract_nearest(temp0, temp1); \
240 } else if (__builtin_types_compatible_p(__typeof__(x), s031) && \
241 __builtin_types_compatible_p(__typeof__(y), s1615)) { \
242 result = accum_times_long_fract_nearest(temp1, temp0); \
243 } else if ((__builtin_types_compatible_p(__typeof__(x), s1615) && \
244 __builtin_types_compatible_p(__typeof__(y), u032))) { \
245 result = accum_times_u_long_fract_nearest(temp0, temp1); \
246 } else if (__builtin_types_compatible_p(__typeof__(x), u032) && \
247 __builtin_types_compatible_p(__typeof__(y), s1615)) { \
248 result = accum_times_u_long_fract_nearest(temp1, temp0); \
249 } else { \
250 __builtin_trap(); \
251 } \
252 result; \
253 })
254
260#define MULT_ROUND_NEAREST_SHORT_ACCUM(x, y) \
261 ({ \
262 __typeof__(x) temp0 = (x); \
263 __typeof__(y) temp1 = (y); \
264 s87 result; \
265 if (__builtin_types_compatible_p(__typeof__(x), s87) && \
266 __builtin_types_compatible_p(__typeof__(y), s87)) { \
267 result = hkbits(__stdfix_smul_hk_round_nearest(bitshk(temp0), \
268 bitshk(temp1))); \
269 } else if ((__builtin_types_compatible_p(__typeof__(x), s87) && \
270 __builtin_types_compatible_p(__typeof__(y), s015))) { \
271 result = short_accum_times_fract_nearest(temp0, temp1); \
272 } else if (__builtin_types_compatible_p(__typeof__(x), s015) && \
273 __builtin_types_compatible_p(__typeof__(y), s87)) { \
274 result = short_accum_times_fract_nearest(temp1, temp0); \
275 } else if ((__builtin_types_compatible_p(__typeof__(x), s87) && \
276 __builtin_types_compatible_p(__typeof__(y), u016))) { \
277 result = short_accum_times_u_fract_nearest(temp0, temp1); \
278 } else if (__builtin_types_compatible_p(__typeof__(x), u016) && \
279 __builtin_types_compatible_p(__typeof__(y), s87)) { \
280 result = short_accum_times_u_fract_nearest(temp1, temp0); \
281 } else { \
282 __builtin_trap(); \
283 } \
284 result; \
285 })
286
292#define MULT_ROUND_NEAREST_FRACT32(x, y) \
293 ({ \
294 __typeof__(x) temp0 = (x); \
295 __typeof__(y) temp1 = (y); \
296 s031 result; \
297 if (__builtin_types_compatible_p(__typeof__(x), u032) && \
298 __builtin_types_compatible_p(__typeof__(y), u032)) { \
299 result = lrbits(__stdfix_smul_ulr_round_nearest(bitsulr(temp0), \
300 bitsulr(temp1))); \
301 } else if (__builtin_types_compatible_p(__typeof__(x), s031) && \
302 __builtin_types_compatible_p(__typeof__(y), u032)) { \
303 result = long_fract_times_u_long_fract_nearest(temp0, temp1); \
304 } else if (__builtin_types_compatible_p(__typeof__(x), u032) && \
305 __builtin_types_compatible_p(__typeof__(y), s031)) { \
306 result = long_fract_times_u_long_fract_nearest(temp1, temp0); \
307 } else { \
308 __builtin_trap(); \
309 } \
310 result; \
311 })
312
318#define MULT_ROUND_NEAREST_FRACT16(x, y) \
319 ({ \
320 __typeof__(x) temp0 = (x); \
321 __typeof__(y) temp1 = (y); \
322 s015 result; \
323 if (__builtin_types_compatible_p(__typeof__(x), u016) && \
324 __builtin_types_compatible_p(__typeof__(y), u016)) { \
325 result = rbits(__stdfix_smul_ur_round_nearest(bitsur(temp0), \
326 bitsur(temp1))); \
327 } else if (__builtin_types_compatible_p(__typeof__(x), s015) && \
328 __builtin_types_compatible_p(__typeof__(y), u016)) { \
329 result = fract_times_u_fract_nearest(temp0, temp1); \
330 } else if (__builtin_types_compatible_p(__typeof__(x), u016) && \
331 __builtin_types_compatible_p(__typeof__(y), s015)) { \
332 result = fract_times_u_fract_nearest(temp1, temp0); \
333 } else { \
334 __builtin_trap(); \
335 } \
336 result; \
337 })
338
344#define MULT_ROUND_STOCHASTIC_ACCUM(x, y) \
345 ({ \
346 __typeof__(x) temp0 = (x); \
347 __typeof__(y) temp1 = (y); \
348 s1615 result; \
349 if (__builtin_types_compatible_p(__typeof__(x), s1615) && \
350 __builtin_types_compatible_p(__typeof__(y), s1615)) { \
351 result = kbits(__stdfix_smul_k_round_stochastic(bitsk(temp0), \
352 bitsk(temp1))); \
353 } else if ((__builtin_types_compatible_p(__typeof__(x), s1615) && \
354 __builtin_types_compatible_p(__typeof__(y), s031))) { \
355 result = accum_times_long_fract_stochastic(temp0, temp1); \
356 } else if (__builtin_types_compatible_p(__typeof__(x), s031) && \
357 __builtin_types_compatible_p(__typeof__(y), s1615)) { \
358 result = accum_times_long_fract_stochastic(temp1, temp0); \
359 } else if ((__builtin_types_compatible_p(__typeof__(x), s1615) && \
360 __builtin_types_compatible_p(__typeof__(y), u032))) { \
361 result = accum_times_u_long_fract_stochastic(temp0, temp1); \
362 } else if (__builtin_types_compatible_p(__typeof__(x), u032) && \
363 __builtin_types_compatible_p(__typeof__(y), s1615)) { \
364 result = accum_times_u_long_fract_stochastic(temp1, temp0); \
365 } else { \
366 __builtin_trap(); \
367 } \
368 result; \
369 })
370
376#define MULT_ROUND_STOCHASTIC_SHORT_ACCUM(x, y) \
377 ({ \
378 __typeof__(x) temp0 = (x); \
379 __typeof__(y) temp1 = (y); \
380 s87 result; \
381 if (__builtin_types_compatible_p(__typeof__(x), s87) && \
382 __builtin_types_compatible_p(__typeof__(y), s87)) { \
383 result = hkbits(__stdfix_smul_hk_round_stochastic(bitshk(temp0), \
384 bitshk(temp1))); \
385 } else if ((__builtin_types_compatible_p(__typeof__(x), s87) && \
386 __builtin_types_compatible_p(__typeof__(y), s015))) { \
387 result = short_accum_times_fract_stochastic(temp0, temp1); \
388 } else if (__builtin_types_compatible_p(__typeof__(x), s015) && \
389 __builtin_types_compatible_p(__typeof__(y), s87)) { \
390 result = short_accum_times_fract_stochastic(temp1, temp0); \
391 } else if ((__builtin_types_compatible_p(__typeof__(x), s87) && \
392 __builtin_types_compatible_p(__typeof__(y), u016))) { \
393 result = short_accum_times_u_fract_stochastic(temp0, temp1); \
394 } else if (__builtin_types_compatible_p(__typeof__(x), u016) && \
395 __builtin_types_compatible_p(__typeof__(y), s87)) { \
396 result = short_accum_times_u_fract_stochastic(temp1, temp0); \
397 } else { \
398 __builtin_trap(); \
399 } \
400 result; \
401 })
402
408#define MULT_ROUND_STOCHASTIC_FRACT32(x, y) \
409 ({ \
410 __typeof__(x) temp0 = (x); \
411 __typeof__(y) temp1 = (y); \
412 s031 result; \
413 if (__builtin_types_compatible_p(__typeof__(x), u032) && \
414 __builtin_types_compatible_p(__typeof__(y), u032)) { \
415 result = lrbits(__stdfix_smul_ulr_round_stochastic(bitsulr(temp0), \
416 bitsulr(temp1))); \
417 } else if (__builtin_types_compatible_p(__typeof__(x), s031) && \
418 __builtin_types_compatible_p(__typeof__(y), u032)) { \
419 result = long_fract_times_u_long_fract_stochastic(temp0, temp1); \
420 } else if (__builtin_types_compatible_p(__typeof__(x), u032) && \
421 __builtin_types_compatible_p(__typeof__(y), s031)) { \
422 result = long_fract_times_u_long_fract_stochastic(temp1, temp0); \
423 } else { \
424 __builtin_trap(); \
425 } \
426 result; \
427 })
428
434#define MULT_ROUND_STOCHASTIC_FRACT16(x, y) \
435 ({ \
436 __typeof__(x) temp0 = (x); \
437 __typeof__(y) temp1 = (y); \
438 s015 result; \
439 if (__builtin_types_compatible_p(__typeof__(x), u016) && \
440 __builtin_types_compatible_p(__typeof__(y), u016)) { \
441 result = rbits(__stdfix_smul_ur_round_stochastic(bitsur(temp0), \
442 bitsur(temp1))); \
443 } else if (__builtin_types_compatible_p(__typeof__(x), s015) && \
444 __builtin_types_compatible_p(__typeof__(y), u016)) { \
445 result = fract_times_u_fract_stochastic(temp0, temp1); \
446 } else if (__builtin_types_compatible_p(__typeof__(x), u016) && \
447 __builtin_types_compatible_p(__typeof__(y), s015)) { \
448 result = fract_times_u_fract_stochastic(temp1, temp0); \
449 } else { \
450 __builtin_trap(); \
451 } \
452 result; \
453 })
455
458
466#define STOCHASTIC_ROUND_S64(x, n) \
467 __stdfix_sat_k(__stdfix_stochastic_round_s64_alternative(x, n) >> n)
468
476#define STOCHASTIC_ROUND_U64(x, n) \
477 __stdfix_sat_uk(__stdfix_stochastic_round_u64(x, n) >> n)
478
486#define NEAREST_ROUND_S64(x, n) \
487 __stdfix_sat_k(__stdfix_round_s64(x, n) >> n)
488
496#define NEAREST_ROUND_U64(x, n) \
497 __stdfix_sat_k(__stdfix_round_u64(x, n) >> n)
498
506#define ROUND_DOWN_S64(x, n) \
507 __stdfix_sat_k(x >> n)
509
513static inline uint32_t cheap_generator(void) {
514 static unsigned long idum;
515 idum = 1664525L * idum + 1013904223L;
516
517 return idum;
518}
519
533static int64_t __stdfix_stochastic_round_s64(int64_t x, int n)
534{
535 register int64_t r;
536 register uint64_t p, dropped_bits;
537
538 r = x >> n;
539 p = RANDOM() >> (32 - n);
540 dropped_bits = x & (((uint64_t) 0x1 << n) - 1);
541
542 if (p < dropped_bits) {
543 return (r + 0x1) << n;
544 } else {
545 return r << n;
546 }
547}
548
554static int64_t __stdfix_stochastic_round_s64_alternative(int64_t x, int n)
555{
556 register int64_t r;
557 register uint64_t p;
558
559 p = RANDOM() & (((uint64_t) 0x1 << n) - 1);
560 r = x + p;
561 return r;
562}
563
569static inline int32_t __stdfix_stochastic_round_s32(int32_t x, int n)
570{
571 register int32_t r;
572 register uint32_t p, dropped_bits;
573
574 r = x >> n;
575 p = RANDOM() & ((0x1 << n) - 1);
576 dropped_bits = x & ((0x1 << n) - 1);
577
578 if (p < dropped_bits) {
579 return (r + 0x1) << n;
580 } else {
581 return r << n;
582 }
583}
584
590static inline int16_t __stdfix_stochastic_round_s16(int16_t x, int n)
591{
592 register int16_t r;
593 register uint16_t p, dropped_bits;
594
595 r = x >> n;
596 p = RANDOM() & ((0x1 << n) - 1);
597 dropped_bits = x & ((0x1 << n) - 1);
598
599 if (p < dropped_bits) {
600 return (r + 0x1) << n;
601 } else {
602 return r << n;
603 }
604}
605
611static inline uint64_t __stdfix_stochastic_round_u64(uint64_t x, int n)
612{
613 register uint64_t r;
614 register uint64_t p, dropped_bits;
615
616 r = x >> n;
617 p = RANDOM() >> (32 - n);
618 dropped_bits = x & (((uint64_t) 0x1 << n) - 1);
619
620 if (p < dropped_bits) {
621 return (r + 0x1) << n;
622 } else {
623 return r << n;
624 }
625}
626
632static inline uint32_t __stdfix_stochastic_round_u32(uint32_t x, int n)
633{
634 register uint32_t r;
635 register uint32_t p, dropped_bits;
636
637 r = x >> n;
638 p = RANDOM() & ((0x1 << n) - 1);
639 dropped_bits = x & ((0x1 << n) - 1);
640
641 if (p < dropped_bits) {
642 return (r + 0x1) << n;
643 } else {
644 return r << n;
645 }
646}
647
653static inline uint16_t __stdfix_stochastic_round_u16(uint16_t x, int n)
654{
655 register uint16_t r;
656 register uint16_t p, dropped_bits;
657
658 r = x >> n;
659 p = RANDOM() & ((0x1 << n) - 1);
660 dropped_bits = x & ((0x1 << n) - 1);
661
662 if (p < dropped_bits) {
663 return (r + 0x1) << n;
664 } else {
665 return r << n;
666 }
667}
669
680static inline int32_t __stdfix_smul_k_round_nearest(int32_t x, int32_t y)
681{
682 if (x == INT32_MIN && y == INT32_MIN) { // special case for -1.0*-1.0
683 return INT32_MAX;
684 }
685
687 (__I64(x) * __I64(y)), 15) >> 15);
688}
689
696static inline int32_t __stdfix_smul_k_round_stochastic(int32_t x, int32_t y)
697{
698 if (x == INT32_MIN && y == INT32_MIN) { // special case for -1.0*-1.0
699 return INT32_MAX;
700 }
701
702 return __stdfix_sat_k(
703 __stdfix_stochastic_round_s64((__I64(x) * __I64(y)), 15) >> 15);
704}
705
712static inline uint32_t __stdfix_smul_ulr_round_nearest(uint32_t x, uint32_t y)
713{
715 (__U64(x) * __U64(y)), 33) >> 33);
716}
717
725 uint32_t x, uint32_t y)
726{
727 // Note, we preshift the answer by 1 before rounding, to do without the
728 // 64-bit RNG.
729 return __stdfix_sat_ulr(
730 __stdfix_stochastic_round_u64((__U64(x) * __U64(y)) >> 1, 32) >> 32);
731}
733
744static inline int32_t __stdfix_smul_hk_round_nearest(int32_t x, int32_t y)
745{
746 if (x == INT16_MIN && y == INT16_MIN) { // special case for -1.0*-1.0
747 return INT16_MAX;
748 }
749
750 return __stdfix_sat_hk(__stdfix_round_s32((__I32(x) * __I32(y)), 7) >> 7);
751}
752
759static inline int32_t __stdfix_smul_hk_round_stochastic(int32_t x, int32_t y)
760{
761 if (x == INT16_MIN && y == INT16_MIN) { // special case for -1.0*-1.0
762 return INT16_MAX;
763 }
764
765 return __stdfix_sat_hk(
766 __stdfix_stochastic_round_s32((__I32(x) * __I32(y)), 7) >> 7);
767}
768
775static inline uint32_t __stdfix_smul_ur_round_nearest(uint32_t x, uint32_t y)
776{
777 return __stdfix_sat_ur(
778 __stdfix_round_u32((__U32(x) * __U32(y)), 17) >> 17);
779}
780
788 uint32_t x, uint32_t y)
789{
790 return __stdfix_sat_ur(
791 __stdfix_stochastic_round_u32((__U32(x) * __U32(y)), 17) >> 17);
792}
794
815{
816 register int64_t r;
817
818 r = (int64_t)(bitsk (x)) * (int64_t)(bitslr (y));
819
820 return (kbits (((int32_t)(r >> 31))));
821}
822
829{
830 register int64_t r;
831
832 r = (int64_t)(bitsk (x)) * (int64_t)(bitslr (y));
833
834 return (kbits (((int32_t)(r >> 31) + ((int32_t)(r >> 30) & 1))));
835}
836
843{
844 register int64_t r;
845
847 (int64_t)(bitsk (x)) * (int64_t)(bitslr (y)), 31);
848
849 return (kbits (((int32_t)(r >> 31))));
850}
851
858{
859 register int64_t r;
860
861 r = (int64_t)(bitsk (x)) * (uint64_t)(bitsulr (y));
862
863 return (kbits (((int32_t)(r >> 32))));
864}
865
872{
873 register int64_t r;
874
875 r = (int64_t)(bitsk (x)) * (uint64_t)(bitsulr (y));
876
877 return (kbits (((int32_t)(r >> 32) + ((int32_t)(r >> 31) & 1))));
878}
879
886{
887 register int64_t r;
888
890 (int64_t)(bitsk (x)) * (uint64_t)(bitsulr (y)), 32);
891
892 return kbits((int32_t) (r >> 32));
893}
894
901{
902 register int64_t r;
903
904 r = (int64_t) bitslr(x) * (uint64_t) bitsulr(y);
905
906 return lrbits((int32_t) (r >> 32));
907}
908
915{
916 register int64_t r;
917
918 r = (int64_t)(bitslr (x)) * (uint64_t) bitsulr(y);
919
920 return lrbits(((int32_t)(r >> 32) + ((int32_t)(r >> 31) & 1)));
921}
922
929{
930 register int64_t r;
931
933 (int64_t) bitslr(x) * (uint64_t) bitsulr(y), 32);
934
935 return lrbits((int32_t) (r >> 32));
936}
937
938/* ---------------------------------------------------------------------
939 * 16-bit multiplies
940 */
941
948{
949 register int32_t r;
950
951 r = (int32_t) bitshk(x) * (int32_t) bitsr(y);
952
953 return hkbits((int32_t) (r >> 15));
954}
955
962{
963 register int32_t r;
964
965 r = (int32_t) bitshk(x) * (int32_t) bitsr(y);
966
967 return hkbits((int32_t) (r >> 15) + ((int32_t) (r >> 14) & 1));
968}
969
976{
977 register int32_t r;
978
980 (int32_t) bitshk(x) * (int32_t) bitsr(y), 15);
981
982 return hkbits((int32_t) (r >> 15));
983}
984
991{
992 register int32_t r;
993
994 r = (int32_t) bitshk(x) * (uint32_t) bitsur(y);
995
996 return hkbits((int32_t) (r >> 16));
997}
998
1005{
1006 register int32_t r;
1007
1008 r = (int32_t) bitshk(x) * (uint32_t) bitsur(y);
1009
1010 return hkbits((int32_t) (r >> 16) + ((int32_t) (r >> 15) & 1));
1011}
1012
1019{
1020 register int32_t r;
1021
1023 (int32_t) bitshk(x) * (int32_t) bitsur(y), 16);
1024
1025 return hkbits((int32_t) (r >> 16));
1026}
1027
1034{
1035 register int32_t r;
1036
1037 r = (int32_t) bitsr(x) * (uint32_t) bitsur(y);
1038
1039 return rbits((int32_t) (r >> 16));
1040}
1041
1048{
1049 register int32_t r;
1050
1051 r = (int32_t) bitsr(x) * (uint32_t) bitsur(y);
1052
1053 return rbits((int32_t) (r >> 16) + ((int32_t) (r >> 15) & 1));
1054}
1055
1062{
1063 register int32_t r;
1064
1066 (int32_t) bitsr(x) * (int32_t) bitsur(y), 16);
1067
1068 return rbits((int32_t) (r >> 16));
1069}
1071
1072#endif
Pseudo-random number generators.
static s87 short_accum_times_u_fract_nearest(s87 x, u016 y)
Multiply an s87 and an u016 and return an s87 answer rounded to the nearest s87.
Definition round.h:1004
static s87 short_accum_times_fract_stochastic(s87 x, s015 y)
Multiply two s87 values and return an s87 answer rounded to a neighbouring s87 stochastically.
Definition round.h:975
static uint32_t __stdfix_smul_ulr_round_stochastic(uint32_t x, uint32_t y)
Multiply two integer representations of u032 and return an integer representation of an s031 answer,...
Definition round.h:724
static s015 fract_times_u_fract_stochastic(s015 x, u016 y)
Multiply an u016 and an s015 and return an s015 answer with stochastic rounding.
Definition round.h:1061
static s031 long_fract_times_u_long_fract_stochastic(s031 x, u032 y)
Multiply an s031 and an u032 and return a s031 answer rounded to a neighbouring s031 stochastically.
Definition round.h:928
static int32_t __stdfix_smul_k_round_stochastic(int32_t x, int32_t y)
Multiply two integer representations of s1615 and return an integer representation of an s1615 answer...
Definition round.h:696
static int64_t __stdfix_stochastic_round_s64(int64_t x, int n)
Stochastic rounding: signed 64-bit.
Definition round.h:533
static s1615 accum_times_long_fract_nearest(s1615 x, s031 y)
Multiply an s1615 and an s031 and return an s1615 answer rounded to the nearest s1615.
Definition round.h:828
static s87 short_accum_times_u_fract(s87 x, u016 y)
Multiply an s87 and an u016 and return an s87 answer without rounding.
Definition round.h:990
static uint16_t __stdfix_stochastic_round_u16(uint16_t x, int n)
Stochastic rounding: unsigned 16-bit.
Definition round.h:653
static s031 long_fract_times_u_long_fract(s031 x, u032 y)
Multiply an s031 and an u032 and return a s031 answer, without rounding.
Definition round.h:900
static s1615 accum_times_u_long_fract(s1615 x, u032 y)
Multiply s1615 and an u032 and return an s1615 answer, without rounding.
Definition round.h:857
static uint32_t __stdfix_stochastic_round_u32(uint32_t x, int n)
Stochastic rounding: unsigned 32-bit.
Definition round.h:632
static int32_t __stdfix_smul_hk_round_nearest(int32_t x, int32_t y)
Multiply two integer representations of s87 and return an integer representation of an s87 answer,...
Definition round.h:744
static uint32_t __stdfix_smul_ulr_round_nearest(uint32_t x, uint32_t y)
Multiply two integer representations of u032 and return an integer representation of an s031 answer,...
Definition round.h:712
#define RANDOM()
Definition round.h:48
static int32_t __stdfix_stochastic_round_s32(int32_t x, int n)
Stochastic rounding: signed 32-bit.
Definition round.h:569
static s015 fract_times_u_fract(s015 x, u016 y)
Multiply an u016 and an s015 and return an s015 answer without rounding.
Definition round.h:1033
static uint64_t __stdfix_stochastic_round_u64(uint64_t x, int n)
Stochastic rounding: unsigned 64-bit.
Definition round.h:611
static int32_t __stdfix_smul_hk_round_stochastic(int32_t x, int32_t y)
Multiply two integer representations of s87 and return an integer representation of an s87 answer,...
Definition round.h:759
static s015 fract_times_u_fract_nearest(s015 x, u016 y)
Multiply an u016 and an s015 and return an s015 answer rounded to the nearest s015.
Definition round.h:1047
static int32_t __stdfix_smul_k_round_nearest(int32_t x, int32_t y)
Multiply two integer representations of s1615 and return an integer representation of an s1615 answer...
Definition round.h:680
static uint32_t __stdfix_smul_ur_round_nearest(uint32_t x, uint32_t y)
Multiply two integer representations of u016 and return an integer representation of an s015 answer,...
Definition round.h:775
static s1615 accum_times_u_long_fract_nearest(s1615 x, u032 y)
Multiply s1615 and an u032 and return an s1615 answer rounded to the nearest s1615.
Definition round.h:871
static s1615 accum_times_u_long_fract_stochastic(s1615 x, u032 y)
Multiply s1615 and an u032 and return an s1615 answer rounded to a neighbouring s1615 stochastically.
Definition round.h:885
static s1615 accum_times_long_fract(s1615 x, s031 y)
Multiply an s1615 and an s031 and return an s1615 answer, without rounding.
Definition round.h:814
static s87 short_accum_times_fract_nearest(s87 x, s015 y)
Multiply two s87 values and return an s87 answer rounded to the nearest s87.
Definition round.h:961
static int64_t __stdfix_stochastic_round_s64_alternative(int64_t x, int n)
Alternative algorithm for __stdfix_stochastic_round_s64().
Definition round.h:554
static uint32_t __stdfix_smul_ur_round_stochastic(uint32_t x, uint32_t y)
Multiply two integer representations of u016 and return an integer representation of an s015 answer,...
Definition round.h:787
static s87 short_accum_times_u_fract_stochastic(s87 x, u016 y)
Multiply an s87 and an u016 and return an s87 answer rounded to a neighbouring s87 stochastically.
Definition round.h:1018
static s1615 accum_times_long_fract_stochastic(s1615 x, s031 y)
Multiply s1615 and an s031 and return an s1615 answer rounded to a neighbouring s1615 stochastically.
Definition round.h:842
static uint32_t cheap_generator(void)
Cheap PRNG from "Numerical Recipes in C", page 284.
Definition round.h:513
static s87 short_accum_times_fract(s87 x, s015 y)
Multiply two s87 numbers and return an s87 answer without rounding.
Definition round.h:947
static s031 long_fract_times_u_long_fract_nearest(s031 x, u032 y)
Multiply an s031 and an u032 and return a s031 answer rounded to the nearest s031.
Definition round.h:914
static int16_t __stdfix_stochastic_round_s16(int16_t x, int n)
Stochastic rounding: signed 16-bit.
Definition round.h:590
Additions to the stdfix.h file to support full Draft ISO/IEC standards compliance.
static s031 lrbits(const int_lr_t n)
Converts a signed integer into a signed long fract.
Definition stdfix-full-iso.h:424
unsigned fract u016
An alternative name for the unsigned fract type.
Definition stdfix-full-iso.h:193
static int_lr_t bitslr(const s031 f)
Converts a long fract into an integer.
Definition stdfix-full-iso.h:263
#define __U32(x)
Cast to uint32_t.
Definition stdfix-full-iso.h:561
fract s015
An alternative name for the signed fract type.
Definition stdfix-full-iso.h:175
static uint32_t __stdfix_sat_ur(const uint32_t x)
Saturates an unsigned integer to 16 bits.
Definition stdfix-full-iso.h:674
#define __U64(x)
Cast to uint64_t.
Definition stdfix-full-iso.h:563
static int_k_t bitsk(const s1615 f)
Converts an accum into an integer.
Definition stdfix-full-iso.h:289
static int32_t __stdfix_sat_k(const int64_t x)
Saturates a 64-bit integer to 32-bits.
Definition stdfix-full-iso.h:643
static uint32_t __stdfix_sat_ulr(const uint64_t x)
Saturates an unsigned 64-bit integer to 32 bits.
Definition stdfix-full-iso.h:688
static int32_t __stdfix_sat_hk(const int32_t x)
Saturates an integer to 16 bits.
Definition stdfix-full-iso.h:626
static uint32_t __stdfix_round_u32(uint32_t x, int n)
This function rounds the input unsigned 32-bit integer to a number of bits, returning a 32-bit intege...
Definition stdfix-full-iso.h:1834
static int_r_t bitsr(const s015 f)
Converts a fract into an integer.
Definition stdfix-full-iso.h:250
static uint_ur_t bitsur(const u016 f)
Converts an unsigned fract into an integer.
Definition stdfix-full-iso.h:328
static uint_ulr_t bitsulr(const u032 f)
Converts an unsigned long fract into an integer.
Definition stdfix-full-iso.h:341
static uint64_t __stdfix_round_u64(uint64_t x, int n)
This function rounds the input unsigned 64-bit integer to a number of bits, returning a 64-bit intege...
Definition stdfix-full-iso.h:1853
long fract s031
An alternative name for the signed long fract type.
Definition stdfix-full-iso.h:178
short accum s87
An alternative name for the signed short accum type.
Definition stdfix-full-iso.h:181
static int64_t __stdfix_round_s64(int64_t x, int n)
This function rounds the input signed 64-bit integer to a number of bits, returning a 64-bit integer.
Definition stdfix-full-iso.h:1929
accum s1615
An alternative name for the signed accum type.
Definition stdfix-full-iso.h:184
static s015 rbits(const int_r_t n)
Converts a signed integer into a signed fract.
Definition stdfix-full-iso.h:411
static int_hk_t bitshk(const s87 f)
Converts a short accum into an integer.
Definition stdfix-full-iso.h:276
static s87 hkbits(const int_hk_t n)
Converts a signed integer into a signed short accum.
Definition stdfix-full-iso.h:437
unsigned long fract u032
An alternative name for the unsigned long fract type.
Definition stdfix-full-iso.h:196
static int32_t __stdfix_round_s32(int32_t x, int n)
This function rounds the input signed 32-bit integer to a number of bits, returning a 32-bit integer.
Definition stdfix-full-iso.h:1910
#define __I32(x)
Cast to int32_t.
Definition stdfix-full-iso.h:555
static s1615 kbits(const int_k_t n)
Converts a signed integer into a signed accum.
Definition stdfix-full-iso.h:450
#define __I64(x)
Cast to int64_t.
Definition stdfix-full-iso.h:557
Utility functions for SpiNNaker.