public static DoubleAD logSum ( DoubleAD [ ] logInputs , int fromIndex , int toIndex ) { if ( logInputs . length == 0 ) throw new IllegalArgumentException ( ) ; if ( fromIndex >= 0 && toIndex < logInputs . length && fromIndex >= toIndex ) return new DoubleAD ( Double . NEGATIVE_INFINITY , Double . NEGATIVE_INFINITY ) ; int maxIdx = fromIndex ; double max = logInputs [ fromIndex ] . getval ( ) ; double maxdot = logInputs [ fromIndex ] . getdot ( ) ; for ( int i = fromIndex + 1 ; i < toIndex ; i ++ ) { if ( logInputs [ i ] . getval ( ) > max ) { maxIdx = i ; maxdot = logInputs [ i ] . getdot ( ) ; max = logInputs [ i ] . getval ( ) ; } } DoubleAD ret = new DoubleAD ( ) ; boolean haveTerms = false ; double intermediate = 0.0 ; double intermediateDot = 0.0 ; double curEXP ; double cutoff = max - SloppyMath . LOGTOLERANCE ; // we avoid rearranging the array and so test indices each time! for ( int i = fromIndex ; i < toIndex ; i ++ ) { if ( i != maxIdx && logInputs [ i ] . getval ( ) > cutoff ) { haveTerms = true ; curEXP = Math . exp ( logInputs [ i ] . getval ( ) - max ) ; intermediate += curEXP ; intermediateDot += curEXP * logInputs [ i ] . getdot ( ) ; } } if ( haveTerms ) { ret . setval ( max + Math . log ( 1.0 + intermediate ) ) ; ret . setdot ( ( maxdot + intermediateDot ) / ( 1.0 + intermediate ) ) ; } else { ret . setval ( max ) ; ret . setdot ( maxdot ) ; } return ret ; }
Some of this might need to change for optimal AD