Add Problem::GetParameterization.

This allows the user to query the local parameterization associated
with a parameter block.

Change-Id: I3ab274aa88221c8e2def7c463825bf3927b1fdc9
diff --git a/include/ceres/problem.h b/include/ceres/problem.h
index cd433f9..77ff970 100644
--- a/include/ceres/problem.h
+++ b/include/ceres/problem.h
@@ -312,6 +312,11 @@
   void SetParameterization(double* values,
                            LocalParameterization* local_parameterization);
 
+  // Get the local parameterization object associated with this
+  // parameter block. If there is no parameterization object
+  // associated then NULL is returned.
+  const LocalParameterization* GetParameterization(double* values) const;
+
   // Number of parameter blocks in the problem. Always equals
   // parameter_blocks().size() and parameter_block_sizes().size().
   int NumParameterBlocks() const;
diff --git a/internal/ceres/problem.cc b/internal/ceres/problem.cc
index 89821b9..bc6d26a 100644
--- a/internal/ceres/problem.cc
+++ b/internal/ceres/problem.cc
@@ -178,6 +178,11 @@
   problem_impl_->SetParameterization(values, local_parameterization);
 }
 
+const LocalParameterization* Problem::GetParameterization(
+    double* values) const {
+  return problem_impl_->GetParameterization(values);
+}
+
 bool Problem::Evaluate(const EvaluateOptions& evaluate_options,
                        double* cost,
                        vector<double>* residuals,
diff --git a/internal/ceres/problem_impl.cc b/internal/ceres/problem_impl.cc
index 37cd351..9882677 100644
--- a/internal/ceres/problem_impl.cc
+++ b/internal/ceres/problem_impl.cc
@@ -535,6 +535,12 @@
       ->SetParameterization(local_parameterization);
 }
 
+const LocalParameterization* ProblemImpl::GetParameterization(
+    double* values) const {
+  return FindParameterBlockOrDie(parameter_block_map_, values)
+      ->local_parameterization();
+}
+
 bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options,
                            double* cost,
                            vector<double>* residuals,
diff --git a/internal/ceres/problem_impl.h b/internal/ceres/problem_impl.h
index 35c16cd..da50578 100644
--- a/internal/ceres/problem_impl.h
+++ b/internal/ceres/problem_impl.h
@@ -127,6 +127,7 @@
   void SetParameterBlockVariable(double* values);
   void SetParameterization(double* values,
                            LocalParameterization* local_parameterization);
+  const LocalParameterization* GetParameterization(double* values) const;
 
   bool Evaluate(const Problem::EvaluateOptions& options,
                 double* cost,
diff --git a/internal/ceres/problem_test.cc b/internal/ceres/problem_test.cc
index 858600d..6ad56a5 100644
--- a/internal/ceres/problem_test.cc
+++ b/internal/ceres/problem_test.cc
@@ -502,6 +502,20 @@
       problem.RemoveParameterBlock(y), "Parameter block not found:");
 }
 
+TEST(Problem, GetParameterization) {
+  double x[3];
+  double y[2];
+
+  Problem problem;
+  problem.AddParameterBlock(x, 3);
+  problem.AddParameterBlock(y, 2);
+
+  LocalParameterization* parameterization =  new IdentityParameterization(3);
+  problem.SetParameterization(x, parameterization);
+  EXPECT_EQ(problem.GetParameterization(x), parameterization);
+  EXPECT_TRUE(problem.GetParameterization(y) == NULL);
+}
+
 TEST(Problem, ParameterBlockQueryTest) {
   double x[3];
   double y[4];