1/* 2 * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * FFmpeg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with FFmpeg; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#ifndef AVUTIL_SOFTFLOAT_H 22#define AVUTIL_SOFTFLOAT_H 23 24#include <stdint.h> 25#include "common.h" 26 27#define MIN_EXP -126 28#define MAX_EXP 126 29#define ONE_BITS 29 30 31typedef struct SoftFloat{ 32 int32_t exp; 33 int32_t mant; 34}SoftFloat; 35 36static av_const SoftFloat av_normalize_sf(SoftFloat a){ 37 if(a.mant){ 38#if 1 39 while((a.mant + 0x20000000U)<0x40000000U){ 40 a.mant += a.mant; 41 a.exp -= 1; 42 } 43#else 44 int s=ONE_BITS + 1 - av_log2(a.mant ^ (a.mant<<1)); 45 a.exp -= s; 46 a.mant <<= s; 47#endif 48 if(a.exp < MIN_EXP){ 49 a.exp = MIN_EXP; 50 a.mant= 0; 51 } 52 }else{ 53 a.exp= MIN_EXP; 54 } 55 return a; 56} 57 58static inline av_const SoftFloat av_normalize1_sf(SoftFloat a){ 59#if 1 60 if(a.mant + 0x40000000 < 0){ 61 a.exp++; 62 a.mant>>=1; 63 } 64 return a; 65#elif 1 66 int t= a.mant + 0x40000000 < 0; 67 return (SoftFloat){a.exp+t, a.mant>>t}; 68#else 69 int t= (a.mant + 0x40000000U)>>31; 70 return (SoftFloat){a.exp+t, a.mant>>t}; 71#endif 72} 73 74/** 75 * @return Will not be more denormalized than a+b. So if either input is 76 * normalized, then the output will not be worse then the other input. 77 * If both are normalized, then the output will be normalized. 78 */ 79static inline av_const SoftFloat av_mul_sf(SoftFloat a, SoftFloat b){ 80 a.exp += b.exp; 81 a.mant = (a.mant * (int64_t)b.mant) >> ONE_BITS; 82 return av_normalize1_sf(a); 83} 84 85/** 86 * b has to be normalized and not zero. 87 * @return Will not be more denormalized than a. 88 */ 89static av_const SoftFloat av_div_sf(SoftFloat a, SoftFloat b){ 90 a.exp -= b.exp+1; 91 a.mant = ((int64_t)a.mant<<(ONE_BITS+1)) / b.mant; 92 return av_normalize1_sf(a); 93} 94 95static inline av_const int av_cmp_sf(SoftFloat a, SoftFloat b){ 96 int t= a.exp - b.exp; 97 if(t<0) return (a.mant >> (-t)) - b.mant ; 98 else return a.mant - (b.mant >> t); 99} 100 101static inline av_const SoftFloat av_add_sf(SoftFloat a, SoftFloat b){ 102 int t= a.exp - b.exp; 103 if(t<0) return av_normalize1_sf((SoftFloat){b.exp, b.mant + (a.mant >> (-t))}); 104 else return av_normalize1_sf((SoftFloat){a.exp, a.mant + (b.mant >> t )}); 105} 106 107static inline av_const SoftFloat av_sub_sf(SoftFloat a, SoftFloat b){ 108 return av_add_sf(a, (SoftFloat){b.exp, -b.mant}); 109} 110 111//FIXME sqrt, log, exp, pow, sin, cos 112 113static inline av_const SoftFloat av_int2sf(int v, int frac_bits){ 114 return av_normalize_sf((SoftFloat){ONE_BITS-frac_bits, v}); 115} 116 117/** 118 * Rounding is to -inf. 119 */ 120static inline av_const int av_sf2int(SoftFloat v, int frac_bits){ 121 v.exp += frac_bits - ONE_BITS; 122 if(v.exp >= 0) return v.mant << v.exp ; 123 else return v.mant >>(-v.exp); 124} 125 126#endif /* AVUTIL_SOFTFLOAT_H */ 127