text:
#ifndef __itkMattesMutualInformationImageToImageMetricv4GetValueAndDerivativeThreader_h
#define __itkMattesMutualInformationImageToImageMetricv4GetValueAndDerivativeThreader_h

#include "itkImageToImageMetricv4GetValueAndDerivativeThreader.h"

namespace itk
{

/** \class MattesMutualInformationImageToImageMetricv4GetValueAndDerivativeThreader
 * \brief Processes points for MattesMutualInformationImageToImageMetricv4 \c
 * GetValueAndDerivative.
 *
 * \ingroup ITKMetricsv4
 */
template < class TDomainPartitioner, class TImageToImageMetric, class TMattesMutualInformationMetric >
class MattesMutualInformationImageToImageMetricv4GetValueAndDerivativeThreader
  : public ImageToImageMetricv4GetValueAndDerivativeThreader< TDomainPartitioner, TImageToImageMetric >
{
public:
  /** Standard class typedefs. */
  typedef MattesMutualInformationImageToImageMetricv4GetValueAndDerivativeThreader                                      Self;
  typedef ImageToImageMetricv4GetValueAndDerivativeThreader< TDomainPartitioner, TImageToImageMetric > Superclass;
  typedef SmartPointer< Self >                                                                         Pointer;
  typedef SmartPointer< const Self >                                                                   ConstPointer;

  itkTypeMacro( MattesMutualInformationImageToImageMetricv4GetValueAndDerivativeThreader, ImageToImageMetricv4GetValueAndDerivativeThreader );

  itkNewMacro( Self );

  typedef typename Superclass::DomainType               DomainType;
  typedef typename Superclass::AssociateType            AssociateType;

  typedef typename Superclass::ImageToImageMetricv4Type ImageToImageMetricv4Type;
  typedef typename Superclass::VirtualPointType         VirtualPointType;
  typedef typename Superclass::VirtualIndexType         VirtualIndexType;
  typedef typename Superclass::FixedImagePointType      FixedImagePointType;
  typedef typename Superclass::FixedImageIndexType      FixedImageIndexType;
  typedef typename Superclass::FixedImagePixelType      FixedImagePixelType;
  typedef typename Superclass::FixedImageGradientType   FixedImageGradientType;
  typedef typename Superclass::MovingImagePointType     MovingImagePointType;
  typedef typename Superclass::MovingImagePixelType     MovingImagePixelType;
  typedef typename Superclass::MovingImageGradientType  MovingImageGradientType;
  typedef typename Superclass::MeasureType              MeasureType;
  typedef typename Superclass::DerivativeType           DerivativeType;
  typedef typename Superclass::DerivativeValueType      DerivativeValueType;
  typedef typename Superclass::NumberOfParametersType   NumberOfParametersType;

  typedef typename TMattesMutualInformationMetric::PDFValueType                   PDFValueType;
  typedef typename TMattesMutualInformationMetric::JointPDFType                   JointPDFType;
  typedef typename TMattesMutualInformationMetric::JointPDFRegionType             JointPDFRegionType;
  typedef typename TMattesMutualInformationMetric::JointPDFIndexType              JointPDFIndexType;
  typedef typename TMattesMutualInformationMetric::JointPDFValueType              JointPDFValueType;
  typedef typename TMattesMutualInformationMetric::JointPDFSizeType               JointPDFSizeType;
  typedef typename TMattesMutualInformationMetric::JointPDFDerivativesType        JointPDFDerivativesType;
  typedef typename TMattesMutualInformationMetric::JointPDFDerivativesIndexType   JointPDFDerivativesIndexType;
  typedef typename TMattesMutualInformationMetric::JointPDFDerivativesValueType   JointPDFDerivativesValueType;
  typedef typename TMattesMutualInformationMetric::JointPDFDerivativesRegionType  JointPDFDerivativesRegionType;
  typedef typename TMattesMutualInformationMetric::JointPDFDerivativesSizeType    JointPDFDerivativesSizeType;

  typedef typename TMattesMutualInformationMetric::CubicBSplineFunctionType            CubicBSplineFunctionType;
  typedef typename TMattesMutualInformationMetric::CubicBSplineDerivativeFunctionType  CubicBSplineDerivativeFunctionType;

  typedef typename TMattesMutualInformationMetric::JacobianType             JacobianType;

protected:
  MattesMutualInformationImageToImageMetricv4GetValueAndDerivativeThreader() {}

  virtual void BeforeThreadedExecution();

  virtual void AfterThreadedExecution();

  /** This function computes the local voxel-wise contribution of
   *  the metric to the global integral of the metric/derivative.
   */
  virtual bool ProcessPoint(
        const VirtualIndexType &          virtualIndex,
        const VirtualPointType &          virtualPoint,
        const FixedImagePointType &       mappedFixedPoint,
        const FixedImagePixelType &       mappedFixedPixelValue,
        const FixedImageGradientType &    mappedFixedImageGradient,
        const MovingImagePointType &      mappedMovingPoint,
        const MovingImagePixelType &      mappedMovingPixelValue,
        const MovingImageGradientType &   mappedMovingImageGradient,
        MeasureType &                     metricValueReturn,
        DerivativeType &                  localDerivativeReturn,
        const ThreadIdType                threadID ) const;

  /** Compute PDF derivative contribution for each parameter. */
  virtual void ComputePDFDerivatives(const ThreadIdType &    threadID,
                             const OffsetValueType &         fixedImageParzenWindowIndex,
                             const JacobianType &            jacobian,
                             const OffsetValueType &         pdfMovingIndex,
                             const MovingImageGradientType & movingGradient,
                             const PDFValueType &            cubicBSplineDerivativeValue,
                             DerivativeValueType *           localSupportDerivativeResultPtr) const;

private:
  MattesMutualInformationImageToImageMetricv4GetValueAndDerivativeThreader( const Self & ); // purposely not implemented
  void operator=( const Self & ); // purposely not implemented
};

} // end namespace itk

#ifndef ITK_MANUAL_INSTANTIATION
#include "itkMattesMutualInformationImageToImageMetricv4GetValueAndDerivativeThreader.hxx"
#endif

#endif


text:
package us.kbase.catalog;

import java.util.HashMap;
import java.util.Map;
import javax.annotation.Generated;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

/**
 *
Original spec-file type: ListReposParams

 *

 * Describes how to filter repositories.
 * with_disabled - optional flag adding disabled repos (default value is false).
 *

 *
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("com.googlecode.jsonschema2pojo")
@JsonPropertyOrder({
    "with_disabled"
})
public class ListReposParams {

    @JsonProperty("with_disabled")
    private Long withDisabled;
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    @JsonProperty("with_disabled")
    public Long getWithDisabled() {
        return withDisabled;
    }

    @JsonProperty("with_disabled")
    public void setWithDisabled(Long withDisabled) {
        this.withDisabled = withDisabled;
    }

    public ListReposParams withWithDisabled(Long withDisabled) {
        this.withDisabled = withDisabled;
        return this;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperties(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

    @Override
    public String toString() {
        return ((((("ListReposParams"+" [withDisabled=")+ withDisabled)+", additionalProperties=")+ additionalProperties)+"]");
    }

}

redpajama_set_name: RedPajamaGithub


text:
package exts

import (
	"encoding/json"
	"errors"
	"sync"
	"sync/atomic"
	"time"
)

var (
	ErrorInvocationTimeout = errors.New("Invocation timeout")
	ErrorInvocationAborted = errors.New("Invocation aborted")
)

type InvokeOptions struct {
	Timeout time.Duration
	Reply   *Message
}

type Invoker interface {
	Invoke(action string, payload RawMessage, timeout time.Duration) (RawMessage, error)
	Notify(event string, payload RawMessage) error
}

type InvokeHelper struct {
	Invoker Invoker
	Action  string
	Payload RawMessage
	Timeout time.Duration
	Reply   RawMessage
	Error   error
}

func InvokeHelp(invoker Invoker) *InvokeHelper {
	return &InvokeHelper{Invoker: invoker}
}

func (v *InvokeHelper) WithAction(action string) *InvokeHelper {
	v.Action = action
	return v
}

func (v *InvokeHelper) WithPayload(payload RawMessage) *InvokeHelper {
	v.Payload = payload
	return v
}

func (v *InvokeHelper) Marshal(payload interface{}) *InvokeHelper {
	if data, err := json.Marshal(payload); err != nil {
		panic(err)
	} else {
		v.Payload = data
	}
	return v
}

func (v *InvokeHelper) WithTimeout(timeout time.Duration) *InvokeHelper {
	v.Timeout = timeout
	return v
}

func (v *InvokeHelper) Invoke() *InvokeHelper {
	v.Reply, v.Error = v.Invoker.Invoke(v.Action, v.Payload, v.Timeout)
	return v
}

func (v *InvokeHelper) Unmarshal(d interface{}) error {
	if v.Error != nil {
		return v.Error
	}
	return json.Unmarshal(v.Reply, d)
}

func (v *InvokeHelper) Result() (RawMessage, error) {
	return v.Reply, v.Error
}

func (v *InvokeHelper) Succeeded() bool {
	return v.Error == nil
}

type NotifyHelper struct {
	Invoker Invoker
	Event   string
	Payload RawMessage
}

func NotifyHelp(invoker Invoker) *NotifyHelper {
	return &NotifyHelper{Invoker: invoker}
}

func (v *NotifyHelper) WithEvent(event string) *NotifyHelper {
	v.Event = event
	return v
}

func (v *NotifyHelper) WithPayload(payload RawMessage) *NotifyHelper {
	v.Payload = payload
	return v
}

func (v *NotifyHelper) Marshal(payload interface{}) *NotifyHelper {
	if data, err := json.Marshal(payload); err != nil {
		panic(err)
	} else {
		v.Payload = data
	}
	return v
}

func (v *NotifyHelper) Notify() error {
	return v.Invoker.Notify(v.Event, v.Payload)
}

type PipeInvoker struct {
	Pipe MessagePipe
}

func (v *PipeInvoker) Invoke(action string, payload RawMessage, timeout time.Duration) (RawMessage, error) {
	option := &InvokeOptions{Timeout: timeout}
	err := v.Pipe.Send(&Message{
		Event: MsgInvoke,
		Name:  action,
		Data:  json.RawMessage(payload),
	}, option)
	if option.Reply == nil {
		return nil, err
	}
	if err == nil && option.Reply.Error != "" {
		err = errors.New(option.Reply.Error)
	}
	return RawMessage(option.Reply.Data), err
}

func (v *PipeInvoker) Notify(event string, payload RawMessage) error {
	return v.Pipe.Send(&Message{
		Event: MsgNotify,
		Name:  event,
		Data:  json.RawMessage(payload),
	})
}

type InvokerPipe struct {
	Pipe MessagePipe

	invocations map[uint32]chan *Message
	lock        sync.RWMutex
	id          uint32
}

func NewInvokerPipe(source MessagePipe) *InvokerPipe {
	return &InvokerPipe{
		Pipe:        source,
		invocations: make(map[uint32]chan *Message),
	}
}

func (v *InvokerPipe) Recv() (*Message, error) {
	for {
		msg, err := v.Pipe.Recv()
		if err != nil || msg == nil || msg.Event != MsgReply {
			return msg, err
		}
		v.lock.RLock()
		replyCh := v.invocations[msg.Id]
		if replyCh != nil {
			delete(v.invocations, msg.Id)
		}
		v.lock.RUnlock()
		if replyCh != nil {
			replyCh <- msg
		} else {
			return msg, err
		}
	}
}

func (v *InvokerPipe) Send(msg *Message, options ...interface{}) error {
	if msg.Event == MsgInvoke {
		var option *InvokeOptions = nil
		for n, opt := range options {
			if o, ok := opt.(*InvokeOptions); ok {
				option = o
				options = append(options[0:n], options[n+1:]...)
				break
			}
		}

		id := atomic.AddUint32(&v.id, 1)
		msg.Id = id

		reply := make(chan *Message)
		v.lock.Lock()
		v.invocations[id] = reply
		v.lock.Unlock()

		defer func() {
			v.lock.Lock()
			delete(v.invocations, id)
			v.lock.Unlock()
		}()

		if err := v.Pipe.Send(msg, options...); err != nil {
			return err
		}

		var timeCh <-chan time.Time
		if option != nil && option.Timeout > 0 {
			timeCh = time.NewTimer(option.Timeout).C
		} else {
			timeCh = make(chan time.Time)
		}
		select {
		case <-timeCh:
			return ErrorInvocationTimeout
		case msg, ok := (<-reply):
			if !ok {
				return ErrorInvocationAborted
			} else if option != nil {
				option.Reply = msg
			}
		}
		return nil
	}
	return v.Pipe.Send(msg, options...)
}

func (v *InvokerPipe) Close() error {
	v.lock.Lock()
	for _, reply := range v.invocations {
		close(reply)
	}
	v.invocations = make(map[uint32]chan *Message)
	v.lock.Unlock()
	return v.Pipe.Close()
}

func (v *InvokerPipe) Invoke(action string, payload RawMessage, timeout time.Duration) (RawMessage, error) {
	return (&PipeInvoker{v}).Invoke(action, payload, timeout)
}

func (v *InvokerPipe) Notify(event string, payload RawMessage) error {
	return (&PipeInvoker{v}).Notify(event, payload)
}


text:
package org.scalajs.linker.interface

import scala.concurrent._

import java.net.URI
import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets.UTF_8

import org.scalajs.logging.Logger

import org.scalajs.linker.interface.unstable.{OutputDirectoryImpl, OutputFileImpl}

/** Backwards compatibility implementation for pre 1.3.0 link method.
 *
 *  The major interface change in 1.3.0 is that the linker (and not the
 *  caller) determines the set of files to be written. As a consequence, the
 *  post 1.3.0 API does not offer as much control over cross-file references
 *  (i.e. source map links): it is based on patterns rather than simply
 *  asking the caller to verbatim provide the URI to reference in each file.
 *
 *  To provide a backwards compatible interface, we do the following post-run
 *  processing:
 *
 *  - Match and copy the produced set of files (in the OutputDirectory) to
 *    the files provided by the caller (in LinkerOutput).
 *  - Replace the pattern generated cross-file references with the ones
 *    provided by the caller. This is necessary as a post-processing step,
 *    because of the reduced flexibility of the 1.3.0 API: we cannot express
 *    all legacy requests in the new API.
  */
@deprecated("Part of legacy API.", "1.3.0")
object ReportToLinkerOutputAdapter {
  final class UnsupportedLinkerOutputException private[ReportToLinkerOutputAdapter] (
      message: String) extends IllegalArgumentException(message)

  def convert(report: Report, outputDirectory: OutputDirectory,
      legacyOutput: LinkerOutput)(
      implicit ec: ExecutionContext): Future[Unit] = {
    report.publicModules.toList match {
      case Nil =>
        writeEmptyOutput(legacyOutput)

      case List(module) =>
        retrieveOutputFiles(module, outputDirectory)
          .flatMap(writePatchedOutput(_, legacyOutput))

      case _ =>
        throw new UnsupportedLinkerOutputException(
            "Linking returned more than one public module. Full report:\n" +
            report)
      }
  }

  private def writeEmptyOutput(legacyOutput: LinkerOutput)(
      implicit ec: ExecutionContext): Future[Unit] = {
    legacyOutput.sourceMap.fold {
      writeString(legacyOutput.jsFile, "")
    } { sourceMapFile =>
      val smFields = List(
          "version" -> "3",
          "mappings" -> "\"\"",
          "sources" -> "[]",
          "names" -> "[]",
          "lineCount" -> "1"
      ) ++ legacyOutput.jsFileURI.map(uri =>
          "file" -> s""""${uri.toASCIIString}"""")

      val jsContent = legacyOutput.sourceMapURI.fold("")(uri =>
          s"//# sourceMappingURL=${uri.toASCIIString}\n")

      val smContent = smFields
        .map { case (n, v) => s""""$n": $v""" }
        .mkString("{\n", ",\n", "\n}")

      writeString(legacyOutput.jsFile, jsContent)
        .flatMap(_ => writeString(sourceMapFile, smContent))
    }
  }

  private def writePatchedOutput(output: (ByteBuffer, Option[ByteBuffer]),
      legacyOutput: LinkerOutput)(implicit ec: ExecutionContext): Future[Unit] = {
    val (jsFileContent, optSourceMapContent) = output

    val hasSourceMap =
      optSourceMapContent.isDefined && legacyOutput.sourceMap.isDefined

    val jsFileWrite = {
      val content = UTF_8.decode(jsFileContent).toString()
      val patched = patchJSFileContent(content,
          legacyOutput.sourceMapURI.filter(_ => hasSourceMap))
      writeString(legacyOutput.jsFile, patched)
    }

    val sourceMapWrite = for {
      sourceMapContent <- optSourceMapContent
      sourceMapFile <- legacyOutput.sourceMap
    } yield {
      val content = UTF_8.decode(sourceMapContent).toString()
      val patched = patchSourceMapContent(content, legacyOutput.jsFileURI)
      writeString(sourceMapFile, patched)
    }

    Future.sequence(List(jsFileWrite) ++ sourceMapWrite).map(_ => ())
  }

  /** Retrieve the linker JS file and an optional source map */
  private def retrieveOutputFiles(module: Report.Module,
      outputDirectory: OutputDirectory)(
      implicit ec: ExecutionContext): Future[(ByteBuffer, Option[ByteBuffer])] = {
    val outDirImpl = OutputDirectoryImpl.fromOutputDirectory(outputDirectory)

    val checkFiles = for {
      foundFilesList <- outDirImpl.listFiles()
    } yield {
      val foundFiles = foundFilesList.toSet
      val expectedFiles = Set(module.jsFileName) ++ module.sourceMapName

      if (foundFiles != expectedFiles) {
        if (expectedFiles.subsetOf(foundFiles)) {
          throw new UnsupportedLinkerOutputException(
              "Linking produced more than a single JS file (and source map). " +
              s"Expected files:\n$expectedFiles\nProduced files:\n$foundFiles")
        } else {
          throw new AssertionError(
              "Linking did not produce the files mentioned in the report. " +
              "This is a bug in the linker. " +
              s"Expected files:\n$expectedFiles\nProduced files:\n$foundFiles")
        }
      }
    }

    for {
      _ <- checkFiles
      jsFileContent <- outDirImpl.readFull(module.jsFileName)
      sourceMapContent <- Future.traverse(module.sourceMapName.toList)(outDirImpl.readFull(_))
    } yield {
      (jsFileContent, sourceMapContent.headOption)
    }
  }

  /* This regex would normally be written with the (?m) flag, but that would
   * require ES2018, so we work around it.
   */
  private val sourceMapRe = """(?:^|\n)(//# sourceMappingURL=[^\n]*)(?:\n|$)""".r

  /** Patches the JS file content to have the provided source map link (or none)
   *
   *  Looks for a line of the form `//# sourceMappingURL=.*` and replaces the
   *  URL with the provided `sourceMapURI`. In case `sourceMapURI` is None, the
   *  line is replaced with an empty line.
   */
  private def patchJSFileContent(content: String,
      sourceMapURI: Option[URI]): String = {

    val newLine =
      sourceMapURI.map(u => s"//# sourceMappingURL=${u.toASCIIString}")

    sourceMapRe.findFirstMatchIn(content).fold {
      content + newLine.fold("")("\n" + _ + "\n")
    } { reMatch =>
      val res = new StringBuilder

      res.append(reMatch.before(1))

      /* If there is no source map link, keep an empty line to not break a
       * potential (unlinked) source map
       */
      newLine.foreach(res.append(_))

      res.append(reMatch.after(1))

      res.toString()
    }
  }

  /* It is somewhat acceptable to parse the JSON field "file" with a Regex
   * because:
   *
   * - Source maps do not contain nested objects.
   * - The file URI should not contain '"', because URI.toASCIIString (which is
   *   used by the StandardLinker) never returns them.
   *
   * So as a legacy mechanism, this is OK-ish. It keeps us from having to build
   * the infrastructure to parse JSON cross platform.
   */
  private val fileFieldRe = """([,{])\s*"file"\s*:\s*"[^"]*"\s*([,}])""".r

  /** Patches the source map content to have the provided JS file link (or none).
   *
   *  Looks for a `"file":` key in the top-level source map JSON object and
   *  replaces it's value with `jsFileURI`. In case `jsFileURI` is None, it
   *  removes the key from the object.
   */
  private def patchSourceMapContent(content: String,
      jsFileURI: Option[URI]): String = {

    // No need for quoting: toASCIIString never returns '"'
    val newField =
      jsFileURI.map(u => s""""file": "${u.toASCIIString}"""")

    fileFieldRe.findFirstMatchIn(content).fold {
      newField.fold(content) { field =>
        content.split("\\{", 2) match {
          case Array(pre, post) =>
            pre + "{" + field + "," + post

          case _ =>
            throw new IllegalArgumentException(
                s"source map file does not seem to contain a JSON object: $content")
        }
      }
    } { reMatch =>
      val res = new StringBuilder

      res.append(reMatch.before)

      newField match {
        case None =>
          if (reMatch.group(1) == "{")
            res.append('{')
          if (reMatch.group(2) == "}")
            res.append('}')
        case Some(field) =>
          res.append(reMatch.group(1))
          res.append(field)
          res.append(reMatch.group(2))
      }

      res.append(reMatch.after)

      res.toString()
    }
  }

  private def writeString(outputFile: LinkerOutput.File, content: String)(
      implicit ec: ExecutionContext): Future[Unit] = {
    OutputFileImpl.fromOutputFile(outputFile)
      .writeFull(ByteBuffer.wrap(content.getBytes(UTF_8)))
  }
}


text:
#ifndef _ITTNOTIFY_CONFIG_H_
#define _ITTNOTIFY_CONFIG_H_

/** @cond exclude_from_documentation */
#ifndef ITT_OS_WIN
#  define ITT_OS_WIN   1
#endif /* ITT_OS_WIN */

#ifndef ITT_OS_LINUX
#  define ITT_OS_LINUX 2
#endif /* ITT_OS_LINUX */

#ifndef ITT_OS_MAC
#  define ITT_OS_MAC   3
#endif /* ITT_OS_MAC */

#ifndef ITT_OS_FREEBSD
#  define ITT_OS_FREEBSD   4
#endif /* ITT_OS_FREEBSD */

#ifndef ITT_OS
#  if defined WIN32 || defined _WIN32
#    define ITT_OS ITT_OS_WIN
#  elif defined( __APPLE__ ) && defined( __MACH__ )
#    define ITT_OS ITT_OS_MAC
#  elif defined( __FreeBSD__ )
#    define ITT_OS ITT_OS_FREEBSD
#  else
#    define ITT_OS ITT_OS_LINUX
#  endif
#endif /* ITT_OS */

#ifndef ITT_PLATFORM_WIN
#  define ITT_PLATFORM_WIN 1
#endif /* ITT_PLATFORM_WIN */

#ifndef ITT_PLATFORM_POSIX
#  define ITT_PLATFORM_POSIX 2
#endif /* ITT_PLATFORM_POSIX */

#ifndef ITT_PLATFORM_MAC
#  define ITT_PLATFORM_MAC 3
#endif /* ITT_PLATFORM_MAC */

#ifndef ITT_PLATFORM_FREEBSD
#  define ITT_PLATFORM_FREEBSD 4
#endif /* ITT_PLATFORM_FREEBSD */

#ifndef ITT_PLATFORM
#  if ITT_OS==ITT_OS_WIN
#    define ITT_PLATFORM ITT_PLATFORM_WIN
#  elif ITT_OS==ITT_OS_MAC
#    define ITT_PLATFORM ITT_PLATFORM_MAC
#  elif ITT_OS==ITT_OS_FREEBSD
#    define ITT_PLATFORM ITT_PLATFORM_FREEBSD
#  else
#    define ITT_PLATFORM ITT_PLATFORM_POSIX
#  endif
#endif /* ITT_PLATFORM */

#if defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif

#include <stddef.h>
#if ITT_PLATFORM==ITT_PLATFORM_WIN
#include <tchar.h>
#else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#include <stdint.h>
#if defined(UNICODE) || defined(_UNICODE)
#include <wchar.h>
#endif /* UNICODE || _UNICODE */
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */

#ifndef ITTAPI_CDECL
#  if ITT_PLATFORM==ITT_PLATFORM_WIN
#    define ITTAPI_CDECL __cdecl
#  else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#    if defined _M_IX86 || defined __i386__
#      define ITTAPI_CDECL __attribute__ ((cdecl))
#    else  /* _M_IX86 || __i386__ */
#      define ITTAPI_CDECL /* actual only on x86 platform */
#    endif /* _M_IX86 || __i386__ */
#  endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#endif /* ITTAPI_CDECL */

#ifndef STDCALL
#  if ITT_PLATFORM==ITT_PLATFORM_WIN
#    define STDCALL __stdcall
#  else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#    if defined _M_IX86 || defined __i386__
#      define STDCALL __attribute__ ((stdcall))
#    else  /* _M_IX86 || __i386__ */
#      define STDCALL /* supported only on x86 platform */
#    endif /* _M_IX86 || __i386__ */
#  endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#endif /* STDCALL */

#define ITTAPI    ITTAPI_CDECL
#define LIBITTAPI ITTAPI_CDECL

/* TODO: Temporary for compatibility! */
#define ITTAPI_CALL    ITTAPI_CDECL
#define LIBITTAPI_CALL ITTAPI_CDECL

#if ITT_PLATFORM==ITT_PLATFORM_WIN
/* use __forceinline (VC++ specific) */
#define ITT_INLINE           __forceinline
#define ITT_INLINE_ATTRIBUTE /* nothing */
#else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
/*
 * Generally, functions are not inlined unless optimization is specified.
 * For functions declared inline, this attribute inlines the function even
 * if no optimization level was specified.
 */
#ifdef __STRICT_ANSI__
#define ITT_INLINE           static
#define ITT_INLINE_ATTRIBUTE __attribute__((unused))
#else  /* __STRICT_ANSI__ */
#define ITT_INLINE           static inline
#define ITT_INLINE_ATTRIBUTE __attribute__((always_inline, unused))
#endif /* __STRICT_ANSI__ */
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
/** @endcond */

#ifndef ITT_ARCH_IA32
#  define ITT_ARCH_IA32  1
#endif /* ITT_ARCH_IA32 */

#ifndef ITT_ARCH_IA32E
#  define ITT_ARCH_IA32E 2
#endif /* ITT_ARCH_IA32E */

#ifndef ITT_ARCH_ARM
#  define ITT_ARCH_ARM  4
#endif /* ITT_ARCH_ARM */

#ifndef ITT_ARCH_PPC64
#  define ITT_ARCH_PPC64  5
#endif /* ITT_ARCH_PPC64 */

#ifndef ITT_ARCH
#  if defined _M_IX86 || defined __i386__
#    define ITT_ARCH ITT_ARCH_IA32
#  elif defined _M_X64 || defined _M_AMD64 || defined __x86_64__
#    define ITT_ARCH ITT_ARCH_IA32E
#  elif defined _M_IA64 || defined __ia64__
#    define ITT_ARCH ITT_ARCH_IA64
#  elif defined _M_ARM || defined __arm__
#    define ITT_ARCH ITT_ARCH_ARM
#  elif defined __powerpc64__
#    define ITT_ARCH ITT_ARCH_PPC64
#  endif
#endif

#ifdef __cplusplus
#  define ITT_EXTERN_C extern "C"
#  define ITT_EXTERN_C_BEGIN extern "C" {
#  define ITT_EXTERN_C_END }
#else
#  define ITT_EXTERN_C /* nothing */
#  define ITT_EXTERN_C_BEGIN /* nothing */
#  define ITT_EXTERN_C_END /* nothing */
#endif /* __cplusplus */

#define ITT_TO_STR_AUX(x) #x
#define ITT_TO_STR(x)     ITT_TO_STR_AUX(x)

#define __ITT_BUILD_ASSERT(expr, suffix) do { \
    static char __itt_build_check_##suffix[(expr) ? 1 : -1]; \
    __itt_build_check_##suffix[0] = 0; \
} while(0)
#define _ITT_BUILD_ASSERT(expr, suffix)  __ITT_BUILD_ASSERT((expr), suffix)
#define ITT_BUILD_ASSERT(expr)           _ITT_BUILD_ASSERT((expr), __LINE__)

#define ITT_MAGIC { 0xED, 0xAB, 0xAB, 0xEC, 0x0D, 0xEE, 0xDA, 0x30 }

/* Replace with snapshot date YYYYMMDD for promotion build. */
#define API_VERSION_BUILD    20151119

#ifndef API_VERSION_NUM
#define API_VERSION_NUM 0.0.0
#endif /* API_VERSION_NUM */

#define API_VERSION "ITT-API-Version " ITT_TO_STR(API_VERSION_NUM) \
                                " (" ITT_TO_STR(API_VERSION_BUILD) ")"

/* OS communication functions */
#if ITT_PLATFORM==ITT_PLATFORM_WIN
#include <windows.h>
typedef HMODULE           lib_t;
typedef DWORD             TIDT;
typedef CRITICAL_SECTION  mutex_t;
#define MUTEX_INITIALIZER { 0 }
#define strong_alias(name, aliasname) /* empty for Windows */
#else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
#include <dlfcn.h>
#if defined(UNICODE) || defined(_UNICODE)
#include <wchar.h>
#endif /* UNICODE */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1 /* need for PTHREAD_MUTEX_RECURSIVE */
#endif /* _GNU_SOURCE */
#ifndef __USE_UNIX98
#define __USE_UNIX98 1 /* need for PTHREAD_MUTEX_RECURSIVE, on SLES11.1 with gcc 4.3.4 wherein pthread.h missing dependency on __USE_XOPEN2K8 */
#endif /*__USE_UNIX98*/
#include <pthread.h>
typedef void*             lib_t;
typedef pthread_t         TIDT;
typedef pthread_mutex_t   mutex_t;
#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define _strong_alias(name, aliasname) \
            extern __typeof (name) aliasname __attribute__ ((alias (#name)));
#define strong_alias(name, aliasname) _strong_alias(name, aliasname)
#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */

#if ITT_PLATFORM==ITT_PLATFORM_WIN
#define __itt_get_proc(lib, name) GetProcAddress(lib, name)
#define __itt_mutex_init(mutex)   InitializeCriticalSection(mutex)
#define __itt_mutex_lock(mutex)   EnterCriticalSection(mutex)
#define __itt_mutex_unlock(mutex) LeaveCriticalSection(mutex)
#define __itt_load_lib(name)      LoadLibraryA(name)
#define __itt_unload_lib(handle)  FreeLibrary(handle)
#define __itt_system_error()      (int)GetLastError()
#define __itt_fstrcmp(s1, s2)     lstrcmpA(s1, s2)
#define __itt_fstrnlen(s, l)      strnlen_s(s, l)
#define __itt_fstrcpyn(s1, b, s2, l) strncpy_s(s1, b, s2, l)
#define __itt_fstrdup(s)          _strdup(s)
#define __itt_thread_id()         GetCurrentThreadId()
#define __itt_thread_yield()      SwitchToThread()
#ifndef ITT_SIMPLE_INIT
ITT_INLINE long
__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE;
ITT_INLINE long __itt_interlocked_increment(volatile long* ptr)
{
    return InterlockedIncrement(ptr);
}
#endif /* ITT_SIMPLE_INIT */

#define DL_SYMBOLS (1)
#define PTHREAD_SYMBOLS (1)

#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */
#define __itt_get_proc(lib, name) dlsym(lib, name)
#define __itt_mutex_init(mutex)   {\
    pthread_mutexattr_t mutex_attr;                                         \
    int error_code = pthread_mutexattr_init(&mutex_attr);                   \
    if (error_code)                                                         \
        __itt_report_error(__itt_error_system, "pthread_mutexattr_init",    \
                           error_code);                                     \
    error_code = pthread_mutexattr_settype(&mutex_attr,                     \
                                           PTHREAD_MUTEX_RECURSIVE);        \
    if (error_code)                                                         \
        __itt_report_error(__itt_error_system, "pthread_mutexattr_settype", \
                           error_code);                                     \
    error_code = pthread_mutex_init(mutex, &mutex_attr);                    \
    if (error_code)                                                         \
        __itt_report_error(__itt_error_system, "pthread_mutex_init",        \
                           error_code);                                     \
    error_code = pthread_mutexattr_destroy(&mutex_attr);                    \
    if (error_code)                                                         \
        __itt_report_error(__itt_error_system, "pthread_mutexattr_destroy", \
                           error_code);                                     \
}
#define __itt_mutex_lock(mutex)   pthread_mutex_lock(mutex)
#define __itt_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
#define __itt_load_lib(name)      dlopen(name, RTLD_LAZY)
#define __itt_unload_lib(handle)  dlclose(handle)
#define __itt_system_error()      errno
#define __itt_fstrcmp(s1, s2)     strcmp(s1, s2)

/* makes customer code define safe APIs for SDL_STRNLEN_S and SDL_STRNCPY_S */
#ifdef SDL_STRNLEN_S
#define __itt_fstrnlen(s, l)      SDL_STRNLEN_S(s, l)
#else
#define __itt_fstrnlen(s, l)      strlen(s)
#endif /* SDL_STRNLEN_S */
#ifdef SDL_STRNCPY_S
#define __itt_fstrcpyn(s1, b, s2, l) SDL_STRNCPY_S(s1, b, s2, l)
#else
#define __itt_fstrcpyn(s1, b, s2, l) strncpy(s1, s2, l)
#endif /* SDL_STRNCPY_S */

#define __itt_fstrdup(s)          strdup(s)
#define __itt_thread_id()         pthread_self()
#define __itt_thread_yield()      sched_yield()
#if ITT_ARCH==ITT_ARCH_IA64
#ifdef __INTEL_COMPILER
#define __TBB_machine_fetchadd4(addr, val) __fetchadd4_acq((void *)addr, val)
#else  /* __INTEL_COMPILER */
/* TODO: Add Support for not Intel compilers for IA-64 architecture */
#endif /* __INTEL_COMPILER */
#elif ITT_ARCH==ITT_ARCH_IA32 || ITT_ARCH==ITT_ARCH_IA32E /* ITT_ARCH!=ITT_ARCH_IA64 */
ITT_INLINE long
__TBB_machine_fetchadd4(volatile void* ptr, long addend) ITT_INLINE_ATTRIBUTE;
ITT_INLINE long __TBB_machine_fetchadd4(volatile void* ptr, long addend)
{
    long result;
    __asm__ __volatile__("lock\nxadd %0,%1"
                          : "=r"(result),"=m"(*(int*)ptr)
                          : "0"(addend), "m"(*(int*)ptr)
                          : "memory");
    return result;
}
#elif ITT_ARCH==ITT_ARCH_ARM || ITT_ARCH==ITT_ARCH_PPC64
#define __TBB_machine_fetchadd4(addr, val) __sync_fetch_and_add(addr, val)
#endif /* ITT_ARCH==ITT_ARCH_IA64 */
#ifndef ITT_SIMPLE_INIT
ITT_INLINE long
__itt_interlocked_increment(volatile long* ptr) ITT_INLINE_ATTRIBUTE;
ITT_INLINE long __itt_interlocked_increment(volatile long* ptr)
{
    return __TBB_machine_fetchadd4(ptr, 1) + 1L;
}
#endif /* ITT_SIMPLE_INIT */

void* dlopen(const char*, int) __attribute__((weak));
void* dlsym(void*, const char*) __attribute__((weak));
int dlclose(void*) __attribute__((weak));
#define DL_SYMBOLS (dlopen && dlsym && dlclose)

int pthread_mutex_init(pthread_mutex_t*, const pthread_mutexattr_t*) __attribute__((weak));
int pthread_mutex_lock(pthread_mutex_t*) __attribute__((weak));
int pthread_mutex_unlock(pthread_mutex_t*) __attribute__((weak));
int pthread_mutex_destroy(pthread_mutex_t*) __attribute__((weak));
int pthread_mutexattr_init(pthread_mutexattr_t*) __attribute__((weak));
int pthread_mutexattr_settype(pthread_mutexattr_t*, int) __attribute__((weak));
int pthread_mutexattr_destroy(pthread_mutexattr_t*) __attribute__((weak));
pthread_t pthread_self(void) __attribute__((weak));
#define PTHREAD_SYMBOLS (pthread_mutex_init && pthread_mutex_lock && pthread_mutex_unlock && pthread_mutex_destroy && pthread_mutexattr_init && pthread_mutexattr_settype && pthread_mutexattr_destroy && pthread_self)

#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */

typedef enum {
    __itt_collection_normal = 0,
    __itt_collection_paused = 1
} __itt_collection_state;

typedef enum {
    __itt_thread_normal  = 0,
    __itt_thread_ignored = 1
} __itt_thread_state;

#pragma pack(push, 8)

typedef struct ___itt_thread_info
{
    const char* nameA; /*!< Copy of original name in ASCII. */
#if defined(UNICODE) || defined(_UNICODE)
    const wchar_t* nameW; /*!< Copy of original name in UNICODE. */
#else  /* UNICODE || _UNICODE */
    void* nameW;
#endif /* UNICODE || _UNICODE */
    TIDT               tid;
    __itt_thread_state state;   /*!< Thread state (paused or normal) */
    int                extra1;  /*!< Reserved to the runtime */
    void*              extra2;  /*!< Reserved to the runtime */
    struct ___itt_thread_info* next;
} __itt_thread_info;

#include "ittnotify_types.h" /* For __itt_group_id definition */

typedef struct ___itt_api_info_20101001
{
    const char*    name;
    void**         func_ptr;
    void*          init_func;
    __itt_group_id group;
}  __itt_api_info_20101001;

typedef struct ___itt_api_info
{
    const char*    name;
    void**         func_ptr;
    void*          init_func;
    void*          null_func;
    __itt_group_id group;
}  __itt_api_info;

typedef struct __itt_counter_info
{
    const char* nameA;  /*!< Copy of original name in ASCII. */
#if defined(UNICODE) || defined(_UNICODE)
    const wchar_t* nameW; /*!< Copy of original name in UNICODE. */
#else  /* UNICODE || _UNICODE */
    void* nameW;
#endif /* UNICODE || _UNICODE */
    const char* domainA;  /*!< Copy of original name in ASCII. */
#if defined(UNICODE) || defined(_UNICODE)
    const wchar_t* domainW; /*!< Copy of original name in UNICODE. */
#else  /* UNICODE || _UNICODE */
    void* domainW;
#endif /* UNICODE || _UNICODE */
    int type;
    long index;
    int   extra1; /*!< Reserved to the runtime */
    void* extra2; /*!< Reserved to the runtime */
    struct __itt_counter_info* next;
}  __itt_counter_info_t;

struct ___itt_domain;
struct ___itt_string_handle;

typedef struct ___itt_global
{
    unsigned char          magic[8];
    unsigned long          version_major;
    unsigned long          version_minor;
    unsigned long          version_build;
    volatile long          api_initialized;
    volatile long          mutex_initialized;
    volatile long          atomic_counter;
    mutex_t                mutex;
    lib_t                  lib;
    void*                  error_handler;
    const char**           dll_path_ptr;
    __itt_api_info*        api_list_ptr;
    struct ___itt_global*  next;
    /* Joinable structures below */
    __itt_thread_info*     thread_list;
    struct ___itt_domain*  domain_list;
    struct ___itt_string_handle* string_list;
    __itt_collection_state state;
    __itt_counter_info_t* counter_list;
} __itt_global;

#pragma pack(pop)

#define NEW_THREAD_INFO_W(gptr,h,h_tail,t,s,n) { \
    h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \
    if (h != NULL) { \
        h->tid    = t; \
        h->nameA  = NULL; \
        h->nameW  = n ? _wcsdup(n) : NULL; \
        h->state  = s; \
        h->extra1 = 0;    /* reserved */ \
        h->extra2 = NULL; /* reserved */ \
        h->next   = NULL; \
        if (h_tail == NULL) \
            (gptr)->thread_list = h; \
        else \
            h_tail->next = h; \
    } \
}

#define NEW_THREAD_INFO_A(gptr,h,h_tail,t,s,n) { \
    h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \
    if (h != NULL) { \
        h->tid    = t; \
        h->nameA  = n ? __itt_fstrdup(n) : NULL; \
        h->nameW  = NULL; \
        h->state  = s; \
        h->extra1 = 0;    /* reserved */ \
        h->extra2 = NULL; /* reserved */ \
        h->next   = NULL; \
        if (h_tail == NULL) \
            (gptr)->thread_list = h; \
        else \
            h_tail->next = h; \
    } \
}

#define NEW_DOMAIN_W(gptr,h,h_tail,name) { \
    h = (__itt_domain*)malloc(sizeof(__itt_domain)); \
    if (h != NULL) { \
        h->flags  = 1;    /* domain is enabled by default */ \
        h->nameA  = NULL; \
        h->nameW  = name ? _wcsdup(name) : NULL; \
        h->extra1 = 0;    /* reserved */ \
        h->extra2 = NULL; /* reserved */ \
        h->next   = NULL; \
        if (h_tail == NULL) \
            (gptr)->domain_list = h; \
        else \
            h_tail->next = h; \
    } \
}

#define NEW_DOMAIN_A(gptr,h,h_tail,name) { \
    h = (__itt_domain*)malloc(sizeof(__itt_domain)); \
    if (h != NULL) { \
        h->flags  = 1;    /* domain is enabled by default */ \
        h->nameA  = name ? __itt_fstrdup(name) : NULL; \
        h->nameW  = NULL; \
        h->extra1 = 0;    /* reserved */ \
        h->extra2 = NULL; /* reserved */ \
        h->next   = NULL; \
        if (h_tail == NULL) \
            (gptr)->domain_list = h; \
        else \
            h_tail->next = h; \
    } \
}

#define NEW_STRING_HANDLE_W(gptr,h,h_tail,name) { \
    h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \
    if (h != NULL) { \
        h->strA   = NULL; \
        h->strW   = name ? _wcsdup(name) : NULL; \
        h->extra1 = 0;    /* reserved */ \
        h->extra2 = NULL; /* reserved */ \
        h->next   = NULL; \
        if (h_tail == NULL) \
            (gptr)->string_list = h; \
        else \
            h_tail->next = h; \
    } \
}

#define NEW_STRING_HANDLE_A(gptr,h,h_tail,name) { \
    h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \
    if (h != NULL) { \
        h->strA   = name ? __itt_fstrdup(name) : NULL; \
        h->strW   = NULL; \
        h->extra1 = 0;    /* reserved */ \
        h->extra2 = NULL; /* reserved */ \
        h->next   = NULL; \
        if (h_tail == NULL) \
            (gptr)->string_list = h; \
        else \
            h_tail->next = h; \
    } \
}

#define NEW_COUNTER_W(gptr,h,h_tail,name,domain,type) { \
    h = (__itt_counter_info_t*)malloc(sizeof(__itt_counter_info_t)); \
    if (h != NULL) { \
        h->nameA   = NULL; \
        h->nameW   = name ? _wcsdup(name) : NULL; \
        h->domainA   = NULL; \
        h->domainW   = name ? _wcsdup(domain) : NULL; \
        h->type = type; \
        h->index = 0; \
        h->next   = NULL; \
        if (h_tail == NULL) \
            (gptr)->counter_list = h; \
        else \
            h_tail->next = h; \
    } \
}

#define NEW_COUNTER_A(gptr,h,h_tail,name,domain,type) { \
    h = (__itt_counter_info_t*)malloc(sizeof(__itt_counter_info_t)); \
    if (h != NULL) { \
        h->nameA   = name ? __itt_fstrdup(name) : NULL; \
        h->nameW   = NULL; \
        h->domainA   = domain ? __itt_fstrdup(domain) : NULL; \
        h->domainW   = NULL; \
        h->type = type; \
        h->index = 0; \
        h->next   = NULL; \
        if (h_tail == NULL) \
            (gptr)->counter_list = h; \
        else \
            h_tail->next = h; \
    } \
}

#endif /* _ITTNOTIFY_CONFIG_H_ */


text:
<?php
declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

use CollectionJson\Entity\Template;
use CollectionJson\Entity\Data;

$template = (new Template())
    ->withData(new Data('string', ''))
    ->withData(new Data('null', null))
    ->withData(new Data('integer', 0))
    ->withData(new Data('float', 0.2))
    ->withData(new Data('boolean', false))
    ->wrap();

echo json_encode($template, JSON_PRETTY_PRINT);


text:
package com.dangdang.ddframe.job.lite.internal.listener;

import com.dangdang.ddframe.job.lite.api.listener.ElasticJobListener;
import com.dangdang.ddframe.job.lite.internal.config.ConfigurationListenerManager;
import com.dangdang.ddframe.job.lite.internal.election.ElectionListenerManager;
import com.dangdang.ddframe.job.lite.internal.execution.ExecutionListenerManager;
import com.dangdang.ddframe.job.lite.internal.failover.FailoverListenerManager;
import com.dangdang.ddframe.job.lite.internal.guarantee.GuaranteeListenerManager;
import com.dangdang.ddframe.job.lite.internal.server.JobOperationListenerManager;
import com.dangdang.ddframe.job.lite.internal.sharding.ShardingListenerManager;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.unitils.util.ReflectionUtils;

import java.util.Collections;

import static org.mockito.Mockito.verify;

public class ListenerManagerTest {

    @Mock
    private ElectionListenerManager electionListenerManager;

    @Mock
    private ShardingListenerManager shardingListenerManager;

    @Mock
    private ExecutionListenerManager executionListenerManager;

    @Mock
    private FailoverListenerManager failoverListenerManager;

    @Mock
    private JobOperationListenerManager jobOperationListenerManager;

    @Mock
    private ConfigurationListenerManager configurationListenerManager;

    @Mock
    private GuaranteeListenerManager guaranteeListenerManager;

    private final ListenerManager listenerManager = new ListenerManager(null, "test_job", Collections.<ElasticJobListener>emptyList());

    @Before
    public void setUp() throws NoSuchFieldException {
        MockitoAnnotations.initMocks(this);
        ReflectionUtils.setFieldValue(listenerManager, "electionListenerManager", electionListenerManager);
        ReflectionUtils.setFieldValue(listenerManager, "shardingListenerManager", shardingListenerManager);
        ReflectionUtils.setFieldValue(listenerManager, "executionListenerManager", executionListenerManager);
        ReflectionUtils.setFieldValue(listenerManager, "failoverListenerManager", failoverListenerManager);
        ReflectionUtils.setFieldValue(listenerManager, "jobOperationListenerManager", jobOperationListenerManager);
        ReflectionUtils.setFieldValue(listenerManager, "configurationListenerManager", configurationListenerManager);
        ReflectionUtils.setFieldValue(listenerManager, "guaranteeListenerManager", guaranteeListenerManager);
    }

    @Test
    public void assertStartAllListeners() {
        listenerManager.startAllListeners();
        verify(electionListenerManager).start();
        verify(shardingListenerManager).start();
        verify(executionListenerManager).start();
        verify(failoverListenerManager).start();
        verify(jobOperationListenerManager).start();
        verify(configurationListenerManager).start();
        verify(guaranteeListenerManager).start();
    }

    @Test
    public void assertSetCurrentShardingTotalCount() {
        listenerManager.setCurrentShardingTotalCount(10);
        verify(shardingListenerManager).setCurrentShardingTotalCount(10);
    }
}


text:
SUITESPARSE ?= $(realpath $(CURDIR)/..)
export SUITESPARSE

# default is 'library' since there is no demo program
default: library

include ../SuiteSparse_config/SuiteSparse_config.mk

# Compile the C-callable libraries
all: library

# Compile the C-callable libraries only.
library:
	( cd Lib ; $(MAKE) )

# compile the static libraries only
static:
	( cd Lib    ; $(MAKE) static )

# Remove all files not in the original distribution
purge:
	( cd Lib ; $(MAKE) purge )
	( cd Demo ; $(MAKE) purge )

# Remove all files not in the original distribution, except keep the
# compiled libraries.
clean:
	( cd Lib ; $(MAKE) clean )
	( cd Demo ; $(MAKE) clean )

distclean: purge

ccode: all

# install GPUQREngine.  Note that the include files are not installed.
install:
	( cd Lib ; $(MAKE) install )

uninstall:
	( cd Lib ; $(MAKE) uninstall )


text:
package com.pizza.auth;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

}


text:
package de.javakaffee.web.msm.serializer;

import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.catalina.core.StandardContext;
import org.apache.catalina.loader.WebappLoader;

import de.javakaffee.web.msm.JavaSerializationTranscoder;
import de.javakaffee.web.msm.MemcachedBackupSession;
import de.javakaffee.web.msm.MemcachedBackupSessionManager;
import de.javakaffee.web.msm.SessionAttributesTranscoder;
import de.javakaffee.web.msm.TranscoderService;
import de.javakaffee.web.msm.serializer.TestClasses.Address;
import de.javakaffee.web.msm.serializer.TestClasses.Component;
import de.javakaffee.web.msm.serializer.TestClasses.Person;
import de.javakaffee.web.msm.serializer.TestClasses.Person.Gender;
import de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoder;
import de.javakaffee.web.msm.serializer.kryo.KryoTranscoder;

/**
 * A simple benchmark for existing serialization strategies.
 *
 * @author Martin Grotzke
 */
public class Benchmark {

    /*
     * 50000:
     * -- JavaSerializationTranscoder --
Serializing 1000 sessions took 156863 msec.
serialized size is 59016 bytes.
-- JavolutionTranscoder --
Serializing 1000 sessions took 251870 msec.
serialized size is 138374 bytes.
-- KryoTranscoder --
Serializing 1000 sessions took 154816 msec.
serialized size is 70122 bytes.

     */

    public static void main( final String[] args ) throws InterruptedException {

        //Thread.sleep( 1000 );

        final MemcachedBackupSessionManager manager = createManager();

        // some warmup
        final int warmupCycles = 100000;
        warmup( manager, new JavaSerializationTranscoder(), warmupCycles, 100, 3 );
        warmup( manager, new JavolutionTranscoder( Thread.currentThread().getContextClassLoader(), false ), warmupCycles, 100, 3 );
        warmup( manager, new KryoTranscoder(), warmupCycles, 100, 3 );
        recover();

        benchmark( manager, 10, 500, 4 /* 4^4 = 256 */ );
        benchmark( manager, 10, 100, 3 /* 3^3 = 27 */ );
        benchmark( manager, 10, 10, 2 /* 2^2 = 4 */ );

        // Thread.sleep( Integer.MAX_VALUE );
    }

    private static void benchmark( final MemcachedBackupSessionManager manager, final int rounds, final int countPersons,
            final int nodesPerEdge ) throws InterruptedException {
        final Stats javaSerStats = new Stats();
        final Stats javaDeSerStats = new Stats();
        benchmark( manager, new JavaSerializationTranscoder(), javaSerStats, javaDeSerStats, rounds, countPersons, nodesPerEdge );

        recover();

        final Stats javolutionSerStats = new Stats();
        final Stats javolutionDeSerStats = new Stats();
        benchmark( manager, new JavolutionTranscoder( Thread.currentThread().getContextClassLoader(), false ), javolutionSerStats,
                javolutionDeSerStats, rounds, countPersons, nodesPerEdge );

        recover();

        final Stats kryoSerStats = new Stats();
        final Stats kryoDeSerStats = new Stats();
        benchmark( manager, new KryoTranscoder(), kryoSerStats, kryoDeSerStats, rounds, countPersons, nodesPerEdge );

        System.out.println( "Serialization,Size,Ser-Min,Ser-Avg,Ser-Max,Deser-Min,Deser-Avg,Deser-Max");
        System.out.println( toCSV( "Java", javaSerStats, javaDeSerStats ) );
        System.out.println( toCSV( "Javolution", javolutionSerStats, javolutionDeSerStats ) );
        System.out.println( toCSV( "Kryo", kryoSerStats, kryoDeSerStats ) );
    }

    private static String toCSV( final String name, final Stats serStats, final Stats deSerStats ) {
        return  name + "," + serStats.size +","+ minAvgMax( serStats ) + "," + minAvgMax( deSerStats );
    }

    private static String minAvgMax( final Stats stats ) {
        return stats.min +","+ stats.avg +","+ stats.max;
    }

    private static void recover() throws InterruptedException {
        Thread.sleep( 200 );
        System.gc();
        Thread.sleep( 200 );
    }

    private static void benchmark( final MemcachedBackupSessionManager manager, final SessionAttributesTranscoder transcoder,
            final Stats serializationStats,
            final Stats deserializationStats,
            final int rounds, final int countPersons, final int nodesPerEdge ) throws InterruptedException {

        System.out.println( "Running benchmark for " + transcoder.getClass().getSimpleName() + "..." +
        		" (rounds: "+ rounds +", persons: "+ countPersons +", nodes: "+ ((int)Math.pow( nodesPerEdge, nodesPerEdge ) + nodesPerEdge + 1 ) +")" );

        final TranscoderService transcoderService = new TranscoderService( transcoder );

        final MemcachedBackupSession session = createSession( manager, "123456789abcdefghijk987654321", countPersons, nodesPerEdge );
        final byte[] data = transcoderService.serialize( session );
        final int size = data.length;

        for( int r = 0; r < rounds; r++ ) {
            final long start = System.currentTimeMillis();
            for( int i = 0; i < 500; i++ ) {
                transcoderService.serialize( session );
            }
            serializationStats.registerSince( start );
            serializationStats.setSize( size );
        }

        System.gc();
        Thread.sleep( 100 );

        // deserialization
        for( int r = 0; r < rounds; r++ ) {
            final long start = System.currentTimeMillis();
            for( int i = 0; i < 500; i++ ) {
                transcoderService.deserialize( data, manager );
            }
            deserializationStats.registerSince( start );
            deserializationStats.setSize( size );
        }

    }

    private static void warmup( final MemcachedBackupSessionManager manager, final SessionAttributesTranscoder transcoder,
            final int loops, final int countPersons, final int nodesPerEdge )
        throws InterruptedException {

        final TranscoderService transcoderService = new TranscoderService( transcoder );
        final MemcachedBackupSession session = createSession( manager, "123456789abcdefghijk987654321", countPersons, nodesPerEdge );

        System.out.print("Performing warmup for serialization using "+ transcoder.getClass().getSimpleName() +"...");
        final long serWarmupStart = System.currentTimeMillis();
        for( int i = 0; i < loops; i++ ) transcoderService.serialize( session );
        System.out.println(" (" + (System.currentTimeMillis() - serWarmupStart) + " ms)");

        System.out.print("Performing warmup for deserialization...");
        final byte[] data = transcoderService.serialize( session );
        final long deserWarmupStart = System.currentTimeMillis();
        for( int i = 0; i < loops; i++ ) transcoderService.deserialize( data, manager );
        System.out.println(" (" + (System.currentTimeMillis() - deserWarmupStart) + " ms)");

    }

    private static MemcachedBackupSession createSession( final MemcachedBackupSessionManager manager, final String id,
            final int countPersons, final int countNodesPerEdge ) {
        final MemcachedBackupSession session = manager.createEmptySession();
        session.setId( id );
        session.setValid( true );

        session.setAttribute( "stringbuffer", new StringBuffer( "<string\n&buffer/>" ) );
        session.setAttribute( "stringbuilder", new StringBuilder( "<string\n&buffer/>" ) );

        session.setAttribute( "persons", createPersons( countPersons ) );
        session.setAttribute( "mycontainer", new TestClasses.MyContainer() );

        session.setAttribute( "component", createComponents( countNodesPerEdge ) );

        return session;
    }

    private static Component createComponents( final int countNodesPerEdge ) {
        final Component root = new Component( "root" );
        for ( int i = 0; i < countNodesPerEdge; i++ ) {
            final Component node = new Component( "child" + i );
            addChildren( node, countNodesPerEdge );
            root.addChild( node );
        }
        return root;
    }

    private static void addChildren( final Component node, final int count ) {
        for ( int i = 0; i < count; i++ ) {
            node.addChild( new Component( node.getName() + "-" + i ) );
        }
    }

    private static Person[] createPersons( final int countPersons ) {
        final Person[] persons = new Person[countPersons];
        for( int i = 0; i < countPersons; i++ ) {
            final Calendar dateOfBirth = Calendar.getInstance();
            dateOfBirth.set( Calendar.YEAR, dateOfBirth.get( Calendar.YEAR ) - 42 );
            final Person person = TestClasses.createPerson( "Firstname" + i + " Lastname" + i,
                    i % 2 == 0 ? Gender.FEMALE : Gender.MALE,
                        dateOfBirth,
                        "email" + i + "-1@example.org", "email" + i + "-2@example.org", "email" + i + "-3@example.org" );
            person.addAddress( new Address( "route66", "123456", "sincity", "sincountry" ) );

            if ( i > 0 ) {
                person.addFriend( persons[i - 1] );
            }

            persons[i] = person;
        }
        return persons;
    }

    private static MemcachedBackupSessionManager createManager() {
        final MemcachedBackupSessionManager manager = new MemcachedBackupSessionManager();

        final StandardContext container = new StandardContext();
        manager.setContainer( container );

        final WebappLoader webappLoader = new WebappLoader() {
            /**
             * {@inheritDoc}
             */
            @Override
            public ClassLoader getClassLoader() {
                return Thread.currentThread().getContextClassLoader();
            }
        };
        manager.getContainer().setLoader( webappLoader );

        return manager;
    }

    static class Stats {

        long min;
        long max;
        double avg;
        int size;

        private boolean _first = true;
        private final AtomicInteger _count = new AtomicInteger();

        /**
         * A utility method that calculates the difference of the time
         * between the given startInMillis and {@link System#currentTimeMillis()}
         * and registers the difference via {@link #register(long)}.
         * @param startInMillis the time in millis that shall be subtracted from {@link System#currentTimeMillis()}.
         */
        public void registerSince( final long startInMillis ) {
            register( System.currentTimeMillis() - startInMillis );
        }

        public void setSize( final int size ) {
            this.size = size;
        }

        /**
         * Register the given value.
         * @param value the value to register.
         */
        public void register( final long value ) {
            if ( value < min || _first ) {
                min = value;
            }
            if ( value > max || _first ) {
                max = value;
            }
            avg = ( avg * _count.get() + value ) / _count.incrementAndGet();
            _first = false;
        }

        /**
         * Returns a string array with labels and values of count, min, avg and max.
         * @return a String array.
         */
        public String[] getInfo() {
            return new String[] {
                    "Count = " + _count.get(),
                    "Min = "+ min,
                    "Avg = "+ avg,
                    "Max = "+ max
            };
        }

    }

}


text: """EmPOWER application implementing an LVNF Chaining."""


text:
#include "thlo/IR/thlo_ops.h"

#include <algorithm>
#include <functional>
#include <iterator>
#include <memory>
#include <string>
#include <tuple>
#include <utility>

#include "gml_st/IR/gml_st_ops.h"
#include "gml_st/interfaces/tiling_interface.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallVector.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Arith/Utils/Utils.h"
#include "mlir/Dialect/Linalg/IR/LinalgInterfaces.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Tensor/Utils/Utils.h"
#include "mlir/Dialect/Utils/StructuredOpsUtils.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/TypeUtilities.h"
#include "mlir/Interfaces/DestinationStyleOpInterface.h"
#include "thlo/IR/thlo_ops.h"

namespace mlir {
namespace {

//===----------------------------------------------------------------------===//
// Destination-style ops tools
//===----------------------------------------------------------------------===//

LogicalResult verifyDestinationStyleOp(Operation *op) {
  auto dstStyleOp = cast<DestinationStyleOpInterface>(*op);
  if (dstStyleOp.hasBufferSemantics()) return success(op->getNumResults() == 0);

  if (!dstStyleOp.hasTensorSemantics())
    return op->emitOpError("expected either buffer or tensor semantics");

  return success();
}

template <typename DstOpTy>
void printDstStyleOp(
    DstOpTy op, OpAsmPrinter &p,
    function_ref<SmallVector<StringRef>(DstOpTy op, OpAsmPrinter &)>
        printAttrsFn = nullptr) {
  if (op.getNumDpsInputs() != 0) {
    p.printNewline();
    p << " ins(";
    llvm::interleaveComma(
        op.getOperands().take_front(op.getNumDpsInputs()), p,
        [&](Value input) { p << input << " : " << input.getType(); });
    p << ")";
  }
  p.printNewline();
  p << " outs(";
  llvm::interleaveComma(
      op.getOperands().take_back(op.getNumDpsInits()), p,
      [&](Value output) { p << output << " : " << output.getType(); });
  p << ")";
  p.printNewline();

  // Print attributes with custom printing logic.
  SmallVector<StringRef> elidedAttrs;
  if (printAttrsFn) elidedAttrs = printAttrsFn(op, p);

  p.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
}

ParseResult parseKeywordOperandListWithTypes(
    OpAsmParser &parser, OperationState &result, StringRef keyword,
    SmallVectorImpl<Type> *operandTypes) {
  SmallVector<OpAsmParser::UnresolvedOperand, 4> operands;
  if (succeeded(parser.parseOptionalKeyword(keyword))) {
    SMLoc operandsOperandsLoc = parser.getCurrentLocation();

    if (parser.parseCommaSeparatedList(
            AsmParser::Delimiter::Paren, [&]() -> ParseResult {
              if (parser.parseOperand(operands.emplace_back(),
                                      /*allowResultNumber=*/false) ||
                  parser.parseColon() ||
                  parser.parseType(operandTypes->emplace_back())) {
                return failure();
              }
              return success();
            }))
      return failure();

    if (parser.resolveOperands(operands, *operandTypes, operandsOperandsLoc,
                               result.operands))
      return failure();
  }
  return success();
}

ParseResult parseDstStyleOp(
    OpAsmParser &parser, OperationState &result,
    function_ref<ParseResult(OpAsmParser &, NamedAttrList &)> parseAttrsFn =
        nullptr) {
  // Parse `ins` and `outs`.
  SmallVector<Type, 4> inputTypes, outputTypes;
  if (parseKeywordOperandListWithTypes(parser, result, "ins", &inputTypes) ||
      parseKeywordOperandListWithTypes(parser, result, "outs", &outputTypes))
    return failure();

  // Add result types.
  for (Type outputType : outputTypes) {
    if (outputType.isa<RankedTensorType>()) result.addTypes(outputType);
  }

  // Parse required attributes.
  if (parseAttrsFn && failed(parseAttrsFn(parser, result.attributes)))
    return failure();

  // Parse optional attributes.
  if (parser.parseOptionalAttrDict(result.attributes)) return failure();
  return success();
}

ParseResult parseDenseI64ArrayAttr(OpAsmParser &parser,
                                   NamedAttrList &attributes,
                                   StringRef attributeName) {
  if (parser.parseKeyword(attributeName) || parser.parseEqual())
    return failure();

  attributes.set(attributeName, DenseI64ArrayAttr::parse(parser, Type{}));
  return success();
}

void printDenseI64ArrayAttr(OpAsmPrinter &p, StringRef attributeName,
                            ArrayRef<int64_t> attributeValue) {
  p << " " << attributeName << " = [" << attributeValue << "] ";
}

SmallVector<utils::IteratorType> getParallelIteratorTypes(int64_t dimCount) {
  return SmallVector<utils::IteratorType>(dimCount,
                                          utils::IteratorType::parallel);
}

SmallVector<Range> getIterationDomainForTensor(OpBuilder &b, Location loc,
                                               Value tensor,
                                               int64_t dimCount = -1) {
  auto dimValues = tensor::createDimValues(b, loc, tensor);
  if (dimCount >= 0) dimValues.resize(dimCount);
  return llvm::to_vector(llvm::map_range(dimValues, [&](OpFoldResult d) {
    return Range{b.getIndexAttr(0), d, b.getIndexAttr(1)};
  }));
}

Value getMaterializedTile(OpBuilder &b, Location loc,
                          TypedValue<TensorType> tensor,
                          ArrayRef<OpFoldResult> offsets,
                          ArrayRef<OpFoldResult> sizes) {
  SmallVector<OpFoldResult> strides(offsets.size(), b.getIndexAttr(1));
  Value tile = b.create<gml_st::TileOp>(loc, offsets, sizes, strides);
  return b.create<gml_st::MaterializeOp>(loc, tensor, tile);
}

}  // namespace
}  // namespace mlir

// Generated dialect definitions.
#include "thlo/IR/thlo_dialect.cc.inc"

namespace mlir {
namespace thlo {

void THLODialect::initialize() {
  addOperations<
#define GET_OP_LIST
#include "thlo/IR/thlo_ops.cc.inc"
      >();
}

//===----------------------------------------------------------------------===//
// YieldOp
//===----------------------------------------------------------------------===//

LogicalResult checkYieldOutputs(YieldOp yieldOp,
                                TypeRange expectedElementTypes) {
  uint64_t numOutputs = expectedElementTypes.size();
  if (yieldOp.getValues().size() != numOutputs) {
    return yieldOp.emitOpError("expects number of tensor output args = ")
           << numOutputs << " to match the number of yield operands = "
           << yieldOp.getValues().size();
  }

  for (auto &item : llvm::enumerate(
           llvm::zip(expectedElementTypes, yieldOp.getOperandTypes()))) {
    Type outputElementType, resultType;
    unsigned index = item.index();
    std::tie(outputElementType, resultType) = item.value();
    if (outputElementType != resultType)
      return yieldOp.emitOpError("expects yield operand ")
             << index << " with type = " << resultType
             << " to match output arg element type = " << outputElementType;
  }

  return success();
}

LogicalResult YieldOp::verify() { return success(); }

//===----------------------------------------------------------------------===//
// ConcatenateOp
//===----------------------------------------------------------------------===//

namespace {

gml_st::TileOp createTileOp(OpBuilder &b, Location loc, Value tensor,
                            ArrayRef<OpFoldResult> offsets,
                            ArrayRef<OpFoldResult> sizes) {
  auto initTy = tensor.getType().cast<RankedTensorType>();
  SmallVector<OpFoldResult> unitStrides(initTy.getRank(), b.getIndexAttr(1));
  return b.create<gml_st::TileOp>(loc, offsets, sizes, unitStrides);
}

}  // namespace

SmallVector<utils::IteratorType> ConcatenateOp::getLoopIteratorTypes() {
  return getParallelIteratorTypes(getInit().getType().getRank());
}

SmallVector<Value> ConcatenateOp::getDestinationOperands(OpBuilder &) {
  return {getInit()};
}

SmallVector<Range> ConcatenateOp::getIterationDomain(OpBuilder &b) {
  return getIterationDomainForTensor(b, getLoc(), getInit());
}

namespace {

// TODO(frgossen): Fuse this as a switch statement if all the operands are unit
// size in the concatenation dimension.
Value fuseConcatenateOpThroughTile(ConcatenateOp op, OpBuilder &builder,
                                   Location loc, Value tile) {
  uint64_t concatDim = op.getDimension();
  RankedTensorType resultTy = op.getType(0).cast<RankedTensorType>();
  int64_t rank = resultTy.getRank();
  OperandRange allOperands = op.getInputs();
  Value anyOperand = allOperands.front();

  // Create the shared tile strides, which are the exact same for every operand
  // tile. Also create a basis for the space sizes, tile offsets, and tile
  // sizes. These hold the shared values in all non-concat dimensions and can be
  // amended in the concat dimension to create the individual operand tiles.
  SmallVector<Value> sharedTileStrides(rank);
  SmallVector<Value> baseSpaceSizes(rank);
  SmallVector<Value> baseTileOffsets(rank);
  SmallVector<Value> baseTileSizes(rank);
  auto tileOp = tile.getDefiningOp<gml_st::TileOp>();
  auto tileOffsets =
      getValueOrCreateConstantIndexOp(builder, loc, tileOp.getMixedOffsets());
  auto tileSizes =
      getValueOrCreateConstantIndexOp(builder, loc, tileOp.getMixedSizes());
  auto tileStrides =
      getValueOrCreateConstantIndexOp(builder, loc, tileOp.getMixedStrides());
  for (int64_t i = 0; i < rank; ++i) {
    Value iCst = builder.create<arith::ConstantIndexOp>(loc, i);
    sharedTileStrides[i] = tileStrides[i];

    // The space sizes, tile offsets, and tile sizes differ in the concat
    // dimension. Do not populate these.
    if (i == static_cast<int64_t>(concatDim)) continue;

    baseSpaceSizes[i] =
        builder.createOrFold<tensor::DimOp>(loc, anyOperand, iCst);
    baseTileOffsets[i] = tileOffsets[i];
    baseTileSizes[i] = tileSizes[i];
  }

  // Some shared values.
  ArrayAttr allDynamicStridesOrOffsetsAttr = builder.getI64ArrayAttr(
      SmallVector<int64_t>(rank, ShapedType::kDynamicStrideOrOffset));
  ArrayAttr allDynamicSizesAttr = builder.getI64ArrayAttr(
      SmallVector<int64_t>(rank, ShapedType::kDynamicSize));
  Value zeroCst = builder.create<arith::ConstantIndexOp>(loc, 0);
  Value concatDimCst = builder.create<arith::ConstantIndexOp>(loc, concatDim);
  Value maxTileSizeInConcatDim = tileSizes[concatDim];

  // The remaining tile offset in the concat dimension is subtracted by each
  // operand's size in that dimension. We maintain the invariant
  // remainingTileOffsetInConcatDim >= 0.
  Value remainingTileOffsetInConcatDim = tileOffsets[concatDim];

  // Create the relevant subsets per operand. These tiles can be empty at
  // runtime.
  SmallVector<Value> subOperands;
  subOperands.reserve(allOperands.size());
  for (Value operand : allOperands) {
    // Create operand space.
    Value operandSizeInConcatDim =
        builder.create<tensor::DimOp>(loc, operand, concatDimCst);
    baseSpaceSizes[concatDim] = operandSizeInConcatDim;

    // Find the current operand's tile offset in the concat dimension. This is
    // the remaining offset clamped into the bounds of the operand. Note that
    // the remaining offset is always >= 0.
    Value operandTileOffsetInConcatDim = builder.create<arith::MinUIOp>(
        loc, remainingTileOffsetInConcatDim, operandSizeInConcatDim);
    baseTileOffsets[concatDim] = operandTileOffsetInConcatDim;

    // Find the current operand's tile size in the concat dimension.
    Value remainingOperandSizeInConcatDim = builder.create<arith::SubIOp>(
        loc, operandSizeInConcatDim, operandTileOffsetInConcatDim);
    baseTileSizes[concatDim] = builder.create<arith::MinUIOp>(
        loc, remainingOperandSizeInConcatDim, maxTileSizeInConcatDim);

    // Create the operand tile and materialize the subset for this operand.
    Value tile = builder.create<gml_st::TileOp>(
        loc, baseTileOffsets, baseTileSizes, sharedTileStrides,
        allDynamicStridesOrOffsetsAttr, allDynamicSizesAttr,
        allDynamicStridesOrOffsetsAttr);
    subOperands.push_back(
        builder.create<gml_st::MaterializeOp>(loc, operand, tile));

    // Unless it is the last operand, update the remaining tile offset in the
    // concat dimension. The remaining offset is subtracted by the operand's
    // size but must remain >= 0.
    if (operand != allOperands.back()) {
      Value cmp = builder.create<arith::CmpIOp>(loc, arith::CmpIPredicate::ule,
                                                remainingTileOffsetInConcatDim,
                                                operandSizeInConcatDim);
      Value sub = builder.create<arith::SubIOp>(
          loc, remainingTileOffsetInConcatDim, operandSizeInConcatDim);
      remainingTileOffsetInConcatDim =
          builder.create<arith::SelectOp>(loc, cmp, zeroCst, sub);
    }
  }

  // Create the tiled concat op.
  auto tileType = tile.getType().cast<gml_st::TileType>();
  Value subInit =
      builder.create<gml_st::MaterializeOp>(loc, op.getInit(), tile);
  auto subResultType =
      RankedTensorType::get(tileType.getShape(), resultTy.getElementType());
  return builder
      .create<thlo::ConcatenateOp>(loc, subResultType, subOperands, subInit,
                                   concatDim)
      ->getResult(0);
}

Value fuseConcatenateOpThroughPointRecursively(
    OpBuilder &builder, Location loc, RankedTensorType rankedTy,
    uint64_t concatDim, SmallVector<Value> &remainingOffsets,
    ValueRange remainingOperands) {
  // Bail if called for no operands.
  if (remainingOperands.empty()) {
    return {};
  }
  Value leadingOperand = remainingOperands.front();

  // Terminal case of exactly one operand.
  if (remainingOperands.size() == 1) {
    // Create operand point.
    SmallVector<int64_t> allDynamicOffsets(rankedTy.getRank(),
                                           ShapedType::kDynamicStrideOrOffset);

    auto sizeOrStride = builder.getI64ArrayAttr({1});
    Value operandPoint = builder.create<gml_st::TileOp>(
        loc, remainingOffsets, ValueRange{}, ValueRange{},
        builder.getI64ArrayAttr(allDynamicOffsets), sizeOrStride, sizeOrStride);

    return builder.create<gml_st::MaterializeOp>(loc, rankedTy.getElementType(),
                                                 leadingOperand, operandPoint);
  }

  // For more than 1 operand, distinguish between the leading operand and the
  // remainder.
  assert(remainingOperands.size() > 1 &&
         "expect more than 1 operand at this point");
  Value leadingOperandConcatDim =
      builder.create<tensor::DimOp>(loc, leadingOperand, concatDim);
  Value leadingOperandPredicate = builder.create<arith::CmpIOp>(
      loc, arith::CmpIPredicate::ult, remainingOffsets[concatDim],
      leadingOperandConcatDim);
  auto ifOp = builder.create<scf::IfOp>(
      loc, rankedTy.getElementType(), leadingOperandPredicate,
      [&](OpBuilder &builder, Location loc) {
        // For the leading operand, recur with the current offsets.
        Value fused = fuseConcatenateOpThroughPointRecursively(
            builder, loc, rankedTy, concatDim, remainingOffsets,
            leadingOperand);
        builder.create<scf::YieldOp>(loc, fused);
      },
      [&](OpBuilder &builder, Location loc) {
        // For the remaining operands, substract the leading operand's size from
        // the remaining offsets in the concatenation dimension.
        SmallVector<Value> thenRemainingOffsets(remainingOffsets.begin(),
                                                remainingOffsets.end());
        thenRemainingOffsets[concatDim] = builder.create<arith::SubIOp>(
            loc, remainingOffsets[concatDim], leadingOperandConcatDim);
        Value fused = fuseConcatenateOpThroughPointRecursively(
            builder, loc, rankedTy, concatDim, thenRemainingOffsets,
            remainingOperands.drop_front());
        builder.create<scf::YieldOp>(loc, fused);
      });
  return ifOp.getResults().front();
}

}  // namespace

gml_st::TilingInterface ConcatenateOp::getTiledImplementation(
    OpBuilder &b, ArrayRef<OpFoldResult> offsets,
    ArrayRef<OpFoldResult> sizes) {
  // Create tile subset.
  auto loc = getLoc();
  gml_st::TileOp tile = createTileOp(b, loc, getInit(), offsets, sizes);

  auto tiled = fuseConcatenateOpThroughTile(*this, b, loc, tile);
  return llvm::cast<gml_st::TilingInterface>(tiled.getDefiningOp());
}

FailureOr<Value> ConcatenateOp::generateResultTileValue(
    OpBuilder &b, unsigned resultNumber, ArrayRef<OpFoldResult> offsets,
    ArrayRef<OpFoldResult> sizes) {
  assert(resultNumber == 0 && "expect unique result idx");
  return getTiledImplementation(b, offsets, sizes)->getResults().front();
}

ParseResult ConcatenateOp::parse(OpAsmParser &parser, OperationState &result) {
  return parseDstStyleOp(parser, result);
}

void ConcatenateOp::print(OpAsmPrinter &p) { printDstStyleOp(*this, p); }

LogicalResult ConcatenateOp::verify() {
  int64_t concatDim = getDimension();

  ShapedType inputType =
      getDpsInputOperand(0)->get().getType().cast<ShapedType>();
  int64_t rank = inputType.getRank();
  auto inputShape = inputType.getShape();

  Type outputElementType =
      getDpsInitOperand(0)->get().getType().cast<ShapedType>().getElementType();

  for (const auto &en : llvm::enumerate(getInputs())) {
    ShapedType inputArgShapedType = en.value().getType().cast<ShapedType>();
    auto inputArgShape = inputArgShapedType.getShape();

    if (inputArgShapedType.getElementType() != outputElementType)
      return emitOpError() << "expected element type of input "
                           << inputArgShapedType.getElementType()
                           << " to match output element type "
                           << outputElementType;

    if (inputArgShapedType.getRank() != rank)
      return emitOpError() << "expected all args to be rank " << rank
                           << ", got " << inputArgShapedType.getRank()
                           << " in arg " << en.index();

    // Make sure that all dimensions, expect for concatenation dim, in the input
    // arg are equal.
    // TODO(shyshkov): Also check output dims once tiling is fixed for
    // ConcatenateOp.
    for (int64_t i = 0; i < rank; ++i) {
      if (i == concatDim) continue;

      if (inputShape[i] != inputArgShape[i])
        return emitOpError()
               << "shape of input arg " << en.index() << ": "
               << inputArgShapedType << " doesn't match expected shape "
               << inputType << " (all dims except concat dim(" << concatDim
               << ") should match exactly)";
    }
  }

  return verifyDestinationStyleOp(getOperation());
}

//===----------------------------------------------------------------------===//
// DynamicBroadcastInDimOp
//===----------------------------------------------------------------------===//

ParseResult DynamicBroadcastInDimOp::parse(OpAsmParser &parser,
                                           OperationState &result) {
  return parseDstStyleOp(parser, result,
                         [&](OpAsmParser &parser, NamedAttrList &attributes) {
                           return parseDenseI64ArrayAttr(
                               parser, attributes, "broadcast_dimensions");
                         });
}

void DynamicBroadcastInDimOp::print(OpAsmPrinter &p) {
  printDstStyleOp<DynamicBroadcastInDimOp>(
      *this, p,
      [](DynamicBroadcastInDimOp op,
         OpAsmPrinter &p) -> SmallVector<StringRef> {
        printDenseI64ArrayAttr(p, op.getBroadcastDimensionsAttrName(),
                               op.getBroadcastDimensions());
        return {op.getBroadcastDimensionsAttrName()};
      });
}

LogicalResult DynamicBroadcastInDimOp::verify() {
  return verifyDestinationStyleOp(getOperation());
}

SmallVector<utils::IteratorType>
DynamicBroadcastInDimOp::getLoopIteratorTypes() {
  return getParallelIteratorTypes(getInit().getType().getRank());
}

SmallVector<Value> DynamicBroadcastInDimOp::getDestinationOperands(
    OpBuilder &) {
  return {getInit()};
}

SmallVector<Range> DynamicBroadcastInDimOp::getIterationDomain(OpBuilder &b) {
  return getIterationDomainForTensor(b, getLoc(), getInit());
}

gml_st::TilingInterface DynamicBroadcastInDimOp::getTiledImplementation(
    OpBuilder &b, ArrayRef<OpFoldResult> offsets,
    ArrayRef<OpFoldResult> sizes) {
  // Create tile subset.
  auto loc = getLoc();
  auto tile = createTileOp(b, loc, getInit(), offsets, sizes);
  auto initRank = getInit().getType().cast<RankedTensorType>().getRank();

  // Create the needed constants only once.
  DenseMap<uint64_t, Value> localIndexConstants;
  auto getIndexConstant = [&](uint64_t c) -> Value {
    auto it = localIndexConstants.find(c);
    if (it != localIndexConstants.end()) return it->second;
    auto cst = b.create<arith::ConstantIndexOp>(loc, c);
    localIndexConstants[c] = cst;
    return cst;
  };

  DenseSet<int64_t> dimensionsThatStay(getBroadcastDimensions().begin(),
                                       getBroadcastDimensions().end());

  // Materialize operand space.
  auto operandTy = getOperand().getType().cast<RankedTensorType>();
  auto dynamicDims = tensor::createDynamicDimValues(b, loc, getOperand());

  // Materialize operand dimensions.
  SmallVector<Value> operandDims;
  int64_t dynamicDimsIdx = 0;
  operandDims.reserve(operandTy.getRank());
  for (const auto &it : llvm::enumerate(operandTy.getShape())) {
    int64_t d = it.value();
    Value dim = d == ShapedType::kDynamicSize ? dynamicDims[dynamicDimsIdx++]
                                              : getIndexConstant(d);
    operandDims.push_back(dim);
  }

  // Find the expanding dimensions. If corresponding operand and result
  // dimensions are different then the dimension is expanding.
  // TODO(frgossen): Use info from known expanding and known non-expanding
  // dimensions here.
  SmallVector<Value> operandExpandingDims;
  for (const auto &it : llvm::enumerate(getBroadcastDimensions())) {
    auto operandDim = operandDims[it.index()];
    auto resultDim =
        b.create<tensor::DimOp>(loc, getInit(), getIndexConstant(it.value()));
    operandExpandingDims.push_back(b.create<arith::CmpIOp>(
        loc, arith::CmpIPredicate::ne, operandDim, resultDim));
  }

  // Compute operand tile offsets.
  auto tileOpOffsets =
      getValueOrCreateConstantIndexOp(b, loc, tile.getMixedOffsets());
  int64_t operandRank = operandTy.getRank();
  auto staticOffsets = b.getI64ArrayAttr(
      SmallVector<int64_t>(operandRank, ShapedType::kDynamicStrideOrOffset));
  SmallVector<Value> operandOffsets;
  Value zero = getIndexConstant(0);
  for (int initId = 0, operandId = 0; initId < initRank; ++initId) {
    if (!dimensionsThatStay.contains(initId)) continue;
    Value isExpanding = operandExpandingDims[operandId++];
    Value collapsedSubsetOffset = tileOpOffsets[initId];
    operandOffsets.push_back(b.create<arith::SelectOp>(loc, isExpanding, zero,
                                                       collapsedSubsetOffset));
  }

  // Compute operand tile sizes.
  auto staticTileSizes = b.getI64ArrayAttr(
      SmallVector<int64_t>(operandRank, ShapedType::kDynamicSize));
  SmallVector<Value> tileSizes;
  Value one = getIndexConstant(1);
  auto tileOpSizes =
      getValueOrCreateConstantIndexOp(b, loc, tile.getMixedSizes());
  for (int initId = 0, operandId = 0; initId < initRank; ++initId) {
    if (!dimensionsThatStay.contains(initId)) continue;
    Value isExpanding = operandExpandingDims[operandId++];
    Value tileSize = tileOpSizes[initId];
    tileSizes.push_back(
        b.create<arith::SelectOp>(loc, isExpanding, one, tileSize));
  }

  // Create operand tile.
  auto staticTileStrides =
      b.getI64ArrayAttr(SmallVector<int64_t>(operandRank, 1));
  SmallVector<Value> tileStrides = {};
  auto operandTileTy = b.getType<gml_st::TileType>(
      SmallVector<int64_t>(operandRank, ShapedType::kDynamicSize));
  auto operandTile = b.create<gml_st::TileOp>(
      loc, operandTileTy, operandOffsets, tileSizes, tileStrides, staticOffsets,
      staticTileSizes, staticTileStrides);

  // Materialize operand tiles.
  Value tiledInit = b.create<gml_st::MaterializeOp>(loc, getInit(), tile);
  Value tiledOperand =
      b.create<gml_st::MaterializeOp>(loc, getOperand(), operandTile);

  // Finally, materialize tiled broadcast.
  auto tileTy = tile.getType();
  auto resultTy = getType(0).cast<RankedTensorType>();
  auto tiledResultTy =
      RankedTensorType::get(tileTy.getShape(), resultTy.getElementType());
  return b.create<DynamicBroadcastInDimOp>(
      loc, TypeRange{tiledResultTy}, tiledOperand, tiledInit,
      getBroadcastDimensionsAttr(), getKnownExpandingDimensionsAttr(),
      getKnownNonexpandingDimensionsAttr());
}

FailureOr<Value> DynamicBroadcastInDimOp::generateResultTileValue(
    OpBuilder &b, unsigned resultNumber, ArrayRef<OpFoldResult> offsets,
    ArrayRef<OpFoldResult> sizes) {
  assert(resultNumber == 0 && "expect unique result idx");
  return getTiledImplementation(b, offsets, sizes)->getResults().front();
}

//===----------------------------------------------------------------------===//
// ScatterOp
//===----------------------------------------------------------------------===//

ParseResult ScatterOp::parse(OpAsmParser &parser, OperationState &result) {
  if (parseDstStyleOp(parser, result)) return failure();

  SmallVector<OpAsmParser::Argument> regionArgs;
  if (parser.parseArgumentList(regionArgs, OpAsmParser::Delimiter::Paren,
                               /*allowType=*/true, /*allowAttrs=*/true)) {
    return failure();
  }

  Region *body = result.addRegion();
  if (parser.parseRegion(*body, regionArgs)) return failure();

  return success();
}

void ScatterOp::print(OpAsmPrinter &p) {
  printDstStyleOp<ScatterOp>(*this, p);

  p << "(";
  llvm::interleaveComma(getUpdateComputation().getArguments(), p,
                        [&](auto arg) { p.printRegionArgument(arg); });
  p << ") ";

  p.printRegion(getUpdateComputation(), /*printEntryBlockArgs=*/false);
}

LogicalResult ScatterOp::verify() {
  if (failed(verifyDestinationStyleOp(getOperation()))) return failure();

  auto indicesType = getIndices().getType().cast<ShapedType>();
  int64_t indicesRank = indicesType.getRank();

  if (indicesRank != 2)
    return emitOpError() << "expected `indices` to be a 2D tensor";

  auto updatesType = getUpdates().getType();
  int64_t updatesRank = updatesType.getRank();

  if (updatesType.getDimSize(0) != indicesType.getDimSize(0)) {
    return emitOpError() << "expected major dimension of `indices` to match "
                            "major dimension of `updates`";
  }

  int64_t indexVectorDim = indicesType.getDimSize(1);
  if (ShapedType::isDynamic(indexVectorDim))
    return emitOpError() << "expected index vector dimension size to be static";

  auto initType = getInit().getType();
  int64_t initRank = initType.getRank();

  if (indexVectorDim > initRank) {
    return emitOpError() << "expected index vector dimension size = "
                         << indexVectorDim
                         << " to be smaller or equal than `init` rank = "
                         << initRank;
  }

  if (updatesRank - 1 != initRank)
    return emitOpError() << "expected `updates` rank + 1 to match `init` rank";

  if (updatesType.getElementType() != initType.getElementType()) {
    return emitOpError()
           << "expected `updates` element type to match `init` element type";
  }

  // The update computation should yield exactly 1 result.
  auto updateTerminator = cast<YieldOp>(getBody()->getTerminator());
  Type outputElementType =
      getDpsInitOperand(0)->get().getType().cast<ShapedType>().getElementType();
  if (!succeeded(checkYieldOutputs(updateTerminator, outputElementType)))
    return failure();

  return success();
}

SmallVector<utils::IteratorType> ScatterOp::getLoopIteratorTypes() {
  return {utils::IteratorType::reduction};
}

SmallVector<Value> ScatterOp::getDestinationOperands(OpBuilder &) {
  return {getInit()};
}

SmallVector<Range> ScatterOp::getIterationDomain(OpBuilder &b) {
  Value indicesCount = b.create<tensor::DimOp>(getLoc(), getIndices(), 0);
  return {Range{b.getIndexAttr(0), indicesCount, b.getIndexAttr(1)}};
}

static Value getSlice(OpBuilder &b, Location loc, Value tensor,
                      ArrayRef<OpFoldResult> offsets,
                      ArrayRef<OpFoldResult> sizes) {
  SmallVector<OpFoldResult> ones(offsets.size(), b.getIndexAttr(1));
  Value tile = b.create<gml_st::TileOp>(loc, offsets, sizes, ones);
  return b.create<gml_st::MaterializeOp>(loc, tensor, tile);
}

static Value getFullSpace(OpBuilder &b, Location loc, Value tensor) {
  SmallVector<OpFoldResult> sizes = tensor::getMixedSizes(b, loc, tensor);
  SmallVector<OpFoldResult> offsets(sizes.size(), b.getIndexAttr(0));
  return getSlice(b, loc, tensor, offsets, sizes);
}

mlir::gml_st::TilingInterface ScatterOp::getTiledImplementation(
    OpBuilder &b, ArrayRef<OpFoldResult> offsets,
    ArrayRef<OpFoldResult> sizes) {
  Location loc = getLoc();
  IntegerAttr zeroAttr = b.getIndexAttr(0);

  OpFoldResult tileOffset = offsets.front();
  OpFoldResult tileSize = sizes.front();

  // Tile outer dimension of updates.
  Value update = this->getUpdates();
  auto updateType = update.getType().cast<RankedTensorType>();

  SmallVector<OpFoldResult> updateOffsets(updateType.getRank(), zeroAttr);
  updateOffsets.front() = tileOffset;
  SmallVector<OpFoldResult> updateSizes = tensor::getMixedSizes(b, loc, update);
  updateSizes.front() = tileSize;

  Value updateSlice = getSlice(b, loc, update, updateOffsets, updateSizes);

  // Tile outer dimension of indices.
  Value indices = this->getIndices();

  SmallVector<OpFoldResult> indicesOffsets{offsets.front(), zeroAttr};
  indicesOffsets.front() = tileOffset;
  SmallVector<OpFoldResult> indicesSizes =
      tensor::getMixedSizes(b, loc, indices);
  indicesSizes.front() = tileSize;

  Value indicesSlice = getSlice(b, loc, indices, indicesOffsets, indicesSizes);

  // Get full space of the `init` tensor.
  Value init = this->getInit();
  Value initSlice = getFullSpace(b, loc, init);

  auto dpsInterface = cast<DestinationStyleOpInterface>(this->getOperation());
  return dpsInterface.clone(b, loc, TypeRange{initSlice.getType()},
                            ValueRange{indicesSlice, updateSlice, initSlice});
}

FailureOr<Value> ScatterOp::generateResultTileValue(
    OpBuilder &b, unsigned resultNumber, ArrayRef<OpFoldResult> offsets,
    ArrayRef<OpFoldResult> sizes) {
  assert(resultNumber == 0 && "variadic scatter is not implemented");
  return getTiledImplementation(b, offsets, sizes)->getResult(0);
}

//===----------------------------------------------------------------------===//
// GatherOp
//===----------------------------------------------------------------------===//

ParseResult GatherOp::parse(OpAsmParser &parser, OperationState &result) {
  return parseDstStyleOp(parser, result);
}

void GatherOp::print(OpAsmPrinter &p) { printDstStyleOp(*this, p); }

LogicalResult GatherOp::verify() {
  auto indicesType = getStartIndices().getType();
  int64_t indicesRank = indicesType.getRank();

  if (indicesRank != 2)
    return emitOpError() << "expected `indices` to be a 2D tensor";

  auto initType = getInit().getType();
  if (indicesType.getDimSize(0) != getInit().getType().getDimSize(0)) {
    return emitOpError()
           << "expected major dimension of `startIndices` to match "
              "major dimension of `init`";
  }

  if (initType.getNumDynamicDims() > 1 ||
      (initType.getNumDynamicDims() == 1 && !initType.isDynamicDim(0))) {
    return emitOpError() << "only the major dimenion of `init` may be dynamic";
  }

  if (indicesType.isDynamic(1)) {
    return emitOpError()
           << "the minor dimensions of `startIndices` must be static";
  }

  return verifyDestinationStyleOp(getOperation());
}

SmallVector<utils::IteratorType> GatherOp::getLoopIteratorTypes() {
  return {utils::IteratorType::parallel};
}

SmallVector<Value> GatherOp::getDestinationOperands(OpBuilder &) {
  return {getInit()};
}

SmallVector<Range> GatherOp::getIterationDomain(OpBuilder &b) {
  Value indicesCount = b.create<tensor::DimOp>(getLoc(), getStartIndices(), 0);
  return {Range{b.getIndexAttr(0), indicesCount, b.getIndexAttr(1)}};
}

mlir::gml_st::TilingInterface GatherOp::getTiledImplementation(
    OpBuilder &b, ArrayRef<OpFoldResult> offsets,
    ArrayRef<OpFoldResult> sizes) {
  SmallVector<OpFoldResult> startIndexOffsets{offsets.front(),
                                              b.getIndexAttr(0)};
  SmallVector<OpFoldResult> startIndexSizes{
      sizes.front(),
      b.getIndexAttr(getStartIndices().getType().getShape().back())};
  auto subStartIndices = getMaterializedTile(
      b, getLoc(), getStartIndices(), startIndexOffsets, startIndexSizes);

  int64_t initRank = getInit().getType().getRank();
  SmallVector<OpFoldResult> initOffsets(initRank, b.getIndexAttr(0));
  initOffsets[0] = offsets.front();
  auto initSizes = tensor::getMixedSizes(b, getLoc(), getInit());
  initSizes[0] = sizes.front();
  Value initSlice =
      getMaterializedTile(b, getLoc(), getInit(), initOffsets, initSizes);

  return b
      .create<GatherOp>(getLoc(), TypeRange{initSlice.getType()},
                        ValueRange{getOperand(), subStartIndices, initSlice})
      .getOperation();
}

FailureOr<Value> GatherOp::generateResultTileValue(
    OpBuilder &b, unsigned resultNumber, ArrayRef<OpFoldResult> offsets,
    ArrayRef<OpFoldResult> sizes) {
  assert(resultNumber == 0 && "resultNumber > 0 not implemented");
  return getTiledImplementation(b, offsets, sizes)->getResult(0);
}

//===----------------------------------------------------------------------===//
// SortOp
//===----------------------------------------------------------------------===//

void SortOp::getAsmResultNames(function_ref<void(Value, StringRef)> setNameFn) {
  ResultRange results = getResults();
  for (int i = 0; i < results.size(); i++) {
    setNameFn(results[i], "sorted" + std::to_string(i));
  }
}

void SortOp::getAsmBlockArgumentNames(Region &region,
                                      OpAsmSetValueNameFn setNameFn) {
  for (int i = 0, e = region.getNumArguments(); i < e; i += 2) {
    setNameFn(region.getArgument(i), "lhs" + std::to_string(i / 2));
    setNameFn(region.getArgument(i + 1), "rhs" + std::to_string(i / 2));
  }
}

ParseResult SortOp::parse(OpAsmParser &parser, OperationState &result) {
  if (parseDstStyleOp(parser, result)) return failure();

  SmallVector<OpAsmParser::Argument> regionArgs;
  if (parser.parseArgumentList(regionArgs, OpAsmParser::Delimiter::Paren,
                               /*allowType=*/true, /*allowAttrs=*/true)) {
    return failure();
  }

  Region *comparator = result.addRegion();
  if (parser.parseRegion(*comparator, regionArgs)) return failure();

  return success();
}

void SortOp::print(OpAsmPrinter &p) {
  printDstStyleOp<SortOp>(*this, p);

  p << "(";
  llvm::interleaveComma(getComparator().getArguments(), p,
                        [&](auto arg) { p.printRegionArgument(arg); });
  p << ") ";

  p.printRegion(getComparator(), /*printEntryBlockArgs=*/false);
}

LogicalResult SortOp::verify() {
  auto *comparatorBlock = getBody();
  auto comparatorArgs = comparatorBlock->getArguments();

  // Checks that the arity of the comparator is equal to twice the number of
  // inputs.
  int64_t numInputs = getNumDpsInputs();
  int64_t numOutputs = getNumDpsInits();
  if (getNumDpsInits() != numInputs) {
    return emitOpError() << "expected the number of inputs " << numInputs
                         << " to match the number of outputs " << numOutputs;
  }
  if (static_cast<int64_t>(comparatorArgs.size()) != numInputs * 2) {
    return emitOpError() << "expected the number of block arguments "
                         << comparatorArgs.size() << " to be twice the number "
                         << "of inputs (2*" << numInputs << ")";
  }
  // Checks that the comparator's arguments match the element type of the
  // inputs.
  TypeRange inputTypes = TypeRange{getInputs()};
  TypeRange comparatorArgElementTypes = comparatorBlock->getArgumentTypes();
  for (size_t i = 0; i < getInputs().size(); ++i) {
    Type inputArgElemType = inputTypes[i].cast<ShapedType>().getElementType(),
         comparatorArgElemType1 = comparatorArgElementTypes[2 * i],
         comparatorArgElemType2 = comparatorArgElementTypes[2 * i + 1];
    if (comparatorArgElemType1 != inputArgElemType ||
        comparatorArgElemType2 != inputArgElemType)
      return emitOpError() << "expected element type of input " << i
                           << " to match type of the corresponding "
                              "arguments to the comparison function but got "
                           << inputArgElemType << " and ("
                           << comparatorArgElemType1 << ", "
                           << comparatorArgElemType2 << ")";
  }

  // Checks that the comparator yields exactly one boolean output.
  YieldOp comparatorTerminator =
      cast<YieldOp>(comparatorBlock->getTerminator());
  if (!succeeded(
          checkYieldOutputs(comparatorTerminator,
                            TypeRange({IntegerType::get(getContext(), 1)}))))
    return failure();

  // Checks that the inputs all have the same shape.
  ArrayRef<int64_t> referenceShape =
      getInputs().front().getType().cast<ShapedType>().getShape();

  for (auto &item : llvm::enumerate(TypeRange{getInputs()})) {
    ArrayRef<int64_t> shape = item.value().cast<ShapedType>().getShape();
    if (shape != referenceShape) {
      return emitOpError() << "expected all inputs to have the same shape ("
                           << referenceShape << ") but input " << item.index()
                           << " has shape (" << shape << ")";
    }
  }

  // Checks that the outputs have the same shape as the inputs.
  for (auto &item : llvm::enumerate(getInits())) {
    ArrayRef<int64_t> shape =
        item.value().getType().cast<ShapedType>().getShape();
    if (shape != referenceShape) {
      return emitOpError() << "expected outputs to have shape ("
                           << referenceShape << ") but output " << item.index()
                           << " has shape (" << shape << ")";
    }
  }

  // Checks that the rank of the reference shape is larger than the absolute
  // value of the sorting dimension. This is enough to ensure that the dimension
  // is valid, since all inputs are known to have the same shape. `getDimension`
  // returns an unsigned int, so no need to check for negative values.
  size_t referenceRank = referenceShape.size();
  if (getDimension() >= referenceRank) {
    return emitOpError() << "sorting dimension must be in range [0, "
                         << referenceRank << ") but got " << getDimension();
  }

  return verifyDestinationStyleOp(getOperation());
}

SmallVector<utils::IteratorType> SortOp::getLoopIteratorTypes() {
  return getParallelIteratorTypes(getType(0).cast<ShapedType>().getRank() - 1);
}

SmallVector<Value> SortOp::getDestinationOperands(OpBuilder &) {
  return {getInits()};
}

SmallVector<Range> SortOp::getIterationDomain(OpBuilder &b) {
  Location loc = getLoc();
  auto oneInit = getInits().front();
  auto operandsRank = oneInit.getType().cast<ShapedType>().getRank();

  SmallVector<Range> iterationDomain(operandsRank - 1);

  IntegerAttr zero = b.getIndexAttr(0);
  IntegerAttr one = b.getIndexAttr(1);
  int64_t sortDimension = getDimension();

  for (auto axis : llvm::seq<int64_t>(0, operandsRank - 1)) {
    int64_t operandAxis = (axis >= sortDimension) ? axis + 1 : axis;
    iterationDomain[axis].offset = zero;
    iterationDomain[axis].size =
        b.createOrFold<tensor::DimOp>(loc, oneInit, operandAxis);
    iterationDomain[axis].stride = one;
  }
  return iterationDomain;
}

mlir::gml_st::TilingInterface SortOp::getTiledImplementation(
    OpBuilder &b, ArrayRef<OpFoldResult> offsets,
    ArrayRef<OpFoldResult> sizes) {
  auto loc = getLoc();
  SmallVector<OpFoldResult> tileOffsets = llvm::to_vector(offsets);
  SmallVector<OpFoldResult> tileSizes = llvm::to_vector(sizes);

  size_t numOutputs = getNumDpsInits();
  int64_t sortDimension = getDimension();

  Value oneInput = getInputs().front();

  // Capture the entire sorting axis in each tile.
  tileOffsets.insert(tileOffsets.begin() + sortDimension, b.getIndexAttr(0));

  OpFoldResult sortDimensionSize =
      b.createOrFold<tensor::DimOp>(loc, oneInput, sortDimension);
  tileSizes.insert(tileSizes.begin() + sortDimension, sortDimensionSize);

  gml_st::TileOp tile = createTileOp(b, loc, oneInput, tileOffsets, tileSizes);

  // Materialize the tile for each input and init.
  SmallVector<Value> tiledInputsAndInits;
  SmallVector<Type> tiledResultTypes;
  tiledInputsAndInits.reserve(numOutputs * 2);
  tiledResultTypes.reserve(numOutputs);

  auto tileShape = tile.getType().cast<gml_st::TileType>().getShape();

  for (const auto &input : getInputs()) {
    tiledInputsAndInits.push_back(
        b.create<gml_st::MaterializeOp>(loc, input, tile));
    tiledResultTypes.push_back(RankedTensorType::get(
        tileShape, input.getType().cast<ShapedType>().getElementType()));
  }

  for (const auto &init : getInits()) {
    tiledInputsAndInits.push_back(
        b.create<gml_st::MaterializeOp>(loc, init, tile));
  }

  auto dpsInterface = cast<DestinationStyleOpInterface>(this->getOperation());
  return dpsInterface.clone(b, loc, tiledResultTypes, tiledInputsAndInits);
}

FailureOr<Value> SortOp::generateResultTileValue(OpBuilder &b,
                                                 unsigned resultNumber,
                                                 ArrayRef<OpFoldResult> offsets,
                                                 ArrayRef<OpFoldResult> sizes) {
  return getTiledImplementation(b, offsets, sizes)->getResult(resultNumber);
}

}  // namespace thlo
}  // namespace mlir

// Generated op classes.
#define GET_OP_CLASSES
#include "thlo/IR/thlo_ops.cc.inc"