spinn_common  development
Support code for SpiNNaker applications.
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 
513 static inline uint32_t cheap_generator(void) {
514  static unsigned long idum;
515  idum = 1664525L * idum + 1013904223L;
516 
517  return idum;
518 }
519 
533 static 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 
554 static 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 
569 static 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 
590 static 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 
611 static 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 
632 static 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 
653 static 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 
680 static 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 
696 static 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 
712 static inline uint32_t __stdfix_smul_ulr_round_nearest(uint32_t x, uint32_t y)
713 {
715  (__U64(x) * __U64(y)), 33) >> 33);
716 }
717 
724 static inline uint32_t __stdfix_smul_ulr_round_stochastic(
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 
744 static 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 
759 static 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 
775 static 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 
787 static inline uint32_t __stdfix_smul_ur_round_stochastic(
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 
947 static inline s87 short_accum_times_fract(s87 x, s015 y)
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 
1033 static inline s015 fract_times_u_fract(s015 x, u016 y)
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.