Originally committed as revision 5955 to svn://svn.ffmpeg.org/ffmpeg/trunk
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,52 @@ |
| 0 |
+#include <inttypes.h> |
|
| 1 |
+#include <stdio.h> |
|
| 2 |
+#include <assert.h> |
|
| 3 |
+#include "softfloat.h" |
|
| 4 |
+#include "common.h" |
|
| 5 |
+#include "log.h" |
|
| 6 |
+ |
|
| 7 |
+#undef printf |
|
| 8 |
+ |
|
| 9 |
+int main(){
|
|
| 10 |
+ SoftFloat one= av_int2sf(1, 0); |
|
| 11 |
+ SoftFloat sf1, sf2; |
|
| 12 |
+ double d1, d2; |
|
| 13 |
+ int i, j; |
|
| 14 |
+av_log_level = AV_LOG_DEBUG; |
|
| 15 |
+ |
|
| 16 |
+ d1= 1; |
|
| 17 |
+ for(i= 0; i<10; i++){
|
|
| 18 |
+ d1= 1/(d1+1); |
|
| 19 |
+ } |
|
| 20 |
+ printf("test1 double=%d\n", (int)(d1 * (1<<24)));
|
|
| 21 |
+ |
|
| 22 |
+ sf1= one; |
|
| 23 |
+ for(i= 0; i<10; i++){
|
|
| 24 |
+ sf1= av_div_sf(one, av_normalize_sf(av_add_sf(one, sf1))); |
|
| 25 |
+ } |
|
| 26 |
+ printf("test1 sf =%d\n", av_sf2int(sf1, 24));
|
|
| 27 |
+ |
|
| 28 |
+ |
|
| 29 |
+ for(i= 0; i<100; i++){
|
|
| 30 |
+ START_TIMER |
|
| 31 |
+ d1= i; |
|
| 32 |
+ d2= i/100.0; |
|
| 33 |
+ for(j= 0; j<1000; j++){
|
|
| 34 |
+ d1= (d1+1)*d2; |
|
| 35 |
+ } |
|
| 36 |
+ STOP_TIMER("float add mul")
|
|
| 37 |
+ } |
|
| 38 |
+ printf("test2 double=%d\n", (int)(d1 * (1<<24)));
|
|
| 39 |
+ |
|
| 40 |
+ for(i= 0; i<100; i++){
|
|
| 41 |
+ START_TIMER |
|
| 42 |
+ sf1= av_int2sf(i, 0); |
|
| 43 |
+ sf2= av_div_sf(av_int2sf(i, 2), av_int2sf(200, 3)); |
|
| 44 |
+ for(j= 0; j<1000; j++){
|
|
| 45 |
+ sf1= av_mul_sf(av_add_sf(sf1, one),sf2); |
|
| 46 |
+ } |
|
| 47 |
+ STOP_TIMER("softfloat add mul")
|
|
| 48 |
+ } |
|
| 49 |
+ printf("test2 sf =%d (%d %d)\n", av_sf2int(sf1, 24), sf1.exp, sf1.mant);
|
|
| 50 |
+ return 0; |
|
| 51 |
+} |
| 0 | 52 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,103 @@ |
| 0 |
+//copyright Michael Niedermayer 2006 license:LGPL |
|
| 1 |
+ |
|
| 2 |
+#define MIN_EXP -126 |
|
| 3 |
+#define MAX_EXP 126 |
|
| 4 |
+#define ONE_BITS 29 |
|
| 5 |
+ |
|
| 6 |
+typedef struct SoftFloat{
|
|
| 7 |
+ int32_t exp; |
|
| 8 |
+ int32_t mant; |
|
| 9 |
+}SoftFloat; |
|
| 10 |
+ |
|
| 11 |
+static SoftFloat av_normalize_sf(SoftFloat a){
|
|
| 12 |
+ if(a.mant){
|
|
| 13 |
+#if 1 |
|
| 14 |
+ while((a.mant + 0x20000000U)<0x40000000U){
|
|
| 15 |
+ a.mant += a.mant; |
|
| 16 |
+ a.exp -= 1; |
|
| 17 |
+ } |
|
| 18 |
+#else |
|
| 19 |
+ int s=ONE_BITS + 1 - av_log2(a.mant ^ (a.mant<<1)); |
|
| 20 |
+ a.exp -= s; |
|
| 21 |
+ a.mant <<= s; |
|
| 22 |
+#endif |
|
| 23 |
+ if(a.exp < MIN_EXP){
|
|
| 24 |
+ a.exp = MIN_EXP; |
|
| 25 |
+ a.mant= 0; |
|
| 26 |
+ } |
|
| 27 |
+ }else{
|
|
| 28 |
+ a.exp= MIN_EXP; |
|
| 29 |
+ } |
|
| 30 |
+ return a; |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+static inline SoftFloat av_normalize1_sf(SoftFloat a){
|
|
| 34 |
+#if 1 |
|
| 35 |
+ if(a.mant + 0x40000000 < 0){
|
|
| 36 |
+ a.exp++; |
|
| 37 |
+ a.mant>>=1; |
|
| 38 |
+ } |
|
| 39 |
+ return a; |
|
| 40 |
+#elif 1 |
|
| 41 |
+ int t= a.mant + 0x40000000 < 0; |
|
| 42 |
+ return (SoftFloat){a.exp+t, a.mant>>t};
|
|
| 43 |
+#else |
|
| 44 |
+ int t= (a.mant + 0x40000000U)>>31; |
|
| 45 |
+ return (SoftFloat){a.exp+t, a.mant>>t};
|
|
| 46 |
+#endif |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 49 |
+/** |
|
| 50 |
+ * |
|
| 51 |
+ * @return will not be more denormalized then a+b, so if either input is |
|
| 52 |
+ * normalized then the output wont be worse then the other input |
|
| 53 |
+ * if both are normalized then the output will be normalized |
|
| 54 |
+ */ |
|
| 55 |
+static inline SoftFloat av_mul_sf(SoftFloat a, SoftFloat b){
|
|
| 56 |
+ a.exp += b.exp; |
|
| 57 |
+ a.mant = (a.mant * (int64_t)b.mant) >> ONE_BITS; |
|
| 58 |
+ return av_normalize1_sf(a); |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+/** |
|
| 62 |
+ * |
|
| 63 |
+ * b has to be normalized and not zero |
|
| 64 |
+ * @return will not be more denormalized then a |
|
| 65 |
+ */ |
|
| 66 |
+static SoftFloat av_div_sf(SoftFloat a, SoftFloat b){
|
|
| 67 |
+ a.exp -= b.exp+1; |
|
| 68 |
+ a.mant = ((int64_t)a.mant<<(ONE_BITS+1)) / b.mant; |
|
| 69 |
+ return av_normalize1_sf(a); |
|
| 70 |
+} |
|
| 71 |
+ |
|
| 72 |
+static inline int av_cmp_sf(SoftFloat a, SoftFloat b){
|
|
| 73 |
+ int t= a.exp - b.exp; |
|
| 74 |
+ if(t<0) return (a.mant >> (-t)) - b.mant ; |
|
| 75 |
+ else return a.mant - (b.mant >> t); |
|
| 76 |
+} |
|
| 77 |
+ |
|
| 78 |
+static inline SoftFloat av_add_sf(SoftFloat a, SoftFloat b){
|
|
| 79 |
+ int t= a.exp - b.exp; |
|
| 80 |
+ if(t<0) return av_normalize1_sf((SoftFloat){b.exp, b.mant + (a.mant >> (-t))});
|
|
| 81 |
+ else return av_normalize1_sf((SoftFloat){a.exp, a.mant + (b.mant >> t )});
|
|
| 82 |
+} |
|
| 83 |
+ |
|
| 84 |
+static inline SoftFloat av_sub_sf(SoftFloat a, SoftFloat b){
|
|
| 85 |
+ return av_add_sf(a, (SoftFloat){b.exp, -b.mant});
|
|
| 86 |
+} |
|
| 87 |
+ |
|
| 88 |
+//FIXME sqrt, log, exp, pow, sin, cos |
|
| 89 |
+ |
|
| 90 |
+static inline SoftFloat av_int2sf(int v, int frac_bits){
|
|
| 91 |
+ return av_normalize_sf((SoftFloat){ONE_BITS-frac_bits, v});
|
|
| 92 |
+} |
|
| 93 |
+ |
|
| 94 |
+/** |
|
| 95 |
+ * |
|
| 96 |
+ * rounding is to -inf |
|
| 97 |
+ */ |
|
| 98 |
+static inline int av_sf2int(SoftFloat v, int frac_bits){
|
|
| 99 |
+ v.exp += frac_bits - ONE_BITS; |
|
| 100 |
+ if(v.exp >= 0) return v.mant << v.exp ; |
|
| 101 |
+ else return v.mant >>(-v.exp); |
|
| 102 |
+} |