// Path: public-java/iamcontent-core/src/main/java/com/iamcontent/core/math/InterRangeDoubleConverter.java
// public static final InterRangeDoubleConverter REVERSE_NORMAL_CONVERTER = converterFromNormalTo(REVERSE_NORMAL_RANGE);
// 
// Path: public-java/iamcontent-core/src/main/java/com/iamcontent/core/math/DoubleConverter.java
// public interface DoubleConverter {
// 	double applyForward(double v);
// 	double applyBackward(double v);
// 	
//     static DoubleConverter IDENTITY = new DoubleConverter() {
// 		@Override
// 		public double applyForward(double v) {
// 			return v;
// 		}
// 		
// 		@Override
// 		public double applyBackward(double v) {
// 			return v;
// 		}
// 	};
// }
// 
// Path: public-java/iamcontent-core/src/main/java/com/iamcontent/core/math/InterRangeDoubleConverter.java
// public class InterRangeDoubleConverter implements DoubleConverter {
// 
// 	public static final ClampingMode DEFAULT_MODE = ClampingMode.CLAMPED;
// 	public static final InterRangeDoubleConverter REVERSE_NORMAL_CONVERTER = converterFromNormalTo(REVERSE_NORMAL_RANGE);
// 	
// 	/**
// 	 * Indicates whether a converted value should be clamped to its target range or not.
// 	 */
// 	public static enum ClampingMode {
// 		CLAMPED {
// 			@Override
// 			double apply(double d, DoubleRange r) {
// 				return r.clamp(d);
// 			}
// 		}, 
// 		UNCLAMPED {
// 			@Override
// 			double apply(double d, DoubleRange r) {
// 				return d;
// 			}
// 		};
// 		abstract double apply(double d, DoubleRange r);
// 	};
// 	
// 	private final DoubleRange fromRange, toRange;
// 	private final ClampingMode clampingMode;
// 
// 	public InterRangeDoubleConverter(DoubleRange fromRange, DoubleRange toRange) {
// 		this(fromRange, toRange, DEFAULT_MODE);
// 	}
// 	
// 	public InterRangeDoubleConverter(DoubleRange fromRange, DoubleRange toRange, ClampingMode clampingMode) {
// 		this.fromRange = fromRange;
// 		this.toRange = toRange;
// 		this.clampingMode = clampingMode;
// 	}
// 
// 	public static InterRangeDoubleConverter converterFromNormalTo(double toLimit1, double toLimit2) {
// 		return converterFromNormalTo(range(toLimit1, toLimit2));
// 	}
// 	
// 	public static InterRangeDoubleConverter converterFromNormalTo(DoubleRange toRange) {
// 		return interRangeConverter(NORMAL_RANGE, toRange, DEFAULT_MODE);
// 	}
// 
// 	public static InterRangeDoubleConverter converterFromNormalTo(DoubleRange toRange, ClampingMode clampingMode) {
// 		return interRangeConverter(NORMAL_RANGE, toRange, clampingMode);
// 	}
// 
// 	public static InterRangeDoubleConverter interRangeConverter(DoubleRange fromRange, DoubleRange toRange) {
// 		return interRangeConverter(fromRange, toRange, DEFAULT_MODE);
// 	}
// 
// 	public static InterRangeDoubleConverter interRangeConverter(DoubleRange fromRange, DoubleRange toRange, ClampingMode clampingMode) {
// 		return new InterRangeDoubleConverter(fromRange, toRange, clampingMode);
// 	}
// 	
// 	@Override
// 	public double applyForward(double v) {
// 		return convertAndClamp(v, fromRange, toRange);
// 	}
// 
// 	@Override
// 	public double applyBackward(double v) {
// 		return convertAndClamp(v, toRange, fromRange);
// 	}
// 
// 	private double convertAndClamp(double d, DoubleRange fromRange, DoubleRange toRange) {
// 		final double convertedButUnclamped = linearConvert(d, fromRange, toRange);
// 		return clampingMode.apply(convertedButUnclamped, toRange);
// 	}
// 
// 	private static double linearConvert(double v, DoubleRange inRange, DoubleRange outRange) {
// 		return MathUtils.linearConvert(v, inRange.getLimit1(), inRange.getLimit2(), outRange.getLimit1(), outRange.getLimit2());
// 	}
// 
// 	public DoubleRange getFromRange() {
// 		return fromRange;
// 	}
// 
// 	public DoubleRange getToRange() {
// 		return toRange;
// 	}
// 
// 	public ClampingMode getClampingMode() {
// 		return clampingMode;
// 	}
// }
// 
// Path: public-java/io/iamcontent-servos/src/main/java/com/iamcontent/device/servo/ServoCalibration.java
// public interface ServoCalibration extends AnalogIOCalibration, ServoFeatures<DoubleConverter> {
// 	static ServoCalibration IDENTITY = new ImmutableServoCalibration(DoubleConverter.IDENTITY);
// }


import static com.iamcontent.core.math.InterRangeDoubleConverter.REVERSE_NORMAL_CONVERTER;
import com.iamcontent.core.math.DoubleConverter;
import com.iamcontent.core.math.InterRangeDoubleConverter;
import com.iamcontent.device.servo.ServoCalibration;
package com.iamcontent.device.servo.impl;



/**
 * Defines an immutable {@link ServoCalibration}.
 * @author Greg Elderfield
 */
public class ImmutableServoCalibration implements ServoCalibration {

	private final DoubleConverter value, speed, acceleration;

// Path: public-java/iamcontent-core/src/main/java/com/iamcontent/core/math/InterRangeDoubleConverter.java
// public static final InterRangeDoubleConverter REVERSE_NORMAL_CONVERTER = converterFromNormalTo(REVERSE_NORMAL_RANGE);
// 
// Path: public-java/iamcontent-core/src/main/java/com/iamcontent/core/math/DoubleConverter.java
// public interface DoubleConverter {
// 	double applyForward(double v);
// 	double applyBackward(double v);
// 	
//     static DoubleConverter IDENTITY = new DoubleConverter() {
// 		@Override
// 		public double applyForward(double v) {
// 			return v;
// 		}
// 		
// 		@Override
// 		public double applyBackward(double v) {
// 			return v;
// 		}
// 	};
// }
// 
// Path: public-java/iamcontent-core/src/main/java/com/iamcontent/core/math/InterRangeDoubleConverter.java
// public class InterRangeDoubleConverter implements DoubleConverter {
// 
// 	public static final ClampingMode DEFAULT_MODE = ClampingMode.CLAMPED;
// 	public static final InterRangeDoubleConverter REVERSE_NORMAL_CONVERTER = converterFromNormalTo(REVERSE_NORMAL_RANGE);
// 	
// 	/**
// 	 * Indicates whether a converted value should be clamped to its target range or not.
// 	 */
// 	public static enum ClampingMode {
// 		CLAMPED {
// 			@Override
// 			double apply(double d, DoubleRange r) {
// 				return r.clamp(d);
// 			}
// 		}, 
// 		UNCLAMPED {
// 			@Override
// 			double apply(double d, DoubleRange r) {
// 				return d;
// 			}
// 		};
// 		abstract double apply(double d, DoubleRange r);
// 	};
// 	
// 	private final DoubleRange fromRange, toRange;
// 	private final ClampingMode clampingMode;
// 
// 	public InterRangeDoubleConverter(DoubleRange fromRange, DoubleRange toRange) {
// 		this(fromRange, toRange, DEFAULT_MODE);
// 	}
// 	
// 	public InterRangeDoubleConverter(DoubleRange fromRange, DoubleRange toRange, ClampingMode clampingMode) {
// 		this.fromRange = fromRange;
// 		this.toRange = toRange;
// 		this.clampingMode = clampingMode;
// 	}
// 
// 	public static InterRangeDoubleConverter converterFromNormalTo(double toLimit1, double toLimit2) {
// 		return converterFromNormalTo(range(toLimit1, toLimit2));
// 	}
// 	
// 	public static InterRangeDoubleConverter converterFromNormalTo(DoubleRange toRange) {
// 		return interRangeConverter(NORMAL_RANGE, toRange, DEFAULT_MODE);
// 	}
// 
// 	public static InterRangeDoubleConverter converterFromNormalTo(DoubleRange toRange, ClampingMode clampingMode) {
// 		return interRangeConverter(NORMAL_RANGE, toRange, clampingMode);
// 	}
// 
// 	public static InterRangeDoubleConverter interRangeConverter(DoubleRange fromRange, DoubleRange toRange) {
// 		return interRangeConverter(fromRange, toRange, DEFAULT_MODE);
// 	}
// 
// 	public static InterRangeDoubleConverter interRangeConverter(DoubleRange fromRange, DoubleRange toRange, ClampingMode clampingMode) {
// 		return new InterRangeDoubleConverter(fromRange, toRange, clampingMode);
// 	}
// 	
// 	@Override
// 	public double applyForward(double v) {
// 		return convertAndClamp(v, fromRange, toRange);
// 	}
// 
// 	@Override
// 	public double applyBackward(double v) {
// 		return convertAndClamp(v, toRange, fromRange);
// 	}
// 
// 	private double convertAndClamp(double d, DoubleRange fromRange, DoubleRange toRange) {
// 		final double convertedButUnclamped = linearConvert(d, fromRange, toRange);
// 		return clampingMode.apply(convertedButUnclamped, toRange);
// 	}
// 
// 	private static double linearConvert(double v, DoubleRange inRange, DoubleRange outRange) {
// 		return MathUtils.linearConvert(v, inRange.getLimit1(), inRange.getLimit2(), outRange.getLimit1(), outRange.getLimit2());
// 	}
// 
// 	public DoubleRange getFromRange() {
// 		return fromRange;
// 	}
// 
// 	public DoubleRange getToRange() {
// 		return toRange;
// 	}
// 
// 	public ClampingMode getClampingMode() {
// 		return clampingMode;
// 	}
// }
// 
// Path: public-java/io/iamcontent-servos/src/main/java/com/iamcontent/device/servo/ServoCalibration.java
// public interface ServoCalibration extends AnalogIOCalibration, ServoFeatures<DoubleConverter> {
// 	static ServoCalibration IDENTITY = new ImmutableServoCalibration(DoubleConverter.IDENTITY);
// }


// Path: public-java/io/iamcontent-servos/src/main/java/com/iamcontent/device/servo/impl/ImmutableServoCalibration.java
import static com.iamcontent.core.math.InterRangeDoubleConverter.REVERSE_NORMAL_CONVERTER;
import com.iamcontent.core.math.DoubleConverter;
import com.iamcontent.core.math.InterRangeDoubleConverter;
import com.iamcontent.device.servo.ServoCalibration;

package com.iamcontent.device.servo.impl;



/**
 * Defines an immutable {@link ServoCalibration}.
 * @author Greg Elderfield
 */
public class ImmutableServoCalibration implements ServoCalibration {

	private final DoubleConverter value, speed, acceleration;

	public static final ServoCalibration REVERSE_NORMAL_SERVO_CALIBRATION = new ImmutableServoCalibration(REVERSE_NORMAL_CONVERTER);