/**
*
*/
package edu.berkeley.nlp.util;
import java.util.Arrays;
import edu.berkeley.nlp.math.DoubleArrays;
import edu.berkeley.nlp.math.SloppyMath;
/**
* @author petrov
*
*/
public class ScalingTools {
// SCALING
public static final int LOGSCALE = 100;
public static final double SCALE = Math.exp(LOGSCALE);
// Note: e^709 is the largest double java can handle.
public static double calcScaleFactor(double logScale) {
return calcScaleFactor(logScale,SCALE);
}
public static double calcScaleFactor(double logScale, double scale) {
if (logScale==Integer.MIN_VALUE){
return 0.0;//System.out.println("give me a break!");
}
if (logScale == 0.0)
return 1.0;
if (logScale == 1.0)
return scale;
if (logScale == 2.0)
return scale * scale;
if (logScale == 3.0)
return scale * scale * scale;
if (logScale == -1.0)
return 1.0 / scale;
if (logScale == -2.0)
return 1.0 / scale / scale;
if (logScale == -3.0)
return 1.0 / scale / scale / scale;
return Math.pow(scale, logScale);
}
public static int scaleArray(double[] scores, int previousScale){
if (previousScale==Integer.MIN_VALUE){
return previousScale;//System.out.println("give me a break!");
}
// if (true) return previousScale;
int logScale = 0;
double scale = 1.0;
double max = DoubleArrays.max(scores);
if (max==Double.POSITIVE_INFINITY) {
// System.out.println("Infinity");
return 0;
}
if (max==0) return previousScale;
while (max > SCALE) {
max /= SCALE;
scale *= SCALE;
logScale += 1;
}
while (max > 0.0 && max < 1.0 / SCALE) {
max *= SCALE;
scale /= SCALE;
logScale -= 1;
}
if (logScale != 0) {
for (int i = 0; i < scores.length; i++) {
scores[i] /= scale;
}
}
// if (SloppyMath.isDangerous(ArrayMath.max(scores))){
// System.out.println("Undeflow when scaling scores!");
// }
return previousScale + logScale;
}
public static void scaleArrayToScale(double[] scores, int previousScale, int newScale){
int scaleDiff = previousScale-newScale;
if (scaleDiff == 0) return; // nothing to do
double max = DoubleArrays.max(scores);
if (SloppyMath.isDangerous(max)) return;
double scale = calcScaleFactor(scaleDiff);
if (Math.abs(scaleDiff)>=800){
// under-/overflow...
Arrays.fill(scores,0.0);
return;
}
for (int i = 0; i < scores.length; i++) {
scores[i] *= scale;
}
// if (SloppyMath.isDangerous(ArrayMath.max(scores))){
// System.out.println("Undeflow when scaling scores!");
// }
}
public static double scaleToScale(double score, int previousScale, int newScale){
int scaleDiff = previousScale-newScale;
if (scaleDiff == 0) return score; // nothing to do
double max = score;
if (SloppyMath.isDangerous(max)) return 0;
double scale = calcScaleFactor(scaleDiff);
if (Math.abs(scaleDiff)>=800){
// under-/overflow...
return 0;
}
score *= scale;
return score;
}
public static boolean isBadScale(int scale)
{
return scale == Integer.MIN_VALUE || scale == Integer.MAX_VALUE || scale == Integer.MAX_VALUE - 1 || scale == Integer.MIN_VALUE + 1 || scale == Integer.MAX_VALUE - 2 || scale == Integer.MIN_VALUE + 2;
}
}