1    	/*
2    	 NL reader
3    	
4    	 NL is a format for representing optimization problems such as linear,
5    	 quadratic, nonlinear, complementarity and constraint programming problems
6    	 in discrete or continuous variables. It is described in the technical report
7    	 "Writing .nl Files" (http://www.cs.sandia.gov/~dmgay/nlwrite.pdf).
8    	
9    	 This is a complete reusable C++ implementation of an NL reader.
10   	
11   	 Usage:
12   	   // Read an NL file:
13   	   ReadNLFile(filename, handler);
14   	
15   	   // Read an NL string:
16   	   ReadNLString(string, handler);
17   	
18   	 where handler is an object that receives notifications of problem
19   	 components. See NLHandler for an example of a handler class.
20   	
21   	 Copyright (C) 2013 - 2016 AMPL Optimization Inc
22   	
23   	 Permission to use, copy, modify, and distribute this software and its
24   	 documentation for any purpose and without fee is hereby granted,
25   	 provided that the above copyright notice appear in all copies and that
26   	 both that the copyright notice and this permission notice and warranty
27   	 disclaimer appear in supporting documentation.
28   	
29   	 The author and AMPL Optimization Inc disclaim all warranties with
30   	 regard to this software, including all implied warranties of
31   	 merchantability and fitness.  In no event shall the author be liable
32   	 for any special, indirect or consequential damages or any damages
33   	 whatsoever resulting from loss of use, data or profits, whether in an
34   	 action of contract, negligence or other tortious action, arising out
35   	 of or in connection with the use or performance of this software.
36   	
37   	 Author: Victor Zverovich
38   	 */
39   	
40   	#ifndef MP_NL_READER_H_
41   	#define MP_NL_READER_H_
42   	
43   	#include "mp/common.h"
44   	#include "mp/error.h"
45   	#include "mp/nl.h"
46   	#include "mp/os.h"
47   	
48   	#include <algorithm>
49   	#include <cctype>
50   	#include <cstdlib>
51   	#include <limits>
52   	#include <string>
53   	
54   	namespace mp {
55   	
56   	using fmt::internal::MakeUnsigned;
57   	
58   	/** A read error with location information. */
59   	class ReadError : public Error {
60   	 private:
61   	  std::string filename_;
62   	  int line_;
63   	  int column_;
64   	
65   	  void init(fmt::CStringRef filename, int line, int column,
66   	            fmt::CStringRef format_str, fmt::ArgList args);
67   	
68   	 public:
69   	  /** Constructs the exception object. */
70   	  ReadError(fmt::CStringRef filename, int line, int column,
71   	            fmt::CStringRef format_str, fmt::ArgList args) {
72   	    init(filename, line, column, format_str, args);
73   	  }
74   	
75   	  /** Destructs the exception object. */
76   	  ~ReadError() throw() {}
77   	
78   	  /** Returns the name of the file where error occurred. */
79   	  const std::string &filename() const { return filename_; }
80   	
81   	  /** Returns the line number where error occurred, starting from 1. */
82   	  int line() const { return line_; }
83   	
84   	  /** Returns the column number where error occurred, starting from 1. */
85   	  int column() const { return column_; }
86   	
87   	  FMT_VARIADIC_(char, , ReadError, init,
88   	                fmt::CStringRef, int, int, fmt::CStringRef)
89   	};
90   	
91   	/** A read error with information about offset in a binary input. */
92   	class BinaryReadError : public Error {
93   	 private:
94   	  std::string filename_;
95   	  std::size_t offset_;
96   	
97   	 public:
98   	  /** Constructs the exception object. */
99   	  BinaryReadError(
100  	      const std::string &filename, std::size_t offset, fmt::CStringRef message)
101  	  : Error(message), filename_(filename), offset_(offset) {}
102  	
103  	  /** Destructs the exception object. */
104  	  ~BinaryReadError() throw() {}
105  	
106  	  /** Returns the name of the file where error occurred. */
107  	  const std::string &filename() const { return filename_; }
108  	
109  	  /** Returns the offset in chars to the error location. */
110  	  std::size_t offset() const { return offset_; }
111  	};
112  	
113  	enum {
114  	  /** Maximum number of options reserved for AMPL use in NL and SOL formats. */
115  	  MAX_AMPL_OPTIONS = 9
116  	};
117  	
118  	namespace arith {
119  	
120  	/** Floating-point arithmetic kind. */
121  	enum Kind {
122  	
123  	  /** Unknown floating-point arithmetic. */
124  	  UNKNOWN = 0,
125  	
126  	  /**
127  	    \rst
128  	    Standard `IEEE-754 floating point
129  	    <http://en.wikipedia.org/wiki/IEEE_floating_point>`_ - little endian.
130  	    \endrst
131  	   */
132  	  IEEE_LITTLE_ENDIAN = 1,
133  	
134  	  /** Standard IEEE-754 floating point - big endian. */
135  	  IEEE_BIG_ENDIAN = 2,
136  	
137  	  /**
138  	    \rst
139  	    `IBM floating point
140  	    <http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture>`_.
141  	    \endrst
142  	   */
143  	  IBM = 3,
144  	
145  	  /** VAX floating point (legacy). */
146  	  VAX = 4,
147  	
148  	  /** Cray floating point. */
149  	  CRAY = 5,
150  	
151  	  /** Last floating point. */
152  	  LAST = CRAY
153  	};
154  	
155  	// Returns floating-point arithmetic kind used on the current system.
156  	Kind GetKind();
157  	
158  	inline bool IsIEEE(arith::Kind k) {
159  	  return k == IEEE_LITTLE_ENDIAN || k == IEEE_BIG_ENDIAN;
160  	}
161  	}  // namespace arith
162  	
163  	/**
164  	  \rst
165  	  An NL `header <http://en.wikipedia.org/wiki/Header_(computing)>`_
166  	  which contains information about problem dimensions, such as the number of
167  	  variables and constraints, and the input format.
168  	
169  	  Base class: `mp::ProblemInfo`
170  	  \endrst
171  	 */
172  	struct NLHeader : ProblemInfo {
173  	  /** Input/output format */
174  	  enum Format {
175  	    /**
176  	      Text format. The text format is fully portable meaning that an .nl file
177  	      can be written on a machine of one architecture and then read on a
178  	      machine of a different architecture.
179  	     */
180  	    TEXT = 0,
181  	
182  	    /**
183  	      Binary format. The binary format is not generally portable and should
184  	      normally be used on a single machine.
185  	     */
186  	    BINARY = 1
187  	  };
188  	
189  	  /** Input/output format. */
190  	  Format format;
191  	
192  	  /** The number of options reserved for AMPL use. */
193  	  int num_ampl_options;
194  	
195  	  /**
196  	    Values of options reserved for AMPL use. Leave the default values if not
197  	    using AMPL.
198  	   */
199  	  int ampl_options[MAX_AMPL_OPTIONS];
200  	
201  	  /**
202  	    Extra info for writing a solution reserved for AMPL use. Leave the default
203  	    value if not using AMPL.
204  	   */
205  	  double ampl_vbtol;
206  	
207  	  /**
208  	    \rst
209  	    Floating-point arithmetic kind used with binary format to check
210  	    if an .nl file is written using a compatible representation of
211  	    floating-point numbers. It is not used with the text format and normally
212  	    set to `mp::arith::UNKNOWN` there.
213  	    \endrst
214  	   */
215  	  arith::Kind arith_kind;
216  	
217  	  /** Flags. */
218  	  enum {
219  	    /** Flag that specifies whether to write output suffixes to a .sol file. */
220  	    WANT_OUTPUT_SUFFIXES = 1
221  	  };
222  	
223  	  /**
224  	    \rst
225  	    Flags. Can be either 0 or `mp::NLHeader::WANT_OUTPUT_SUFFIXES`.
226  	    \endrst
227  	   */
228  	  int flags;
229  	
230  	  NLHeader()
231  	    : ProblemInfo(), format(TEXT), num_ampl_options(0), ampl_vbtol(0),
232  	      arith_kind(arith::UNKNOWN), flags(0) {
233  	    std::fill(ampl_options, ampl_options + MAX_AMPL_OPTIONS, 0);
234  	  }
235  	};
236  	
237  	/** Writes NLHeader in the NL format. */
238  	fmt::Writer &operator<<(fmt::Writer &w, const NLHeader &h);
239  	
240  	/**
241  	  \rst
242  	  An NL handler.
243  	
244  	  `~mp::NLHandler` can be used as a base class for other handlers. Subclasses
245  	  only need to redefine methods that handle constructs they are interested
246  	  in and, possibly, the types used by these methods.
247  	
248  	  *Impl* is a type derived from `~mp::NLHandler` that will receive notifications
249  	  of unhandled constructs via `~mp::NLHandler::OnUnhandled`.
250  	
251  	  *ExprType* is a return type of expression handler methods such as
252  	  `~mp::NLHandler::OnUnary` useful for building expression objects. If not used
253  	  it can be any default-constructible type.
254  	  \endrst
255  	 */
256  	template <typename Impl, typename ExprType>
257  	class NLHandler {
258  	 public:
259  	  /** Destroys the object. */
260  	  virtual ~NLHandler() {}
261  	
262  	  /** An expression type. */
263  	  typedef ExprType Expr;
264  	
265  	  /**
266  	    \rst
267  	    .. |Expr| replace:: `Expr <mp::NLHandler::Expr>`
268  	
269  	    A numeric expression type.
270  	    It is a typedef of |Expr| but subclasses may define it as a different type
271  	    convertible to |Expr|.
272  	    \endrst
273  	   */
274  	  typedef Expr NumericExpr;
275  	
276  	  /**
277  	    \rst
278  	    A logical expression type.
279  	    It is a typedef of |Expr| but subclasses may define it as a different type
280  	    convertible to |Expr|.
281  	    \endrst
282  	   */
283  	  typedef Expr LogicalExpr;
284  	
285  	  /**
286  	    \rst
287  	    A count expression type.
288  	    It is a typedef of |Expr| but subclasses may define it as a different type
289  	    convertible to `NumericExpr <mp::NLHandler::NumericExpr>`.
290  	    \endrst
291  	   */
292  	  typedef Expr CountExpr;
293  	
294  	  /**
295  	    \rst
296  	    A reference expression type.
297  	    It is a typedef of |Expr| but subclasses may define it as a different type
298  	    convertible to `NumericExpr <mp::NLHandler::NumericExpr>`.
299  	    \endrst
300  	   */
301  	  typedef Expr Reference;
302  	
303  	  /**
304  	    Receives notification of an unhandled construct of the given kind.
305  	    Throws `UnsupportedError`.
306  	   */
307  	  void OnUnhandled(const char *kind) {
308  	    throw MakeUnsupportedError(kind);
309  	  }
310  	
311  	  /** Receives notification of an NL header. */
312  	  void OnHeader(const NLHeader &h) {
313  	    internal::Unused(&h);
314  	    MP_DISPATCH(OnUnhandled("NL header"));
315  	  }
316  	
317  	  /**
318  	    \rst
319  	    Returns true if the objective with index *obj_index* should be handled.
320  	    \endrst
321  	   */
322  	  bool NeedObj(int obj_index) const {
323  	    internal::Unused(obj_index);
324  	    return true;
325  	  }
326  	
327  	  /**
328  	    \rst
329  	    Returns final objective index
330  	    (e.g., returns 0 if objno>0 and multiobj=0)
331  	    \endrst
332  	   */
333  	  int resulting_obj_index(int obj_index) const { return obj_index; }
334  	
335  	  /**
336  	    Receives notification of an objective type and the nonlinear part of
337  	    an objective expression.
338  	   */
339  	  void OnObj(int index, obj::Type type, NumericExpr expr) {
340  	    internal::Unused(index, type, &expr);
341  	    MP_DISPATCH(OnUnhandled("objective"));
342  	  }
343  	
344  	  /**
345  	    Receives notification of the nonlinear part of an algebraic constraint
346  	    expression.
347  	   */
348  	  void OnAlgebraicCon(int index, NumericExpr expr) {
349  	    internal::Unused(index, &expr);
350  	    MP_DISPATCH(OnUnhandled("nonlinear constraint"));
351  	  }
352  	
353  	  /** Receives notification of a logical constraint expression. */
354  	  void OnLogicalCon(int index, LogicalExpr expr) {
355  	    internal::Unused(index, &expr);
356  	    MP_DISPATCH(OnUnhandled("logical constraint"));
357  	  }
358  	
359  	  /**
360  	    A class (struct) that receives notifications of terms in the linear part
361  	    of a common expression.
362  	   */
363  	  struct LinearExprHandler {
364  	    /** Receives notification of a term in the linear expression. */
365  	    void AddTerm(int var_index, double coef) {
366  	      internal::Unused(var_index, coef);
367  	    }
368  	  };
369  	
370  	  /**
371  	    Receives notification of the beginning of a common expression
372  	    (defined variable).
373  	   */
374  	  LinearExprHandler BeginCommonExpr(int index, int num_linear_terms) {
375  	    internal::Unused(index, num_linear_terms);
376  	    MP_DISPATCH(OnUnhandled("common expression"));
377  	    return LinearExprHandler();
378  	  }
379  	
380  	  /** Receives notification of the end of a common expression. */
381  	  void EndCommonExpr(int index, NumericExpr expr, int position) {
382  	    internal::Unused(index, &expr, position);
383  	    MP_DISPATCH(OnUnhandled("common expression"));
384  	  }
385  	
386  	  /**
387  	    \rst
388  	    Receives notification of a complementarity relation
389  	    ``var_lb <= x <= var_ub complements con_lb <= body <= con_ub``, where ``x``
390  	    is the variable at index *var_index* and ``body`` is the constraint body.
391  	    *info* gives the constraint bounds.
392  	    \endrst
393  	   */
394  	  void OnComplementarity(int con_index, int var_index, ComplInfo info) {
395  	    internal::Unused(con_index, var_index, &info);
396  	    MP_DISPATCH(OnUnhandled("complementarity constraint"));
397  	  }
398  	
399  	  /**
400  	    A typedef of a class that receives notifications of terms in the linear
401  	    part of an objective expression.
402  	   */
403  	  typedef LinearExprHandler LinearObjHandler;
404  	
405  	  /** Receives notification of the linear part of an objective expression. */
406  	  LinearObjHandler OnLinearObjExpr(int obj_index, int num_linear_terms) {
407  	    internal::Unused(obj_index, num_linear_terms);
408  	    MP_DISPATCH(OnUnhandled("linear objective"));
409  	    return LinearObjHandler();
410  	  }
411  	
412  	  /**
413  	    A typedef of a class that receives notifications of terms in the linear
414  	    part of a constraint expression.
415  	   */
416  	  typedef LinearExprHandler LinearConHandler;
417  	
418  	  /** Receives notification of the linear part of a constraint expression. */
419  	  LinearConHandler OnLinearConExpr(int con_index, int num_linear_terms) {
420  	    internal::Unused(con_index, num_linear_terms);
421  	    MP_DISPATCH(OnUnhandled("linear constraint"));
422  	    return LinearConHandler();
423  	  }
424  	
425  	  /** Receives notification of the linear part of a common expression. */
426  	  LinearExprHandler OnLinearCommonExpr(int expr_index, int num_linear_terms) {
427  	    internal::Unused(expr_index, num_linear_terms);
428  	    MP_DISPATCH(OnUnhandled("linear common expression"));
429  	    return LinearExprHandler();
430  	  }
431  	
432  	  /** Receives notification of variable bounds. */
433  	  void OnVarBounds(int index, double lb, double ub) {
434  	    internal::Unused(index, lb, ub);
435  	    MP_DISPATCH(OnUnhandled("variable bounds"));
436  	  }
437  	
438  	  /** Receives notification of constraint bounds (ranges). */
439  	  void OnConBounds(int index, double lb, double ub) {
440  	    internal::Unused(index, lb, ub);
441  	    MP_DISPATCH(OnUnhandled("constraint bounds"));
442  	  }
443  	
444  	  /** Receives notification of the initial value for a variable. */
445  	  void OnInitialValue(int var_index, double value) {
446  	    internal::Unused(var_index, value);
447  	    MP_DISPATCH(OnUnhandled("initial value"));
448  	  }
449  	
450  	  /** Receives notification of the initial value for a dual variable. */
451  	  void OnInitialDualValue(int con_index, double value) {
452  	    internal::Unused(con_index, value);
453  	    MP_DISPATCH(OnUnhandled("initial dual value"));
454  	  }
455  	
456  	  /** A class (struct) that receives notifications of Jacobian column sizes. */
457  	  struct ColumnSizeHandler {
458  	    /** Receives notification of a Jacobian column size. */
459  	    void Add(int size) { internal::Unused(size); }
460  	  };
461  	
462  	  /** Receives notification of Jacobian column sizes. */
463  	  ColumnSizeHandler OnColumnSizes() {
464  	    MP_DISPATCH(OnUnhandled("column sizes"));
465  	    return ColumnSizeHandler();
466  	  }
467  	
468  	  /**
469  	    \rst
470  	    Receives notification of a function.
471  	    The *name* argument is a function name and it is not null-terminated.
472  	    \endrst
473  	   */
474  	  void OnFunction(int index, fmt::StringRef name,
475  	                  int num_args, func::Type type) {
476  	    internal::Unused(index, &name, num_args, type);
477  	    MP_DISPATCH(OnUnhandled("function"));
478  	  }
479  	
480  	  /** A class (struct) that receives notifications of integer suffix values. */
481  	  struct IntSuffixHandler {
482  	    /** Receives notification of a suffix value. */
483  	    void SetValue(int index, int value) { internal::Unused(index, value); }
484  	  };
485  	
486  	  /**
487  	    \rst
488  	    Receives notification of an integer suffix.
489  	    The *name* argument is a suffix name and it is not null-terminated.
490  	    *kind* specifies the suffix kind.
491  	    \endrst
492  	   */
493  	  IntSuffixHandler OnIntSuffix(fmt::StringRef name, suf::Kind kind,
494  	                               int num_values) {
495  	    internal::Unused(&name, kind, num_values);
496  	    MP_DISPATCH(OnUnhandled("integer suffix"));
497  	    return IntSuffixHandler();
498  	  }
499  	
500  	  /** A class (struct) that receives notifications of double suffix values. */
501  	  struct DblSuffixHandler {
502  	    /** Receives notification of a suffix value. */
503  	    void SetValue(int index, double value) { internal::Unused(index, value); }
504  	  };
505  	
506  	  /**
507  	    \rst
508  	    Receives notification of a double suffix.
509  	    The *name* argument is a suffix name and it is not null-terminated.
510  	    *kind* specifies the suffix kind.
511  	    \endrst
512  	   */
513  	  DblSuffixHandler OnDblSuffix(fmt::StringRef name, suf::Kind kind,
514  	                               int num_values) {
515  	    internal::Unused(&name, kind, num_values);
516  	    MP_DISPATCH(OnUnhandled("double suffix"));
517  	    return DblSuffixHandler();
518  	  }
519  	
520  	  /**
521  	    \rst
522  	    A class (struct) that receives notifications of expression arguments.
523  	    All argument handlers in `mp::NLHandler` are typedefs of this class, but
524  	    subclasses of `mp::NLHandler` may define them as different classes.
525  	    \endrst
526  	   */
527  	  struct ArgHandler {
528  	    /** Receives notification of an argument. */
529  	    void AddArg(Expr arg) { internal::Unused(&arg); }
530  	  };
531  	
532  	  /**
533  	    \rst
534  	    A typedef of a class that receives notifications of `numeric
535  	    <mp::expr::FIRST_NUMERIC>` arguments.
536  	    \endrst
537  	   */
538  	  typedef ArgHandler NumericArgHandler;
539  	
540  	  /**
541  	    \rst
542  	    A typedef of a class that receives notifications of `vararg expression
543  	    <mp::expr::FIRST_VARARG>` arguments.
544  	    \endrst
545  	   */
546  	  typedef ArgHandler VarArgHandler;
547  	
548  	  /**
549  	    \rst
550  	    A typedef of a class that receives notifications of `call expression
551  	    <mp::expr::CALL>` arguments.
552  	    \endrst
553  	   */
554  	  typedef ArgHandler CallArgHandler;
555  	
556  	  /**
557  	    \rst
558  	    A typedef of a class that receives notifications of `numberof expression
559  	    <mp::expr::NUMBEROF>` arguments.
560  	    \endrst
561  	   */
562  	  typedef ArgHandler NumberOfArgHandler;
563  	
564  	  /**
565  	    \rst
566  	    A typedef of a class that receives notifications of `count expression
567  	    <mp::expr::COUNT>` arguments.
568  	    \endrst
569  	   */
570  	  typedef ArgHandler CountArgHandler;
571  	
572  	  /**
573  	    \rst
574  	    A typedef of a class that receives notifications of `logical
575  	    <mp::expr::FIRST_LOGICAL>` arguments.
576  	    \endrst
577  	   */
578  	  typedef ArgHandler LogicalArgHandler;
579  	
580  	  /**
581  	    \rst
582  	    A typedef of a class that receives notifications of `pairwise expression
583  	    <mp::expr::FIRST_PAIRWISE>` arguments.
584  	    \endrst
585  	   */
586  	  typedef ArgHandler PairwiseArgHandler;
587  	
588  	  /**
589  	    \rst
590  	    A typedef of a class that receives notifications of symbolic
591  	    (`numeric <mp::expr::FIRST_NUMERIC>` or `string <mp::expr::STRING>`)
592  	    arguments.
593  	    \endrst
594  	   */
595  	  typedef ArgHandler SymbolicArgHandler;
596  	
597  	  /**
598  	    \rst
599  	    Receives notification of a `number <mp::expr::FIRST_NUMERIC>` in a
600  	    nonlinear expression.
601  	    \endrst
602  	   */
603  	  NumericExpr OnNumber(double value) {
604  	    internal::Unused(value);
605  	    MP_DISPATCH(OnUnhandled("number"));
606  	    return NumericExpr();
607  	  }
608  	
609  	  /**
610  	    \rst
611  	    Receives notification of a `variable reference <mp::expr::FIRST_REFERENCE>`.
612  	    \endrst
613  	   */
614  	  Reference OnVariableRef(int var_index) {
615  	    internal::Unused(var_index);
616  	    MP_DISPATCH(OnUnhandled("variable reference"));
617  	    return Reference();
618  	  }
619  	
620  	  /**
621  	    \rst
622  	    Receives notification of a `common expression <mp::expr::COMMON_EXPR>`
623  	    (defined variable) reference.
624  	    \endrst
625  	   */
626  	  Reference OnCommonExprRef(int expr_index) {
627  	    internal::Unused(expr_index);
628  	    MP_DISPATCH(OnUnhandled("common expression reference"));
629  	    return Reference();
630  	  }
631  	
632  	  /**
633  	    \rst
634  	    Receives notification of a `unary expression <mp::expr::FIRST_UNARY>`.
635  	    \endrst
636  	   */
637  	  NumericExpr OnUnary(expr::Kind kind, NumericExpr arg) {
638  	    internal::Unused(kind, &arg);
639  	    MP_DISPATCH(OnUnhandled("unary expression"));
640  	    return NumericExpr();
641  	  }
642  	
643  	  /**
644  	    \rst
645  	    Receives notification of a `binary expression <mp::expr::FIRST_BINARY>`.
646  	    \endrst
647  	   */
648  	  NumericExpr OnBinary(expr::Kind kind, NumericExpr lhs, NumericExpr rhs) {
649  	    internal::Unused(kind, &lhs, &rhs);
650  	    MP_DISPATCH(OnUnhandled("binary expression"));
651  	    return NumericExpr();
652  	  }
653  	
654  	  /**
655  	    \rst
656  	    Receives notification of an `if expression <mp::expr::IF>`.
657  	    \endrst
658  	   */
659  	  NumericExpr OnIf(LogicalExpr condition,
660  	      NumericExpr then_expr, NumericExpr else_expr) {
661  	    internal::Unused(&condition, &then_expr, &else_expr);
662  	    MP_DISPATCH(OnUnhandled("if expression"));
663  	    return NumericExpr();
664  	  }
665  	
666  	  /**
667  	    \rst
668  	    A class (struct) that receives notifications of slopes and breakpoints in a
669  	    `piecewise-linear term <mp::expr::PLTERM>`.
670  	    \endrst
671  	   */
672  	  struct PLTermHandler {
673  	    /** Receives notification of a slope. */
674  	    void AddSlope(double slope) { internal::Unused(slope); }
675  	
676  	    /** Receives notification of a breakpoint. */
677  	    void AddBreakpoint(double breakpoint) { internal::Unused(breakpoint); }
678  	  };
679  	
680  	  /**
681  	    \rst
682  	    Receives notification of the beginning of a `piecewise-linear term
683  	    <mp::expr::PLTERM>`.
684  	    \endrst
685  	   */
686  	  PLTermHandler BeginPLTerm(int num_breakpoints) {
687  	    internal::Unused(num_breakpoints);
688  	    MP_DISPATCH(OnUnhandled("piecewise-linear term"));
689  	    return PLTermHandler();
690  	  }
691  	
692  	  /**
693  	    \rst
694  	    Receives notification of the end of a `piecewise-linear term
695  	    <mp::expr::PLTERM>`.
696  	
697  	    *arg*: argument that is a variable or a common expression reference.
698  	    \endrst
699  	   */
700  	  NumericExpr EndPLTerm(PLTermHandler handler, Reference arg) {
701  	    internal::Unused(&handler, &arg);
702  	    MP_DISPATCH(OnUnhandled("piecewise-linear term"));
703  	    return NumericExpr();
704  	  }
705  	
706  	  /**
707  	    \rst
708  	    Receives notification of the beginning of a `call expression
709  	    <mp::expr::CALL>`.
710  	    \endrst
711  	   */
712  	  CallArgHandler BeginCall(int func_index, int num_args) {
713  	    internal::Unused(func_index, num_args);
714  	    MP_DISPATCH(OnUnhandled("call expression"));
715  	    return CallArgHandler();
716  	  }
717  	
718  	  /**
719  	    \rst
720  	    Receives notification of the end of a `call expression <mp::expr::CALL>`.
721  	    \endrst
722  	   */
723  	  NumericExpr EndCall(CallArgHandler handler) {
724  	    internal::Unused(handler);
725  	    MP_DISPATCH(OnUnhandled("call expression"));
726  	    return NumericExpr();
727  	  }
728  	
729  	  /**
730  	    \rst
731  	    Receives notification of the beginning of a `vararg expression
732  	    <mp::expr::FIRST_VARARG>`.
733  	    \endrst
734  	   */
735  	  VarArgHandler BeginVarArg(expr::Kind kind, int num_args) {
736  	    internal::Unused(kind, num_args);
737  	    MP_DISPATCH(OnUnhandled("vararg expression"));
738  	    return NumericArgHandler();
739  	  }
740  	
741  	  /**
742  	    \rst
743  	    Receives notification of the end of a `vararg expression
744  	    <mp::expr::FIRST_VARARG>`.
745  	    \endrst
746  	   */
747  	  NumericExpr EndVarArg(VarArgHandler handler) {
748  	    internal::Unused(handler);
749  	    MP_DISPATCH(OnUnhandled("vararg expression"));
750  	    return NumericExpr();
751  	  }
752  	
753  	  /**
754  	    \rst
755  	    Receives notification of the beginning of a `summation <mp::expr::SUM>`.
756  	    \endrst
757  	   */
758  	  NumericArgHandler BeginSum(int num_args) {
759  	    internal::Unused(num_args);
760  	    MP_DISPATCH(OnUnhandled("summation"));
761  	    return NumericArgHandler();
762  	  }
763  	
764  	  /**
765  	    \rst
766  	    Receives notification of the end of a `summation <mp::expr::SUM>`.
767  	    \endrst
768  	   */
769  	  NumericExpr EndSum(NumericArgHandler handler) {
770  	    internal::Unused(handler);
771  	    MP_DISPATCH(OnUnhandled("summation"));
772  	    return NumericExpr();
773  	  }
774  	
775  	  /**
776  	    \rst
777  	    Receives notification of the beginning of a `count expression
778  	    <mp::expr::COUNT>`.
779  	    \endrst
780  	   */
781  	  CountArgHandler BeginCount(int num_args) {
782  	    internal::Unused(num_args);
783  	    MP_DISPATCH(OnUnhandled("count expression"));
784  	    return CountArgHandler();
785  	  }
786  	
787  	  /**
788  	    \rst
789  	    Receives notification of the end of a `count expression <mp::expr::COUNT>`.
790  	    \endrst
791  	   */
792  	  CountExpr EndCount(CountArgHandler handler) {
793  	    internal::Unused(handler);
794  	    MP_DISPATCH(OnUnhandled("count expression"));
795  	    return NumericExpr();
796  	  }
797  	
798  	  /**
799  	    \rst
800  	    Receives notification of the beginning of a `numberof expression
801  	    <mp::expr::NUMBEROF>`.
802  	    \endrst
803  	   */
804  	  NumberOfArgHandler BeginNumberOf(int num_args, NumericExpr arg0) {
805  	    internal::Unused(num_args, &arg0);
806  	    MP_DISPATCH(OnUnhandled("numberof expression"));
807  	    return NumberOfArgHandler();
808  	  }
809  	
810  	  /**
811  	    \rst
812  	    Receives notification of the end of a `numberof expression
813  	    <mp::expr::NUMBEROF>`.
814  	    \endrst
815  	   */
816  	  NumericExpr EndNumberOf(NumberOfArgHandler handler) {
817  	    internal::Unused(handler);
818  	    MP_DISPATCH(OnUnhandled("numberof expression"));
819  	    return NumericExpr();
820  	  }
821  	
822  	  /**
823  	    \rst
824  	    Receives notification of the beginning of a `symbolic numberof
825  	    expression <mp::expr::NUMBEROF_SYM>`.
826  	    \endrst
827  	   */
828  	  SymbolicArgHandler BeginSymbolicNumberOf(int num_args, Expr arg0) {
829  	    internal::Unused(num_args, &arg0);
830  	    MP_DISPATCH(OnUnhandled("symbolic numberof expression"));
831  	    return SymbolicArgHandler();
832  	  }
833  	
834  	  /**
835  	    \rst
836  	    Receives notification of the end of a `symbolic numberof expression
837  	    <mp::expr::NUMBEROF_SYM>`.
838  	    \endrst
839  	   */
840  	  NumericExpr EndSymbolicNumberOf(SymbolicArgHandler handler) {
841  	    internal::Unused(handler);
842  	    MP_DISPATCH(OnUnhandled("symbolic numberof expression"));
843  	    return NumericExpr();
844  	  }
845  	
846  	  /**
847  	    \rst
848  	    Receives notification of a `Boolean value <mp::expr::BOOL>`.
849  	    \endrst
850  	   */
851  	  LogicalExpr OnBool(bool value) {
852  	    internal::Unused(value);
853  	    MP_DISPATCH(OnUnhandled("bool"));
854  	    return LogicalExpr();
855  	  }
856  	
857  	  /**
858  	    \rst
859  	    Receives notification of a `logical not <mp::expr::NOT>`.
860  	    \endrst
861  	   */
862  	  LogicalExpr OnNot(LogicalExpr arg) {
863  	    internal::Unused(&arg);
864  	    MP_DISPATCH(OnUnhandled("logical not"));
865  	    return LogicalExpr();
866  	  }
867  	
868  	  /**
869  	    \rst
870  	    Receives notification of a `binary logical expression
871  	    <mp::expr::FIRST_BINARY_LOGICAL>`.
872  	    \endrst
873  	   */
874  	  LogicalExpr OnBinaryLogical(
875  	      expr::Kind kind, LogicalExpr lhs, LogicalExpr rhs) {
876  	    internal::Unused(kind, &lhs, &rhs);
877  	    MP_DISPATCH(OnUnhandled("binary logical expression"));
878  	    return LogicalExpr();
879  	  }
880  	
881  	  /**
882  	    \rst
883  	    Receives notification of a `relational expression
884  	    <mp::expr::FIRST_RELATIONAL>`.
885  	    \endrst
886  	   */
887  	  LogicalExpr OnRelational(expr::Kind kind, NumericExpr lhs, NumericExpr rhs) {
888  	    internal::Unused(kind, &lhs, &rhs);
889  	    MP_DISPATCH(OnUnhandled("relational expression"));
890  	    return LogicalExpr();
891  	  }
892  	
893  	  /**
894  	    \rst
895  	    Receives notification of a `logical count expression
896  	    <mp::expr::FIRST_LOGICAL_COUNT>`.
897  	    \endrst
898  	   */
899  	  LogicalExpr OnLogicalCount(expr::Kind kind, NumericExpr lhs, CountExpr rhs) {
900  	    internal::Unused(kind, &lhs, &rhs);
901  	    MP_DISPATCH(OnUnhandled("logical count expression"));
902  	    return LogicalExpr();
903  	  }
904  	
905  	  /**
906  	    \rst
907  	    Receives notification of an `implication expression
908  	    <mp::expr::IMPLICATION>`.
909  	    \endrst
910  	   */
911  	  LogicalExpr OnImplication(
912  	      LogicalExpr condition, LogicalExpr then_expr, LogicalExpr else_expr) {
913  	    internal::Unused(&condition, &then_expr, &else_expr);
914  	    MP_DISPATCH(OnUnhandled("implication expression"));
915  	    return LogicalExpr();
916  	  }
917  	
918  	  /**
919  	    \rst
920  	    Receives notification of the beginning of an `iterated logical
921  	    expression <mp::expr::FIRST_ITERATED_LOGICAL>`.
922  	    \endrst
923  	   */
924  	  LogicalArgHandler BeginIteratedLogical(expr::Kind kind, int num_args) {
925  	    internal::Unused(kind, num_args);
926  	    MP_DISPATCH(OnUnhandled("iterated logical expression"));
927  	    return LogicalArgHandler();
928  	  }
929  	
930  	  /**
931  	    \rst
932  	    Receives notification of the end of an `iterated logical expression
933  	    <mp::expr::FIRST_ITERATED_LOGICAL>`.
934  	    \endrst
935  	   */
936  	  LogicalExpr EndIteratedLogical(LogicalArgHandler handler) {
937  	    internal::Unused(handler);
938  	    MP_DISPATCH(OnUnhandled("iterated logical expression"));
939  	    return LogicalExpr();
940  	  }
941  	
942  	  /**
943  	    \rst
944  	    Receives notification of the beginning of a `pairwise expression
945  	    <mp::expr::FIRST_PAIRWISE>`.
946  	    \endrst
947  	   */
948  	  PairwiseArgHandler BeginPairwise(expr::Kind kind, int num_args) {
949  	    internal::Unused(kind, num_args);
950  	    MP_DISPATCH(OnUnhandled("pairwise expression"));
951  	    return PairwiseArgHandler();
952  	  }
953  	
954  	  /**
955  	    \rst
956  	    Receives notification of the end of a `pairwise expression
957  	    <mp::expr::FIRST_PAIRWISE>`.
958  	    \endrst
959  	   */
960  	  LogicalExpr EndPairwise(PairwiseArgHandler handler) {
961  	    internal::Unused(handler);
962  	    MP_DISPATCH(OnUnhandled("pairwise expression"));
963  	    return LogicalExpr();
964  	  }
965  	
966  	  /**
967  	    \rst
968  	    Receives notification of a `string <mp::expr::STRING>`.
969  	    The *value* argument is a string value and it is not null-terminated.
970  	    \endrst
971  	   */
972  	  Expr OnString(fmt::StringRef value) {
973  	    internal::Unused(&value);
974  	    MP_DISPATCH(OnUnhandled("string"));
975  	    return Expr();
976  	  }
977  	
978  	  /**
979  	    \rst
980  	    Receives notification of a `symbolic if expression <mp::expr::IFSYM>`.
981  	    \endrst
982  	   */
983  	  Expr OnSymbolicIf(LogicalExpr condition, Expr then_expr, Expr else_expr) {
984  	    internal::Unused(&condition, &then_expr, &else_expr);
985  	    MP_DISPATCH(OnUnhandled("symbolic if expression"));
986  	    return Expr();
987  	  }
988  	
989  	  /** Receives notification of the end of the input. */
990  	  void EndInput() {}
991  	};
992  	
993  	/**
994  	  \rst
995  	  An NL handler that ignores all input.
996  	
997  	  `~mp::NullNLHandler` can be used as a base class when only a subset of
998  	  constructs needs to be handled. Unhandled constructs will be ignored, not
999  	  reported.
1000 	
1001 	  *ExprType* is a return type of expression handler methods such as
1002 	  `~mp::NLHandler::OnUnary` useful for building expression objects. If not used
1003 	  it can be any default-constructible type.
1004 	  \endrst
1005 	 */
1006 	template <typename ExprType>
1007 	class NullNLHandler : public NLHandler<NullNLHandler<ExprType>, ExprType> {
1008 	 public:
1009 	  /** Receives notification of an unhandled construct and ignores it. */
1010 	  void OnUnhandled(const char *) {}
1011 	};
1012 	
1013 	namespace internal {
1014 	
1015 	class ReaderBase {
1016 	 protected:
1017 	  const char *ptr_, *start_, *end_;
1018 	  const char *token_;  // start of the current token
1019 	  std::string name_;
1020 	
1021 	  ~ReaderBase() {}
1022 	
1023 	 public:
1024 	  ReaderBase(NLStringRef data, fmt::CStringRef name);
1025 	
1026 	  char ReadChar() {
1027 	    token_ = ptr_;
1028 	    return *ptr_++;
1029 	  }
1030 	
(1) Event side_effect_free_fn: This function only appears useful for its return value.
1031 	  const char *ptr() const { return ptr_; }
1032 	  void set_ptr(const char *ptr) { token_ = ptr_ = ptr; }
1033 	
1034 	  bool IsEOF(const char *ptr) const { return ptr == end_ + 1; }
1035 	  bool IsEOF() const { return IsEOF(ptr_); }
1036 	};
1037 	
1038 	#ifdef FMT_LOCALE
1039 	typedef fmt::Locale Locale;
1040 	#else
1041 	# warning "Parsing is locale-dependent"
1042 	struct Locale {
1043 	  double strtod(const char *&str) const {
1044 	    char *end = 0;
1045 	    double result = std::strtod(str, &end);
1046 	    str = end;
1047 	    return result;
1048 	  }
1049 	};
1050 	#endif
1051 	
1052 	template <typename Locale = Locale>
1053 	class TextReader : public ReaderBase {
1054 	 private:
1055 	  const char *line_start_;
1056 	  int line_;
1057 	
1058 	  class CopyableLocale : public Locale {
1059 	   public:
1060 	    CopyableLocale() {}
1061 	    // All Locale objects refer to the "C" locale, so no need to copy.
1062 	    CopyableLocale(const CopyableLocale &) : Locale() {}
1063 	    CopyableLocale &operator=(const CopyableLocale &) { return *this; }
1064 	  };
1065 	  CopyableLocale locale_;
1066 	
1067 	  // Reads an integer without a sign.
1068 	  // Int: signed or unsigned integer type.
1069 	  template <typename Int>
1070 	  bool ReadIntWithoutSign(Int& value) {
1071 	    char c = *ptr_;
1072 	    if (c < '0' || c > '9')
1073 	      return false;
1074 	    typedef typename MakeUnsigned<Int>::Type UInt;
1075 	    UInt result = 0;
1076 	    do {
1077 	      UInt new_result = result * 10 + (c - '0');
1078 	      if (new_result < result)
1079 	        ReportError("number is too big");
1080 	      result = new_result;
1081 	      c = *++ptr_;
1082 	    } while (c >= '0' && c <= '9');
1083 	    UInt max = std::numeric_limits<Int>::max();
1084 	    if (result > max)
1085 	      ReportError("number is too big");
1086 	    value = result;
1087 	    return true;
1088 	  }
1089 	
1090 	  template <typename Int>
1091 	  bool DoReadOptionalInt(Int &value) {
1092 	    SkipSpace();
1093 	    char sign = *ptr_;
1094 	    if (sign == '+' || sign == '-')
1095 	      ++ptr_;
1096 	    typedef typename MakeUnsigned<Int>::Type UInt;
1097 	    UInt result = 0;
1098 	    if (!ReadIntWithoutSign<UInt>(result))
1099 	      return false;
1100 	    UInt max = std::numeric_limits<Int>::max();
1101 	    if (result > max && !(sign == '-' && result == max + 1))
1102 	      ReportError("number is too big");
1103 	    value = sign != '-' ? result : 0 - result;
1104 	    return true;
1105 	  }
1106 	
1107 	  // Reads a nonnegative integer and checks that adding it to accumulator
1108 	  // doesn't overflow.
1109 	  int ReadUInt(int &accumulator) {
1110 	    int value = ReadUInt();
1111 	    if (accumulator > std::numeric_limits<int>::max() - value)
1112 	      ReportError("integer overflow");
1113 	    accumulator += value;
1114 	    return value;
1115 	  }
1116 	
1117 	  template <typename Int>
1118 	  Int ReadUInt() {
1119 	    SkipSpace();
1120 	    Int value = 0;
1121 	    if (!ReadIntWithoutSign(value))
1122 	      ReportError("expected unsigned integer");
1123 	    return value;
1124 	  }
1125 	
1126 	  bool ReadOptionalInt(int &value) { return DoReadOptionalInt(value); }
1127 	
1128 	  bool ReadOptionalUInt(int &value) {
1129 	    SkipSpace();
1130 	    return ReadIntWithoutSign(value);
1131 	  }
1132 	
1133 	  bool ReadOptionalDouble(double &value);
1134 	
1135 	  void DoReportError(
1136 	      const char *loc, fmt::CStringRef format_str,
1137 	      const fmt::ArgList &args = fmt::ArgList());
1138 	
1139 	  void SkipSpace() {
1140 	    while (std::isspace(*ptr_) && *ptr_ != '\n')
1141 	      ++ptr_;
1142 	    token_ = ptr_;
1143 	  }
1144 	
1145 	 public:
1146 	  TextReader(NLStringRef data, fmt::CStringRef name);
1147 	
1148 	  Locale &locale() { return locale_; }
1149 	
1150 	  void ReportError(fmt::CStringRef format_str, const fmt::ArgList &args) {
1151 	    DoReportError(token_, format_str, args);
1152 	  }
1153 	  FMT_VARIADIC(void, ReportError, fmt::CStringRef)
1154 	
1155 	  void ReadTillEndOfLine() {
1156 	    while (char c = *ptr_) {
1157 	      ++ptr_;
1158 	      if (c == '\n') {
1159 	        line_start_ = ptr_;
1160 	        ++line_;
1161 	        return;
1162 	      }
1163 	    }
1164 	    DoReportError(ptr_, "expected newline");
1165 	  }
1166 	
1167 	  template <typename Int>
1168 	  Int ReadInt() {
1169 	    Int value = 0;
1170 	    if (!DoReadOptionalInt(value))
1171 	      ReportError("expected integer");
1172 	    return value;
1173 	  }
1174 	
1175 	  int ReadUInt() { return ReadUInt<int>(); }
1176 	
1177 	  double ReadDouble() {
1178 	    SkipSpace();
1179 	    const char *start = ptr_;
1180 	    double value = 0;
1181 	    if (*ptr_ != '\n')
1182 	      value = locale_.strtod(ptr_);
1183 	    if (ptr_ == start)
1184 	      ReportError("expected double");
1185 	    return value;
1186 	  }
1187 	
1188 	  fmt::StringRef ReadString();
1189 	
1190 	  // Reads a function or suffix name.
1191 	  fmt::StringRef ReadName();
1192 	
1193 	  // Reads an .nl file header. The header is always in text format, so this
1194 	  // function doesn't have a counterpart in BinaryReader.
1195 	  void ReadHeader(NLHeader &header);
1196 	};
1197 	
1198 	// Converter that doesn't change the input.
1199 	class IdentityConverter {
1200 	 public:
1201 	  template <typename T>
1202 	  T Convert(T value) { return value; }
1203 	};
1204 	
1205 	// Converter that changes the input endianness.
1206 	class EndiannessConverter {
1207 	 private:
1208 	  void Convert(char *data, std::size_t size) {
1209 	    std::reverse(data, data + size);
1210 	  }
1211 	
1212 	 public:
1213 	  template <typename T>
1214 	  T Convert(T value) {
1215 	    Convert(reinterpret_cast<char*>(&value), sizeof(T));
1216 	    return value;
1217 	  }
1218 	};
1219 	
1220 	class BinaryReaderBase : public ReaderBase {
1221 	 protected:
1222 	  explicit BinaryReaderBase(const ReaderBase &base) : ReaderBase(base) {}
1223 	
1224 	  // Reads length chars.
1225 	  const char *Read(int length) {
1226 	    if (end_ - ptr_ < length) {
1227 	      token_ = end_;
1228 	      ReportError("unexpected end of file");
1229 	    }
1230 	    const char *start = ptr_;
1231 	    ptr_ += length;
1232 	    return start;
1233 	  }
1234 	
1235 	 public:
1236 	  void ReportError(fmt::CStringRef format_str, const fmt::ArgList &args);
1237 	  FMT_VARIADIC(void, ReportError, fmt::CStringRef)
1238 	
1239 	  void ReadTillEndOfLine() {
1240 	    // Do nothing.
1241 	  }
1242 	};
1243 	
1244 	// Binary reader.
1245 	template <typename InputConverter = IdentityConverter>
1246 	class BinaryReader : private InputConverter, public BinaryReaderBase {
1247 	 public:
1248 	  explicit BinaryReader(const ReaderBase &base) : BinaryReaderBase(base) {}
1249 	
1250 	  template <typename Int>
1251 	  Int ReadInt() {
1252 	    token_ = ptr_;
1253 	    Int val;
1254 	    memcpy(&val, Read(sizeof(Int)), sizeof(Int));
1255 	    return this->Convert(val);
1256 	  }
1257 	
1258 	  int ReadUInt() {
1259 	    int value = ReadInt<int>();
1260 	    if (value < 0)
1261 	      ReportError("expected unsigned integer");
1262 	    return value;
1263 	  }
1264 	
1265 	  double ReadDouble() {
1266 	    token_ = ptr_;
1267 	    double val;
1268 	    memcpy(&val, Read(sizeof(double)), sizeof(double));
1269 	    return this->Convert(val);
1270 	  }
1271 	
1272 	  fmt::StringRef ReadString() {
1273 	    int length = ReadUInt();
1274 	    return fmt::StringRef(length != 0 ? Read(length) : 0, length);
1275 	  }
1276 	
1277 	  // Reads a function or suffix name.
1278 	  fmt::StringRef ReadName() { return ReadString(); }
1279 	};
1280 	
1281 	// An NLHandler that forwards notification of variable bounds to another
1282 	// handler and ignores all other notifications.
1283 	template <typename Handler>
1284 	class VarBoundHandler : public NullNLHandler<typename Handler::Expr> {
1285 	 private:
1286 	  Handler &handler_;
1287 	
1288 	 public:
1289 	  explicit VarBoundHandler(Handler &h) : handler_(h) {}
1290 	
1291 	  void OnVarBounds(int index, double lb, double ub) {
1292 	    handler_.OnVarBounds(index, lb, ub);
1293 	  }
1294 	};
1295 	
1296 	// Linear expression handler that ignores input.
1297 	struct NullLinearExprHandler {
1298 	  void AddTerm(int, double) {}
1299 	};
1300 	
1301 	// An NL reader.
1302 	// Handler: a class implementing the NLHandler concept that receives
1303 	//          notifications of NL constructs
1304 	template <typename Reader, typename Handler>
1305 	class NLReader {
1306 	 private:
1307 	  Reader &reader_;
1308 	  const NLHeader &header_;
1309 	  Handler &handler_;
1310 	  int flags_;
1311 	  int num_vars_and_exprs_;  // Number of variables and common expressions.
1312 	
1313 	  typedef typename Handler::Expr Expr;
1314 	  typedef typename Handler::NumericExpr NumericExpr;
1315 	  typedef typename Handler::LogicalExpr LogicalExpr;
1316 	  typedef typename Handler::Reference Reference;
1317 	
1318 	  double ReadConstant(char code);
1319 	  double ReadConstant() { return ReadConstant(reader_.ReadChar()); }
1320 	
1321 	  // Reads a nonnegative integer and checks that it is less than ub.
1322 	  // ub is unsigned so that it can hold value INT_MAX + 1u.
1323 	  int ReadUInt(unsigned ub) {
1324 	    int value = reader_.ReadUInt();
1325 	    unsigned unsigned_value = value;
1326 	    if (unsigned_value >= ub)
1327 	      reader_.ReportError("integer {} out of bounds", value);
1328 	    return value;
1329 	  }
1330 	
1331 	  // Reads a nonnegative integer and checks that it is in the range [lb, ub).
1332 	  int ReadUInt(unsigned lb, unsigned ub) {
1333 	    int value = reader_.ReadUInt();
1334 	    unsigned unsigned_value = value;
1335 	    if (unsigned_value < lb || unsigned_value >= ub)
1336 	      reader_.ReportError("integer {} out of bounds", value);
1337 	    return value;
1338 	  }
1339 	
1340 	  // Minimum number of arguments for an iterated expression that has a
1341 	  // binary counterpart. Examples: sum (+), forall (&&), exists (||).
1342 	  enum {MIN_ITER_ARGS = 3};
1343 	
1344 	  int ReadNumArgs(int min_args = MIN_ITER_ARGS) {
1345 	    int num_args = reader_.ReadUInt();
1346 	    if (num_args < min_args)
1347 	      reader_.ReportError("too few arguments");
1348 	    return num_args;
1349 	  }
1350 	
1351 	  // Reads a variable or a common expression reference.
1352 	  Reference DoReadReference() {
1353 	    int index = ReadUInt(num_vars_and_exprs_);
1354 	    reader_.ReadTillEndOfLine();
1355 	    return index < header_.num_vars ?
1356 	          handler_.OnVariableRef(index) :
1357 	          handler_.OnCommonExprRef(index - header_.num_vars);
1358 	  }
1359 	
1360 	  // Reads a variable or a common expression reference.
1361 	  Reference ReadReference() {
1362 	    if (reader_.ReadChar() != 'v')
1363 	      reader_.ReportError("expected reference");
1364 	    return DoReadReference();
1365 	  }
1366 	
1367 	  template <typename ExprReader, typename ArgHandler>
1368 	  void DoReadArgs(int num_args, ArgHandler &arg_handler) {
1369 	    ExprReader expr_reader;
1370 	    for (int i = 0; i < num_args; ++i)
1371 	      arg_handler.AddArg(expr_reader.Read(*this));
1372 	  }
1373 	
1374 	  template <typename ExprReader, typename ArgHandler>
1375 	  void ReadArgs(int num_args, ArgHandler &arg_handler) {
1376 	    reader_.ReadTillEndOfLine();
1377 	    DoReadArgs<ExprReader>(num_args, arg_handler);
1378 	  }
1379 	
1380 	  int ReadOpCode() {
1381 	    int opcode = reader_.ReadUInt();
1382 	    if (opcode > internal::MAX_OPCODE)
1383 	      reader_.ReportError("invalid opcode {}", opcode);
1384 	    reader_.ReadTillEndOfLine();
1385 	    return opcode;
1386 	  }
1387 	
1388 	  typename Handler::CountExpr ReadCountExpr() {
1389 	    int num_args = ReadNumArgs(1);
1390 	    typename Handler::CountArgHandler args = handler_.BeginCount(num_args);
1391 	    ReadArgs<LogicalExprReader>(num_args, args);
1392 	    return handler_.EndCount(args);
1393 	  }
1394 	
1395 	  // Helper structs to provide a uniform interface to Read{Numeric,Logical}Expr
1396 	  // since it is not possible to overload on expression type as NumericExpr
1397 	  // and LogicalExpr can be the same type.
1398 	  struct NumericExprReader {
1399 	    typedef NumericExpr Expr;
1400 	    Expr Read(NLReader &r) const { return r.ReadNumericExpr(); }
1401 	  };
1402 	  struct LogicalExprReader {
1403 	    typedef LogicalExpr Expr;
1404 	    Expr Read(NLReader &r) const { return r.ReadLogicalExpr(); }
1405 	  };
1406 	  struct SymbolicExprReader {
1407 	    typedef typename Handler::Expr Expr;
1408 	    Expr Read(NLReader &r) const { return r.ReadSymbolicExpr(); }
1409 	  };
1410 	
1411 	  // A helper struct used to make sure that the arguments to a binary
1412 	  // expression are read in the correct order and avoid errors of the form:
1413 	  //   MakeBinary(opcode, ReadNumericExpr(), ReadNumericExpr())
1414 	  // The above code is incorrect as the order of evaluation of arguments is
1415 	  // unspecified.
1416 	  template <typename ExprReader = NumericExprReader>
1417 	  struct BinaryArgReader {
1418 	    typename ExprReader::Expr lhs;
1419 	    typename ExprReader::Expr rhs;
1420 	    BinaryArgReader(NLReader &r)
1421 	      : lhs(ExprReader().Read(r)), rhs(ExprReader().Read(r)) {}
1422 	  };
1423 	
1424 	  // Reads a numeric or string expression.
1425 	  Expr ReadSymbolicExpr();
1426 	
1427 	  // Reads a numeric expression.
1428 	  // ignore_zero: if true, zero constants are ignored
1429 	  NumericExpr ReadNumericExpr(bool ignore_zero = false) {
1430 	    return ReadNumericExpr(reader_.ReadChar(), ignore_zero);
1431 	  }
1432 	  NumericExpr ReadNumericExpr(char code, bool ignore_zero);
1433 	  NumericExpr ReadNumericExpr(int opcode);
1434 	
1435 	  // Reads a logical expression.
1436 	  LogicalExpr ReadLogicalExpr();
1437 	  LogicalExpr ReadLogicalExpr(int opcode);
1438 	
1439 	  enum ItemType { VAR, OBJ, CON, PROB };
1440 	
1441 	  template <ItemType T>
1442 	  class ItemHandler {
1443 	   protected:
1444 	    NLReader &reader_;
1445 	
1446 	   public:
1447 	    static const ItemType TYPE = T;
1448 	    explicit ItemHandler(NLReader &r) : reader_(r) {}
1449 	  };
1450 	
1451 	  struct VarHandler : ItemHandler<VAR> {
1452 	    explicit VarHandler(NLReader &r) : ItemHandler<VAR>(r) {}
1453 	
1454 	    int num_items() const { return this->reader_.header_.num_vars; }
1455 	
1456 	    void SetBounds(int index, double lb, double ub) {
1457 	      this->reader_.handler_.OnVarBounds(index, lb, ub);
1458 	    }
1459 	    void SetInitialValue(int index, double value) {
1460 	      this->reader_.handler_.OnInitialValue(index, value);
1461 	    }
1462 	  };
1463 	
1464 	  struct ObjHandler : ItemHandler<OBJ> {
1465 	    explicit ObjHandler(NLReader &r) : ItemHandler<OBJ>(r) {}
1466 	
1467 	    int num_items() const { return this->reader_.header_.num_objs; }
1468 	
1469 	    // Returns true if objective expression should be skipped.
1470 	    bool SkipExpr(int obj_index) const {
1471 	      return !this->reader_.handler_.NeedObj(obj_index);
1472 	    }
1473 	
1474 	    typename Handler::LinearObjHandler OnLinearExpr(int index, int num_terms) {
1475 	      auto& h = this->reader_.handler_;
1476 	      return h.OnLinearObjExpr( h.resulting_obj_index(index), num_terms);
1477 	    }
1478 	  };
1479 	
1480 	  struct ConHandler : ItemHandler<CON> {
1481 	    explicit ConHandler(NLReader &r) : ItemHandler<CON>(r) {}
1482 	
1483 	    int num_items() const {
1484 	      return this->reader_.header_.num_algebraic_cons +
1485 	          this->reader_.header_.num_logical_cons;
1486 	    }
1487 	  };
1488 	
1489 	  struct ProblemHandler : ItemHandler<PROB> {
1490 	    explicit ProblemHandler(NLReader &r) : ItemHandler<PROB>(r) {}
1491 	
1492 	    // An NL input always contains one problem.
1493 	    int num_items() const { return 1; }
1494 	  };
1495 	
1496 	  // Reads the linear part of an objective or constraint expression.
1497 	  template <typename LinearHandler>
1498 	  void ReadLinearExpr();
1499 	
1500 	  template <typename LinearHandler>
1501 	  void ReadLinearExpr(int num_terms, LinearHandler linear_expr);
1502 	
1503 	  // Reads column sizes, numbers of nonzeros in the first num_var − 1
1504 	  // columns of the Jacobian sparsity matrix.
1505 	  template <bool CUMULATIVE>
1506 	  void ReadColumnSizes();
1507 	
1508 	  // Reads initial values for primal or dual variables.
1509 	  template <typename ValueHandler>
1510 	  void ReadInitialValues();
1511 	
1512 	  struct IntReader {
1513 	    int operator()(Reader &r) const { return r.template ReadInt<int>(); }
1514 	  };
1515 	
1516 	  struct DoubleReader {
1517 	    double operator()(Reader &r) const { return r.ReadDouble(); }
1518 	  };
1519 	
1520 	  template <typename ValueReader, typename SuffixHandler>
1521 	  void ReadSuffixValues(int num_values, int num_items, SuffixHandler &handler) {
1522 	    ValueReader read;
1523 	    for (int i = 0; i < num_values; ++i) {
1524 	      int index = ReadUInt(num_items);
1525 	      handler.SetValue(index, read(reader_));
1526 	      reader_.ReadTillEndOfLine();
1527 	    }
1528 	  }
1529 	
1530 	  template <typename ItemInfo>
1531 	  void ReadSuffix(int info);
1532 	
1533 	 public:
1534 	  NLReader(Reader &reader, const NLHeader &header, Handler &handler, int flags)
1535 	    : reader_(reader), header_(header), handler_(handler), flags_(flags),
1536 	      num_vars_and_exprs_(0) {}
1537 	
1538 	  // Algebraic constraint handler.
1539 	  struct AlgebraicConHandler : ItemHandler<CON> {
1540 	    explicit AlgebraicConHandler(NLReader &r) : ItemHandler<CON>(r) {}
1541 	
1542 	    int num_items() const { return this->reader_.header_.num_algebraic_cons; }
1543 	
1544 	    // Returns false because constraint expressions are always read.
1545 	    bool SkipExpr(int) const { return false; }
1546 	
1547 	    typename Handler::LinearConHandler OnLinearExpr(int index, int num_terms) {
1548 	      return this->reader_.handler_.OnLinearConExpr(index, num_terms);
1549 	    }
1550 	
1551 	    void SetBounds(int index, double lb, double ub) {
1552 	      this->reader_.handler_.OnConBounds(index, lb, ub);
1553 	    }
1554 	    void SetInitialValue(int index, double value) {
1555 	      this->reader_.handler_.OnInitialDualValue(index, value);
1556 	    }
1557 	  };
1558 	
1559 	  // Reads variable or constraint bounds.
1560 	  template <typename BoundHandler>
1561 	  void ReadBounds();
1562 	
1563 	  // bound_reader: a reader after variable bounds section input
1564 	  void Read(Reader *bound_reader);
1565 	
1566 	  void Read();
1567 	};
1568 	
1569 	template <typename Reader, typename Handler>
1570 	double NLReader<Reader, Handler>::ReadConstant(char code) {
1571 	  double value = 0;
1572 	  switch (code) {
1573 	  case 'n':
1574 	    value = reader_.ReadDouble();
1575 	    break;
1576 	  case 's':
1577 	    value = reader_.template ReadInt<short>();
1578 	    break;
1579 	  case 'l':
1580 	    // The following check is necessary for compatibility with ASL.
1581 	    if (sizeof(double) == 2 * sizeof(int))
1582 	      value = reader_.template ReadInt<int>();
1583 	    else
1584 	      value = reader_.template ReadInt<long>();
1585 	    break;
1586 	  default:
1587 	    reader_.ReportError("expected constant");
1588 	  }
1589 	  reader_.ReadTillEndOfLine();
1590 	  return value;
1591 	}
1592 	
1593 	template <typename Reader, typename Handler>
1594 	typename Handler::Expr NLReader<Reader, Handler>::ReadSymbolicExpr() {
1595 	  char c = reader_.ReadChar();
1596 	  switch (c) {
1597 	  case 'h':
1598 	    return handler_.OnString(reader_.ReadString());
1599 	  case 'o': {
1600 	    int opcode = ReadOpCode();
1601 	    if (opcode != expr::nl_opcode(expr::IFSYM))
1602 	      return ReadNumericExpr(opcode);
1603 	    // Read symbolic if expression.
1604 	    LogicalExpr condition = ReadLogicalExpr();
1605 	    Expr then_expr = ReadSymbolicExpr();
1606 	    Expr else_expr = ReadSymbolicExpr();
1607 	    return handler_.OnSymbolicIf(condition, then_expr, else_expr);
1608 	  }
1609 	  }
1610 	  return ReadNumericExpr(c, false);
1611 	}
1612 	
1613 	template <typename Reader, typename Handler>
1614 	typename Handler::NumericExpr
1615 	    NLReader<Reader, Handler>::ReadNumericExpr(char code, bool ignore_zero) {
1616 	  switch (code) {
1617 	  case 'f': {
1618 	    // Read a function call.
1619 	    int func_index = ReadUInt(header_.num_funcs);
1620 	    int num_args = reader_.ReadUInt();
1621 	    reader_.ReadTillEndOfLine();
1622 	    typename Handler::CallArgHandler args =
1623 	        handler_.BeginCall(func_index, num_args);
1624 	    for (int i = 0; i < num_args; ++i)
1625 	      args.AddArg(ReadSymbolicExpr());
1626 	    return handler_.EndCall(args);
1627 	  }
1628 	  case 'n': case 'l': case 's': {
1629 	    // Read a number.
1630 	    double value = ReadConstant(code);
1631 	    if (ignore_zero && value == 0)
1632 	      break;  // Ignore zero constant.
1633 	    return handler_.OnNumber(value);
1634 	  }
1635 	  case 'o':
1636 	    return ReadNumericExpr(ReadOpCode());
1637 	  case 'v':
1638 	    return DoReadReference();
1639 	  default:
1640 	    reader_.ReportError("expected expression");
1641 	  }
1642 	  return NumericExpr();
1643 	}
1644 	
1645 	template <typename Reader, typename Handler>
1646 	typename Handler::NumericExpr
1647 	    NLReader<Reader, Handler>::ReadNumericExpr(int opcode) {
1648 	  const internal::OpCodeInfo &info = internal::GetOpCodeInfo(opcode);
1649 	  expr::Kind kind = info.kind;
1650 	  switch (info.first_kind) {
1651 	  case expr::FIRST_UNARY:
1652 	    return handler_.OnUnary(kind, ReadNumericExpr());
1653 	  case expr::FIRST_BINARY: {
1654 	    BinaryArgReader<> args(*this);
1655 	    return handler_.OnBinary(kind, args.lhs, args.rhs);
1656 	  }
1657 	  case expr::IF: {
1658 	    LogicalExpr condition = ReadLogicalExpr();
1659 	    NumericExpr then_expr = ReadNumericExpr();
1660 	    NumericExpr else_expr = ReadNumericExpr();
1661 	    return handler_.OnIf(condition, then_expr, else_expr);
1662 	  }
1663 	  case expr::PLTERM: {
1664 	    // Read a piecewise-linear term.
1665 	    int num_slopes = reader_.ReadUInt();
1666 	    if (num_slopes <= 1)
1667 	      reader_.ReportError("too few slopes in piecewise-linear term");
1668 	    reader_.ReadTillEndOfLine();
1669 	    typename Handler::PLTermHandler pl_handler =
1670 	        handler_.BeginPLTerm(num_slopes - 1);
1671 	    for (int i = 0; i < num_slopes - 1; ++i) {
1672 	      pl_handler.AddSlope(ReadConstant());
1673 	      pl_handler.AddBreakpoint(ReadConstant());
1674 	    }
1675 	    pl_handler.AddSlope(ReadConstant());
1676 	    return handler_.EndPLTerm(pl_handler, ReadReference());
1677 	  }
1678 	  case expr::FIRST_VARARG: {
1679 	    // Read a vararg expression (min or max).
1680 	    int num_args = ReadNumArgs(1);
1681 	    typename Handler::VarArgHandler args = handler_.BeginVarArg(kind, num_args);
1682 	    ReadArgs<NumericExprReader>(num_args, args);
1683 	    return handler_.EndVarArg(args);
1684 	  }
1685 	  case expr::SUM: {
1686 	    int num_args = ReadNumArgs();
1687 	    typename Handler::NumericArgHandler args = handler_.BeginSum(num_args);
1688 	    ReadArgs<NumericExprReader>(num_args, args);
1689 	    return handler_.EndSum(args);
1690 	  }
1691 	  case expr::COUNT:
1692 	    return ReadCountExpr();
1693 	  case expr::NUMBEROF: {
1694 	    // Read a numberof expression.
1695 	    int num_args = ReadNumArgs(1);
1696 	    reader_.ReadTillEndOfLine();
1697 	    typename Handler::NumberOfArgHandler args =
1698 	        handler_.BeginNumberOf(num_args, ReadNumericExpr());
1699 	    DoReadArgs<NumericExprReader>(num_args - 1, args);
1700 	    return handler_.EndNumberOf(args);
1701 	  }
1702 	  case expr::NUMBEROF_SYM: {
1703 	    // Read a symbolic numberof expression.
1704 	    int num_args = ReadNumArgs(1);
1705 	    reader_.ReadTillEndOfLine();
1706 	    typename Handler::SymbolicArgHandler args =
1707 	        handler_.BeginSymbolicNumberOf(num_args, ReadSymbolicExpr());
1708 	    DoReadArgs<SymbolicExprReader>(num_args - 1, args);
1709 	    return handler_.EndSymbolicNumberOf(args);
1710 	  }
1711 	  default:
1712 	    reader_.ReportError("expected numeric expression opcode");
1713 	  }
1714 	  return NumericExpr();
1715 	}
1716 	
1717 	template <typename Reader, typename Handler>
1718 	typename Handler::LogicalExpr NLReader<Reader, Handler>::ReadLogicalExpr() {
1719 	  switch (char c = reader_.ReadChar()) {
1720 	  case 'n': case 'l': case 's':
1721 	    return handler_.OnBool(ReadConstant(c) != 0);
1722 	  case 'o':
1723 	    return ReadLogicalExpr(ReadOpCode());
1724 	  }
1725 	  reader_.ReportError("expected logical expression");
1726 	  return LogicalExpr();
1727 	}
1728 	
1729 	template <typename Reader, typename Handler>
1730 	typename Handler::LogicalExpr
1731 	    NLReader<Reader, Handler>::ReadLogicalExpr(int opcode) {
1732 	  const internal::OpCodeInfo &info = internal::GetOpCodeInfo(opcode);
1733 	  expr::Kind kind = info.kind;
1734 	  switch (info.first_kind) {
1735 	  case expr::NOT:
1736 	    return handler_.OnNot(ReadLogicalExpr());
1737 	  case expr::FIRST_BINARY_LOGICAL: {
1738 	    BinaryArgReader<LogicalExprReader> args(*this);
1739 	    return handler_.OnBinaryLogical(kind, args.lhs, args.rhs);
1740 	  }
1741 	  case expr::FIRST_RELATIONAL: {
1742 	    BinaryArgReader<> args(*this);
1743 	    return handler_.OnRelational(kind, args.lhs, args.rhs);
1744 	  }
1745 	  case expr::FIRST_LOGICAL_COUNT: {
1746 	    NumericExpr lhs = ReadNumericExpr();
1747 	    char c = reader_.ReadChar();
1748 	    if (c != 'o' || internal::GetOpCodeInfo(ReadOpCode()).kind != expr::COUNT)
1749 	      reader_.ReportError("expected count expression");
1750 	    return handler_.OnLogicalCount(kind, lhs, ReadCountExpr());
1751 	  }
1752 	  case expr::IMPLICATION: {
1753 	    // Read an implication (=>).
1754 	    LogicalExpr condition = ReadLogicalExpr();
1755 	    LogicalExpr then_expr = ReadLogicalExpr();
1756 	    LogicalExpr else_expr = ReadLogicalExpr();
1757 	    return handler_.OnImplication(condition, then_expr, else_expr);
1758 	  }
1759 	  case expr::FIRST_ITERATED_LOGICAL: {
1760 	    // Read an iterated logical expression (exists or forall).
1761 	    int num_args = ReadNumArgs();
1762 	    typename Handler::LogicalArgHandler args =
1763 	        handler_.BeginIteratedLogical(kind, num_args);
1764 	    ReadArgs<LogicalExprReader>(num_args, args);
1765 	    return handler_.EndIteratedLogical(args);
1766 	  }
1767 	  case expr::FIRST_PAIRWISE: {
1768 	    // Read a pairwise expression (alldiff or !alldiff).
1769 	    int num_args = ReadNumArgs(1);
1770 	    typename Handler::PairwiseArgHandler args =
1771 	        handler_.BeginPairwise(kind, num_args);
1772 	    ReadArgs<NumericExprReader>(num_args, args);
1773 	    return handler_.EndPairwise(args);
1774 	  }
1775 	  default:
1776 	    reader_.ReportError("expected logical expression opcode");
1777 	  }
1778 	  return LogicalExpr();
1779 	}
1780 	
1781 	template <typename Reader, typename Handler>
1782 	template <typename LinearHandler>
1783 	void NLReader<Reader, Handler>::ReadLinearExpr() {
1784 	  LinearHandler lh(*this);
1785 	  int index = ReadUInt(lh.num_items());
1786 	  // The number of terms should be less than num_vars because common
1787 	  // expressions are not allowed in a linear expression.
1788 	  int num_terms = ReadUInt(1, header_.num_vars + 1u);
1789 	  reader_.ReadTillEndOfLine();
1790 	  if (lh.SkipExpr(index))
1791 	    ReadLinearExpr(num_terms, NullLinearExprHandler());
1792 	  else
1793 	    ReadLinearExpr(num_terms, lh.OnLinearExpr(index, num_terms));
1794 	}
1795 	
1796 	template <typename Reader, typename Handler>
1797 	template <typename LinearHandler>
1798 	void NLReader<Reader, Handler>::ReadLinearExpr(
1799 	    int num_terms, LinearHandler linear_expr) {
1800 	  for (int i = 0; i < num_terms; ++i) {
1801 	    // Variable index should be less than num_vars because common
1802 	    // expressions are not allowed in a linear expression.
1803 	    int var_index = ReadUInt(header_.num_vars);
1804 	    double coef = reader_.ReadDouble();
1805 	    reader_.ReadTillEndOfLine();
1806 	    linear_expr.AddTerm(var_index, coef);
1807 	  }
1808 	}
1809 	
1810 	template <typename Reader, typename Handler>
1811 	template <typename BoundHandler>
1812 	void NLReader<Reader, Handler>::ReadBounds() {
1813 	  enum BoundType {
1814 	    RANGE,     // Both lower and upper bounds: l <= body <= u.
1815 	    UPPER,     // Only upper bound: body <= u.
1816 	    LOWER,     // Only lower bound: l <= body.
1817 	    FREE,      // No constraints on body (free variable or constraint).
1818 	    CONSTANT,  // Equal to constant: body = c.
1819 	    COMPL      // Body complements variable v[i - 1].
1820 	  };
1821 	  reader_.ReadTillEndOfLine();
1822 	  double lb = 0, ub = 0;
1823 	  BoundHandler bh(*this);
1824 	  int num_bounds = bh.num_items();
1825 	  double infinity = std::numeric_limits<double>::infinity();
1826 	  for (int i = 0; i < num_bounds; ++i) {
1827 	    switch (reader_.ReadChar() - '0') {
1828 	    case RANGE:
1829 	      lb = reader_.ReadDouble();
1830 	      ub = reader_.ReadDouble();
1831 	      break;
1832 	    case UPPER:
1833 	      lb = -infinity;
1834 	      ub = reader_.ReadDouble();
1835 	      break;
1836 	    case LOWER:
1837 	      lb = reader_.ReadDouble();
1838 	      ub = infinity;
1839 	      break;
1840 	    case FREE:
1841 	      lb = -infinity;
1842 	      ub =  infinity;
1843 	      break;
1844 	    case CONSTANT:
1845 	      lb = ub = reader_.ReadDouble();
1846 	      break;
1847 	    case COMPL:
1848 	      if (BoundHandler::TYPE == CON) {
1849 	        int flags = reader_.template ReadInt<int>();
1850 	        int var_index = reader_.ReadUInt();
1851 	        // Don't use NLReader::ReadUInt(int, int) as num_vars + 1 may overflow.
1852 	        if (var_index == 0 || var_index > header_.num_vars)
1853 	          reader_.ReportError("integer {} out of bounds", var_index);
1854 	        --var_index;
1855 	        int mask = ComplInfo::INF_LB | ComplInfo::INF_UB;
1856 	        handler_.OnComplementarity(i, var_index, ComplInfo(flags & mask));
1857 	        reader_.ReadTillEndOfLine();
1858 	        continue;
1859 	      }
1860 	      reader_.ReportError("COMPL bound type is invalid for variables");
1861 	      break;
1862 	    default:
1863 	      reader_.ReportError("expected bound");
1864 	    }
1865 	    reader_.ReadTillEndOfLine();
1866 	    bh.SetBounds(i, lb, ub);
1867 	  }
1868 	}
1869 	
1870 	template <typename Reader, typename Handler>
1871 	template <bool CUMULATIVE>
1872 	void NLReader<Reader, Handler>::ReadColumnSizes() {
1873 	  int num_sizes = header_.num_vars - 1;
1874 	  if (reader_.ReadUInt() != num_sizes)
1875 	    reader_.ReportError("expected {}", num_sizes);
1876 	  reader_.ReadTillEndOfLine();
1877 	  typename Handler::ColumnSizeHandler size_handler = handler_.OnColumnSizes();
1878 	  int prev_size = 0;
1879 	  for (int i = 0; i < num_sizes; ++i) {
1880 	    int size = reader_.ReadUInt();
1881 	    if (CUMULATIVE) {
1882 	      if (size < prev_size)
1883 	        reader_.ReportError("invalid column offset");
1884 	      size -= prev_size;
1885 	      prev_size += size;
1886 	    }
1887 	    size_handler.Add(size);
1888 	    reader_.ReadTillEndOfLine();
1889 	  }
1890 	}
1891 	
1892 	template <typename Reader, typename Handler>
1893 	template <typename ValueHandler>
1894 	void NLReader<Reader, Handler>::ReadInitialValues() {
1895 	  int num_values = reader_.ReadUInt();
1896 	  ValueHandler vh(*this);
1897 	  if (num_values > vh.num_items())
1898 	    reader_.ReportError("too many initial values");
1899 	  reader_.ReadTillEndOfLine();
1900 	  for (int i = 0; i < num_values; ++i) {
1901 	    int index = ReadUInt(vh.num_items());
1902 	    vh.SetInitialValue(index, reader_.ReadDouble());
1903 	    reader_.ReadTillEndOfLine();
1904 	  }
1905 	}
1906 	
1907 	template <typename Reader, typename Handler>
1908 	template <typename ItemInfo>
1909 	void NLReader<Reader, Handler>::ReadSuffix(int info) {
1910 	  int num_items = ItemInfo(*this).num_items();
1911 	  int num_values = ReadUInt(1, num_items + 1);
1912 	  fmt::StringRef name = reader_.ReadName();
1913 	  reader_.ReadTillEndOfLine();
1914 	  suf::Kind kind = static_cast<suf::Kind>(info & internal::SUFFIX_KIND_MASK);
1915 	  if ((info & suf::FLOAT) != 0) {
1916 	    typename Handler::DblSuffixHandler
1917 	        suffix_handler = handler_.OnDblSuffix(name, kind, num_values);
1918 	    ReadSuffixValues<DoubleReader>(num_values, num_items, suffix_handler);
1919 	  } else {
1920 	    typename Handler::IntSuffixHandler
1921 	        suffix_handler = handler_.OnIntSuffix(name, kind, num_values);
1922 	    ReadSuffixValues<IntReader>(num_values, num_items, suffix_handler);
1923 	  }
1924 	}
1925 	
1926 	template <typename Reader, typename Handler>
1927 	void NLReader<Reader, Handler>::Read(Reader *bound_reader) {
1928 	  bool read_bounds = bound_reader == 0;
1929 	  // TextReader::ReadHeader checks that this doesn't overflow.
1930 	  num_vars_and_exprs_ = header_.num_vars +
1931 	      header_.num_common_exprs_in_both +
1932 	      header_.num_common_exprs_in_cons +
1933 	      header_.num_common_exprs_in_objs +
1934 	      header_.num_common_exprs_in_single_cons +
1935 	      header_.num_common_exprs_in_single_objs;
1936 	  for (;;) {
1937 	    char c = reader_.ReadChar();
1938 	    switch (c) {
1939 	    case 'C': {
1940 	      // Nonlinear part of an algebraic constraint body.
1941 	      int index = ReadUInt(header_.num_algebraic_cons);
1942 	      reader_.ReadTillEndOfLine();
1943 	      handler_.OnAlgebraicCon(index, ReadNumericExpr(true));
1944 	      break;
1945 	    }
1946 	    case 'L': {
1947 	      // Logical constraint expression.
1948 	      int index = ReadUInt(header_.num_logical_cons);
1949 	      reader_.ReadTillEndOfLine();
1950 	      handler_.OnLogicalCon(index, ReadLogicalExpr());
1951 	      break;
1952 	    }
1953 	    case 'O': {
1954 	      // Objective type and nonlinear part of an objective expression.
1955 	      int index = ReadUInt(header_.num_objs);
1956 	      int obj_type = reader_.ReadUInt();
1957 	      reader_.ReadTillEndOfLine();
1958 	      NumericExpr expr = ReadNumericExpr(true);
1959 	      if (handler_.NeedObj(index))
1960 	        handler_.OnObj(handler_.resulting_obj_index(index),
1961 	                       obj_type != 0 ? obj::MAX : obj::MIN,
1962 	                       expr);
1963 	      break;
1964 	    }
1965 	    case 'V': {
1966 	      // Defined variable definition (must precede V, C, L, O segments
1967 	      // where used).
1968 	      int expr_index = ReadUInt(header_.num_vars, num_vars_and_exprs_);
1969 	      expr_index -= header_.num_vars;
1970 	      int num_linear_terms = reader_.ReadUInt();
1971 	      int position = reader_.ReadUInt();
1972 	      reader_.ReadTillEndOfLine();
1973 	      typename Handler::LinearExprHandler
1974 	          expr_handler(handler_.BeginCommonExpr(expr_index, num_linear_terms));
1975 	      if (num_linear_terms != 0)
1976 	        ReadLinearExpr(num_linear_terms, expr_handler);
1977 	      handler_.EndCommonExpr(expr_index, ReadNumericExpr(), position);
1978 	      break;
1979 	    }
1980 	    case 'F': {
1981 	      // Imported function description.
1982 	      int index = ReadUInt(header_.num_funcs);
1983 	      int type = reader_.ReadUInt();
1984 	      if (type != func::NUMERIC && type != func::SYMBOLIC)
1985 	        reader_.ReportError("invalid function type");
1986 	      int num_args = reader_.template ReadInt<int>();
1987 	      fmt::StringRef name = reader_.ReadName();
1988 	      reader_.ReadTillEndOfLine();
1989 	      handler_.OnFunction(index, name, num_args, static_cast<func::Type>(type));
1990 	      break;
1991 	    }
1992 	    case 'G':
1993 	      // Linear part of an objective expression & gradient sparsity.
1994 	      ReadLinearExpr<ObjHandler>();
1995 	      break;
1996 	    case 'J':
1997 	      // Jacobian sparsity & linear terms in constraints.
1998 	      ReadLinearExpr<AlgebraicConHandler>();
1999 	      break;
2000 	    case 'S': {
2001 	      // Suffix values.
2002 	      int info = reader_.ReadUInt();
2003 	      if (info > (internal::SUFFIX_KIND_MASK | suf::FLOAT))
2004 	        reader_.ReportError("invalid suffix kind");
2005 	      switch (info & internal::SUFFIX_KIND_MASK) {
2006 	      case suf::VAR:
2007 	        ReadSuffix<VarHandler>(info);
2008 	        break;
2009 	      case suf::CON:
2010 	        ReadSuffix<ConHandler>(info);
2011 	        break;
2012 	      case suf::OBJ:
2013 	        ReadSuffix<ObjHandler>(info);
2014 	        break;
2015 	      case suf::PROBLEM:
2016 	        ReadSuffix<ProblemHandler>(info);
2017 	        break;
2018 	      }
2019 	      break;
2020 	    }
2021 	    case 'b':
2022 	      // Bounds on variables.
2023 	      if (read_bounds) {
2024 	        ReadBounds<VarHandler>();
(1) Event side_effect_free: Calling "this->reader_->ptr()" is only useful for its return value, which is ignored. [details]
2025 	        reader_.ptr();
2026 	        if ((flags_ & READ_BOUNDS_FIRST) != 0)
2027 	          return;
2028 	        read_bounds = false;
2029 	        break;
2030 	      }
2031 	      if (!bound_reader)
2032 	        reader_.ReportError("duplicate 'b' segment");
2033 	      reader_ = *bound_reader;
2034 	      bound_reader = 0;
2035 	      break;
2036 	    case 'r':
2037 	      // Bounds on algebraic constraint bodies ("ranges").
2038 	      ReadBounds<AlgebraicConHandler>();
2039 	      break;
2040 	    case 'K':
2041 	      // Jacobian sparsity & linear constraint term matrix column sizes
2042 	      // (must precede all J segments).
2043 	      ReadColumnSizes<false>();
2044 	      break;
2045 	    case 'k':
2046 	      // Jacobian sparsity & linear constraint term matrix cumulative column
2047 	      // sizes (must precede all J segments).
2048 	      ReadColumnSizes<true>();
2049 	      break;
2050 	    case 'x':
2051 	      // Primal initial guess.
2052 	      ReadInitialValues<VarHandler>();
2053 	      break;
2054 	    case 'd':
2055 	      // Dual initial guess.
2056 	      ReadInitialValues<AlgebraicConHandler>();
2057 	      break;
2058 	    case '\0':
2059 	      if (reader_.IsEOF()) {
2060 	        if (read_bounds)
2061 	          reader_.ReportError("segment 'b' missing");
2062 	        return;
2063 	      }
2064 	      // Fall through.
2065 	    default:
2066 	      reader_.ReportError("invalid segment type");
2067 	    }
2068 	  }
2069 	}
2070 	
2071 	template <typename Reader, typename Handler>
2072 	void NLReader<Reader, Handler>::Read() {
2073 	  if ((flags_ & READ_BOUNDS_FIRST) != 0) {
2074 	    // Read variable bounds first because this allows more efficient
2075 	    // problem construction.
2076 	    VarBoundHandler<Handler> bound_handler(handler_);
2077 	    Reader bound_reader(reader_);
2078 	    NLReader< Reader, VarBoundHandler<Handler> >
2079 	        reader(bound_reader, header_, bound_handler, flags_);
2080 	    reader.Read(0);
2081 	    // Read everything else.
2082 	    Read(&bound_reader);
2083 	  } else {
2084 	    Read(0);
2085 	  }
2086 	  handler_.EndInput();
2087 	}
2088 	
2089 	// An .nl file reader.
2090 	template <typename File = fmt::File>
2091 	class NLFileReader {
2092 	 private:
2093 	  File file_;
2094 	  std::size_t size_;
2095 	  std::size_t rounded_size_;  // Size rounded up to a multiple of page size.
2096 	
2097 	  void Open(fmt::CStringRef filename);
2098 	
2099 	  // Reads the file into an array.
2100 	  void Read(fmt::internal::MemoryBuffer<char, 1> &array);
2101 	
2102 	 public:
2103 	  NLFileReader() : size_(0), rounded_size_(0) {}
2104 	
2105 	  const File &file() { return file_; }
2106 	
2107 	  // Opens and reads the file.
2108 	  template <typename Handler>
2109 	  void Read(fmt::CStringRef filename, Handler &handler, int flags) {
2110 	    Open(filename);
2111 	    if (size_ == rounded_size_) {
2112 	      // Don't use mmap, because the file size is a multiple of the page size
2113 	      // and therefore the mmap'ed buffer won't be null-terminated.
2114 	      fmt::internal::MemoryBuffer<char, 1> array;
2115 	      Read(array);
2116 	      return ReadNLString(
2117 	            NLStringRef(&array[0], size_), handler, filename, flags);
2118 	    }
2119 	    MemoryMappedFile<File> mapped_file(file_, rounded_size_);
2120 	    ReadNLString(
2121 	          NLStringRef(mapped_file.start(), size_), handler, filename, flags);
2122 	  }
2123 	};
2124 	
2125 	template <typename InputConverter, typename Handler>
2126 	void ReadBinary(TextReader<> &reader, const NLHeader &header,
2127 	                Handler &handler, int flags) {
2128 	  BinaryReader<InputConverter> bin_reader(reader);
2129 	  NLReader<BinaryReader<InputConverter>, Handler>(
2130 	        bin_reader, header, handler, flags).Read();
2131 	}
2132 	
2133 	template <typename NameHandler>
2134 	void ReadNames(fmt::CStringRef filename, fmt::StringRef data,
2135 	               NameHandler &handler) {
2136 	  int line = 1;
2137 	  const char *start = data.data();
2138 	  const char *end = start + data.size();
2139 	  for (const char *ptr = start; ptr != end; ++ptr) {
2140 	    if (*ptr == '\n') {
2141 	      handler.OnName(fmt::StringRef(start, ptr - start));
2142 	      start = ptr + 1;
2143 	      ++line;
2144 	    }
2145 	  }
2146 	  if (start != end) {
2147 	    int column = static_cast<int>(end - start + 1);
2148 	    throw ReadError(filename, line, column, "missing newline");
2149 	  }
2150 	}
2151 	
2152 	// A name file reader.
2153 	class NameReader {
2154 	 private:
2155 	  MemoryMappedFile<> mapped_file_;
2156 	
2157 	 public:
2158 	  // Reads names from the file *filename* sending the names to the *handler*
2159 	  // object by calling ``handler.OnName(name)``. The name argument to
2160 	  // ``OnName`` is a ``fmt::StringRef`` object and the string it refers to
2161 	  // is not null-terminated.
2162 	  // Each name in the input file should be on a separate line ended with a
2163 	  // newline character ('\n').
2164 	  template <typename NameHandler>
2165 	  void Read(fmt::CStringRef filename, NameHandler &handler) {
2166 	    fmt::File file(filename, fmt::File::RDONLY);
2167 	    mapped_file_.map(file, filename);
2168 	    fmt::StringRef data(mapped_file_.start(), mapped_file_.size());
2169 	    ReadNames(filename, data, handler);
2170 	  }
2171 	};
2172 	
2173 	// An NL handler that constructs an optimization problem using ProblemBuilder.
2174 	template <typename ProblemBuilder>
2175 	class NLProblemBuilder {
2176 	 public:
2177 	  typedef typename ProblemBuilder::Function Function;
2178 	  typedef typename ProblemBuilder::Expr Expr;
2179 	  typedef typename ProblemBuilder::NumericExpr NumericExpr;
2180 	  typedef typename ProblemBuilder::LogicalExpr LogicalExpr;
2181 	  typedef typename ProblemBuilder::CountExpr CountExpr;
2182 	  typedef typename ProblemBuilder::Reference Reference;
2183 	
2184 	 private:
2185 	  ProblemBuilder &builder_;
2186 	
2187 	  template <typename Obj>
2188 	  void SetObj(const Obj &obj, obj::Type type, NumericExpr expr) {
2189 	    obj.set_type(type);
2190 	    obj.set_nonlinear_expr(expr);
2191 	  }
2192 	
2193 	  // Sets bounds on a problem item (objective or constraint).
2194 	  template <typename Item>
2195 	  void SetBounds(const Item &item, double lb, double ub) {
2196 	    item.set_lb(lb);
2197 	    item.set_ub(ub);
2198 	  }
2199 	
2200 	  template <typename CommonExpr>
2201 	  void SetCommonExpr(const CommonExpr &common_expr,
2202 	                     NumericExpr expr, int position) {
2203 	    common_expr.set_nonlinear_expr(expr);
2204 	    common_expr.set_position(position);
2205 	  }
2206 	
2207 	 public:
2208 	  explicit NLProblemBuilder(ProblemBuilder &builder): builder_(builder) {}
2209 	
2210 	  ProblemBuilder &builder() { return builder_; }
2211 	
2212 	  void OnHeader(const NLHeader &h) {
2213 	    builder_.SetInfo(h);
2214 	
2215 	    // As nl-benchmark shows, adding problem components at once and then
2216 	    // updating them is faster than adding them incrementally. The latter
2217 	    // requires additional checks to make sure that prolbem components are
2218 	    // in the correct order.
2219 	    if (int n = h.num_continuous_vars())
2220 	      builder_.AddVars(n, var::CONTINUOUS);
2221 	    if (int n = h.num_integer_vars())
2222 	      builder_.AddVars(n, var::INTEGER);
2223 	    if (int n = h.num_common_exprs())
2224 	      builder_.AddCommonExprs(n);
2225 	    int n_objs = resulting_nobj( h.num_objs );
2226 	    if (n_objs != 0)
2227 	      builder_.AddObjs( n_objs );
2228 	    if (h.num_algebraic_cons != 0)
2229 	      builder_.AddAlgebraicCons(h.num_algebraic_cons);
2230 	    if (h.num_logical_cons != 0)
2231 	      builder_.AddLogicalCons(h.num_logical_cons);
2232 	    if (h.num_funcs != 0)
2233 	      builder_.AddFunctions(h.num_funcs);
2234 	  }
2235 	
2236 	  virtual int objno() const { return 1; }
2237 	  virtual bool multiobj() const { return true; }
2238 	
2239 	  int resulting_nobj(int nobj_header) const {
2240 	    return multiobj() ? nobj_header :
2241 	                        std::min( (objno()>0), (nobj_header>0) );
2242 	  }
2243 	  bool NeedObj(int obj_index) const {
2244 	    return multiobj() || objno()-1==obj_index;
2245 	  }
2246 	  int resulting_obj_index(int index) const {
2247 	    if (multiobj())
2248 	      return index;
2249 	    assert(objno()-1==index);
2250 	    return 0;
2251 	  }
2252 	
2253 	  void OnObj(int index, obj::Type type, NumericExpr expr) {
2254 	    SetObj(builder_.obj(index), type, expr);
2255 	  }
2256 	
2257 	  void OnAlgebraicCon(int index, NumericExpr expr) {
2258 	    builder_.algebraic_con(index).set_nonlinear_expr(expr);
2259 	  }
2260 	
2261 	  void OnLogicalCon(int index, LogicalExpr expr) {
2262 	    builder_.logical_con(index).set_expr(expr);
2263 	  }
2264 	
2265 	  void OnComplementarity(int con_index, int var_index, ComplInfo info) {
2266 	    builder_.SetComplementarity(con_index, var_index, info);
2267 	  }
2268 	
2269 	  typedef typename ProblemBuilder::LinearObjBuilder LinearObjHandler;
2270 	
2271 	  LinearObjHandler OnLinearObjExpr(int obj_index, int num_linear_terms) {
2272 	    return builder_.obj(obj_index).set_linear_expr(num_linear_terms);
2273 	  }
2274 	
2275 	  typedef typename ProblemBuilder::LinearConBuilder LinearConHandler;
2276 	
2277 	  LinearConHandler OnLinearConExpr(int con_index, int num_linear_terms) {
2278 	    return builder_.algebraic_con(con_index).set_linear_expr(num_linear_terms);
2279 	  }
2280 	
2281 	  typedef typename ProblemBuilder::LinearExprBuilder LinearExprHandler;
2282 	
2283 	  LinearExprHandler BeginCommonExpr(int index, int num_linear_terms) {
2284 	    return builder_.common_expr(index).set_linear_expr(num_linear_terms);
2285 	  }
2286 	  void EndCommonExpr(int index, NumericExpr expr, int position) {
2287 	    SetCommonExpr(builder_.common_expr(index), expr, position);
2288 	  }
2289 	
2290 	  void OnVarBounds(int index, double lb, double ub) {
2291 	    SetBounds(builder_.var(index), lb, ub);
2292 	  }
2293 	
2294 	  void OnConBounds(int index, double lb, double ub) {
2295 	    SetBounds(builder_.algebraic_con(index), lb, ub);
2296 	  }
2297 	
2298 	  void OnInitialValue(int var_index, double value) {
2299 	    builder_.var(var_index).set_value(value);
2300 	  }
2301 	
2302 	  void OnInitialDualValue(int con_index, double value) {
2303 	    builder_.algebraic_con(con_index).set_dual(value);
2304 	  }
2305 	
2306 	  struct ColumnSizeHandler {
2307 	    void Add(int) {
2308 	      // Ignore column sizes as the constraints are stored row-wise by default.
2309 	    }
2310 	  };
2311 	
2312 	  ColumnSizeHandler OnColumnSizes() {
2313 	    return ColumnSizeHandler();
2314 	  }
2315 	
2316 	  void OnFunction(int index, fmt::StringRef name,
2317 	                  int num_args, func::Type type) {
2318 	    builder_.DefineFunction(index, name, num_args, type);
2319 	  }
2320 	
2321 	  typedef typename ProblemBuilder::IntSuffixHandler IntSuffixHandler;
2322 	
2323 	  IntSuffixHandler OnIntSuffix(fmt::StringRef name, suf::Kind kind,
2324 	                               int num_values) {
2325 	    return builder_.AddIntSuffix(name, kind, num_values);
2326 	  }
2327 	
2328 	  typedef typename ProblemBuilder::DblSuffixHandler DblSuffixHandler;
2329 	
2330 	  DblSuffixHandler OnDblSuffix(fmt::StringRef name, suf::Kind kind,
2331 	                               int num_values) {
2332 	    return builder_.AddDblSuffix(name, kind, num_values);
2333 	  }
2334 	
2335 	  NumericExpr OnNumber(double value) {
2336 	    return builder_.MakeNumericConstant(value);
2337 	  }
2338 	
2339 	  Reference OnVariableRef(int var_index) {
2340 	    return builder_.MakeVariable(var_index);
2341 	  }
2342 	
2343 	  Reference OnCommonExprRef(int expr_index) {
2344 	    return builder_.MakeCommonExpr(expr_index);
2345 	  }
2346 	
2347 	  NumericExpr OnUnary(expr::Kind kind, NumericExpr arg) {
2348 	    return builder_.MakeUnary(kind, arg);
2349 	  }
2350 	
2351 	  NumericExpr OnBinary(expr::Kind kind, NumericExpr lhs, NumericExpr rhs) {
2352 	    return builder_.MakeBinary(kind, lhs, rhs);
2353 	  }
2354 	
2355 	  NumericExpr OnIf(LogicalExpr condition,
2356 	      NumericExpr then_expr, NumericExpr else_expr) {
2357 	    return builder_.MakeIf(condition, then_expr, else_expr);
2358 	  }
2359 	
2360 	  typedef typename ProblemBuilder::PLTermBuilder PLTermHandler;
2361 	
2362 	  PLTermHandler BeginPLTerm(int num_breakpoints) {
2363 	    return builder_.BeginPLTerm(num_breakpoints);
2364 	  }
2365 	  NumericExpr EndPLTerm(PLTermHandler handler, Reference arg) {
2366 	    return builder_.EndPLTerm(handler, arg);
2367 	  }
2368 	
2369 	  typedef typename ProblemBuilder::CallExprBuilder CallArgHandler;
2370 	
2371 	  CallArgHandler BeginCall(int func_index, int num_args) {
2372 	    // Check if the function is defined.
2373 	    if (Function func = builder_.function(func_index))
2374 	      return builder_.BeginCall(func, num_args);
2375 	    throw Error("function {} is not defined", func_index);
2376 	  }
2377 	  NumericExpr EndCall(CallArgHandler handler) {
2378 	    return builder_.EndCall(handler);
2379 	  }
2380 	
2381 	  typedef typename ProblemBuilder::IteratedExprBuilder VarArgHandler;
2382 	
2383 	  VarArgHandler BeginVarArg(expr::Kind kind, int num_args) {
2384 	    return builder_.BeginIterated(kind, num_args);
2385 	  }
2386 	  NumericExpr EndVarArg(VarArgHandler handler) {
2387 	    return builder_.EndIterated(handler);
2388 	  }
2389 	
2390 	  typedef typename ProblemBuilder::IteratedExprBuilder NumericArgHandler;
2391 	
2392 	  NumericArgHandler BeginSum(int num_args) {
2393 	    return builder_.BeginSum(num_args);
2394 	  }
2395 	  NumericExpr EndSum(NumericArgHandler handler) {
2396 	    return builder_.EndSum(handler);
2397 	  }
2398 	
2399 	  typedef typename ProblemBuilder::NumberOfExprBuilder NumberOfArgHandler;
2400 	
2401 	  NumberOfArgHandler BeginNumberOf(int num_args, NumericExpr arg0) {
2402 	    return builder_.BeginNumberOf(num_args, arg0);
2403 	  }
2404 	  NumericExpr EndNumberOf(NumberOfArgHandler handler) {
2405 	    return builder_.EndNumberOf(handler);
2406 	  }
2407 	
2408 	  typedef typename ProblemBuilder::SymbolicNumberOfExprBuilder
2409 	          SymbolicArgHandler;
2410 	
2411 	  SymbolicArgHandler BeginSymbolicNumberOf(int num_args, Expr arg0) {
2412 	    return builder_.BeginSymbolicNumberOf(num_args, arg0);
2413 	  }
2414 	  NumericExpr EndSymbolicNumberOf(SymbolicArgHandler handler) {
2415 	    return builder_.EndSymbolicNumberOf(handler);
2416 	  }
2417 	
2418 	  typedef typename ProblemBuilder::CountExprBuilder CountArgHandler;
2419 	
2420 	  CountArgHandler BeginCount(int num_args) {
2421 	    return builder_.BeginCount(num_args);
2422 	  }
2423 	  CountExpr EndCount(CountArgHandler handler) {
2424 	    return builder_.EndCount(handler);
2425 	  }
2426 	
2427 	  LogicalExpr OnBool(bool value) {
2428 	    return builder_.MakeLogicalConstant(value);
2429 	  }
2430 	
2431 	  LogicalExpr OnNot(LogicalExpr arg) {
2432 	    return builder_.MakeNot(arg);
2433 	  }
2434 	
2435 	  LogicalExpr OnBinaryLogical(
2436 	      expr::Kind kind, LogicalExpr lhs, LogicalExpr rhs) {
2437 	    return builder_.MakeBinaryLogical(kind, lhs, rhs);
2438 	  }
2439 	
2440 	  LogicalExpr OnRelational(
2441 	      expr::Kind kind, NumericExpr lhs, NumericExpr rhs) {
2442 	    return builder_.MakeRelational(kind, lhs, rhs);
2443 	  }
2444 	
2445 	  LogicalExpr OnLogicalCount(
2446 	      expr::Kind kind, NumericExpr lhs, CountExpr rhs) {
2447 	    return builder_.MakeLogicalCount(kind, lhs, rhs);
2448 	  }
2449 	
2450 	  LogicalExpr OnImplication(
2451 	      LogicalExpr condition, LogicalExpr then_expr, LogicalExpr else_expr) {
2452 	    return builder_.MakeImplication(condition, then_expr, else_expr);
2453 	  }
2454 	
2455 	  typedef typename ProblemBuilder::IteratedLogicalExprBuilder LogicalArgHandler;
2456 	
2457 	  LogicalArgHandler BeginIteratedLogical(expr::Kind kind, int num_args) {
2458 	    return builder_.BeginIteratedLogical(kind, num_args);
2459 	  }
2460 	  LogicalExpr EndIteratedLogical(LogicalArgHandler handler) {
2461 	    return builder_.EndIteratedLogical(handler);
2462 	  }
2463 	
2464 	  typedef typename ProblemBuilder::PairwiseExprBuilder PairwiseArgHandler;
2465 	
2466 	  PairwiseArgHandler BeginPairwise(expr::Kind kind, int num_args) {
2467 	    return builder_.BeginPairwise(kind, num_args);
2468 	  }
2469 	  LogicalExpr EndPairwise(PairwiseArgHandler handler) {
2470 	    return builder_.EndPairwise(handler);
2471 	  }
2472 	
2473 	  Expr OnString(fmt::StringRef value) {
2474 	    return builder_.MakeStringLiteral(value);
2475 	  }
2476 	
2477 	  Expr OnSymbolicIf(LogicalExpr condition, Expr then_expr, Expr else_expr) {
2478 	    return builder_.MakeSymbolicIf(condition, then_expr, else_expr);
2479 	  }
2480 	
2481 	  void EndInput() {}
2482 	};
2483 	
2484 	template <typename Handler, bool>
2485 	struct NLAdapter {
2486 	  typedef Handler Type;
2487 	  typedef Handler &RefType;
2488 	};
2489 	
2490 	template <typename Handler>
2491 	struct NLAdapter<Handler, true> {
2492 	  typedef NLProblemBuilder<typename Handler::Builder> Type;
2493 	  typedef Type RefType;
2494 	};
2495 	
2496 	// SV added to suppress warning in following class
2497 	// see also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71484#c5
2498 	#ifdef __GNUC__
2499 	#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
2500 	#endif
2501 	
2502 	// Checks if T has a member type Builder.
2503 	template <typename T>
2504 	class HasBuilder {
2505 	 private:
2506 	  template <typename U> static fmt::internal::Yes &test(typename U::Builder *);
2507 	  template <typename U> static fmt::internal::No &test(...);
2508 	 public:
2509 	  enum {value = sizeof(test<T>(0)) == sizeof(fmt::internal::Yes)};
2510 	};
2511 	}  // namespace internal
2512 	
2513 	template <typename Handler>
2514 	void ReadNLString(NLStringRef str, Handler &handler,
2515 	                  fmt::CStringRef name, int flags) {
2516 	  // If handler is a Problem-like object (Problem::Builder type is defined)
2517 	  // then use ProblemBuilder API to populate it.
2518 	  typedef internal::NLAdapter<
2519 	      Handler, internal::HasBuilder<Handler>::value> Adapter;
2520 	  typename Adapter::RefType adapter(handler);
2521 	  internal::TextReader<> reader(str, name);
2522 	  NLHeader header = NLHeader();
2523 	  reader.ReadHeader(header);
2524 	  adapter.OnHeader(header);
2525 	  switch (header.format) {
2526 	  case NLHeader::TEXT:
2527 	    internal::NLReader<internal::TextReader<>, typename Adapter::Type>(
2528 	          reader, header, adapter, flags).Read();
2529 	    break;
2530 	  case NLHeader::BINARY: {
2531 	      using internal::ReadBinary;
2532 	    arith::Kind arith_kind = arith::GetKind();
2533 	    if (arith_kind == header.arith_kind) {
2534 	      ReadBinary<internal::IdentityConverter>(reader, header, adapter, flags);
2535 	      break;
2536 	    }
2537 	    if (!IsIEEE(arith_kind) || !IsIEEE(header.arith_kind))
2538 	      throw ReadError(name, 0, 0, "unsupported floating-point arithmetic");
2539 	    ReadBinary<internal::EndiannessConverter>(reader, header, adapter, flags);
2540 	    break;
2541 	  }
2542 	  }
2543 	}
2544 	
2545 	template <typename Handler>
2546 	inline void ReadNLFile(fmt::CStringRef filename, Handler &handler, int flags) {
2547 	  internal::NLFileReader<>().Read(filename, handler, flags);
2548 	}
2549 	}  // namespace mp
2550 	
2551 	#endif  // MP_NL_READER_H_
2552