text:
--/**
-- * <copyright>
-- *
-- * Copyright (c) 2005, 2009 IBM Corporation and others.
-- * All rights reserved.   This program and the accompanying materials
-- * are made available under the terms of the Eclipse Public License v2.0
-- * which accompanies this distribution, and is available at
-- * http://www.eclipse.org/legal/epl-v20.html
-- *
-- * Contributors:
-- *   See (or edit) Notice Declaration below
-- *
-- * </copyright>
-- */
--
-- The Essential OCL Lexer
--

%options escape=$
%options la=2
%options fp=EssentialOCLLexer,prefix=Char_
%options single-productions
%options noserialize
%options package=org.eclipse.ocl.parser
%options template=../lpg/LexerTemplateF.gi
%options filter=EssentialOCLKWLexer.gi
%options export_terminals=("EssentialOCLParsersym.java", "TK_")
%options include_directory="../lpg"

%Import
	LexerBasicMapF.gi
%End

%Define

	--
	-- Definition of macros used in the template
	--
	$action_class /.$file_prefix./  -- Deprecated.
	$eof_token /.$_EOF_TOKEN./
    $environment_class /.Environment<?,?,?,?,?,?,?,?,?,?,?,?>./
    $adapt_environment /.OCLUtil.getAdapter(environment, BasicEnvironment.class)./
    $environment_import /.org.eclipse.ocl.Environment./

 	--
	-- Redefinition of macros used in the template
	-- NB: They are also used in the included file LexerBasicMapF.g
	--
 	$prs_stream_class /.DerivedPrsStream./
 	$lex_stream_class /.DerivedLexStream./

	--
	-- Definition of macro used in the included file LexerBasicMapF.g
	--
	$kw_lexer_class /.EssentialOCLKWLexer./
	$copyright_contributions /.*./

%End

%Headers
	/.

    // Some OCL additions to make lexer work with an input reader
	/**
	 * @since 3.0
	 */
	public $action_type($environment_class environment, Reader reader, String filename) throws java.io.IOException {
		super($adapt_environment);
		oclEnvironment = environment;
		reset(reader, filename);
	}

   // OCL addition to reset the lexer stream from an input reader
	/**
	 * @since 3.0
	 */
    @Override
    public void reset(Reader reader, String filename) throws java.io.IOException {
    	char[] input_chars = getInputChars(reader);
        reset(input_chars, filename, ECLIPSE_TAB_VALUE);
    }
	./
%End
%Notice
	/./**
 * Essential OCL Lexer
 * <copyright>
 *
 * Copyright (c) 2005, 2010 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *   IBM - Initial API and implementation
 *   E.D.Willink - Lexer and Parser refactoring to support extensibility and flexible error handling
 *   Borland - Bug 242880
 *   E.D.Willink - Bug 292112, 295166
 *   Adolfo Sanchez-Barbudo Herrera (Open Canarias) - LPG v 2.0.17 adoption (242153)
 *   Adolfo Sanchez-Barbudo Herrera (Open Canarias) - Introducing new LPG templates (299396)
 $copyright_contributions
 *******************************************************************************/
	./
%End

%Globals
    /.
    import java.io.Reader;

    import $environment_import;
    import org.eclipse.ocl.lpg.BasicEnvironment;
    import org.eclipse.ocl.lpg.DerivedPrsStream;
    import org.eclipse.ocl.lpg.DerivedLexStream;
    import org.eclipse.ocl.util.OCLUtil;
    ./
%End

%Export

	IDENTIFIER
	QUOTED_IDENTIFIER
	INTEGER_LITERAL
	REAL_LITERAL
	STRING_LITERAL

	PLUS
	MINUS
	MULTIPLY
	DIVIDE

	GREATER
	LESS
	EQUAL
	GREATER_EQUAL
	LESS_EQUAL
	NOT_EQUAL

	LPAREN
	RPAREN
	LBRACE
	RBRACE
	LBRACKET
	RBRACKET

	ARROW
	BAR
	COMMA
	COLON
	COLONCOLON
	SEMICOLON
	DOT
	DOTDOT

	SINGLE_LINE_COMMENT
	MULTI_LINE_COMMENT

%End

%Terminals
	CtlCharNotWS

	LF   CR   HT   FF

	a b c d e f g h i j k l m n o p q r s t u v w x y z
	_

	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

	0 1 2 3 4 5 6 7 8 9

	AfterASCIINotAcute
	Space        ::= ' '
	LF           ::= NewLine
	CR           ::= Return
	HT           ::= HorizontalTab
	FF           ::= FormFeed
	DoubleQuote  ::= '"'
	SingleQuote  ::= "'"
	Percent      ::= '%'
	VerticalBar  ::= '|'
	Exclamation  ::= '!'
	AtSign       ::= '@'
	BackQuote    ::= '`'
	Acute        ::= 'Ã¯Â¿Â½'
	Tilde        ::= '~'
	Sharp        ::= '#'
	DollarSign   ::= '$'
	Ampersand    ::= '&'
	Caret        ::= '^'
	Colon        ::= ':'
	SemiColon    ::= ';'
	BackSlash    ::= '\'
	LeftBrace    ::= '{'
	RightBrace   ::= '}'
	LeftBracket  ::= '['
	RightBracket ::= ']'
	QuestionMark ::= '?'
	Comma        ::= ','
	Dot          ::= '.'
	LessThan     ::= '<'
	GreaterThan  ::= '>'
	Plus         ::= '+'
	Minus        ::= '-'
	Slash        ::= '/'
	Star         ::= '*'
	LeftParen    ::= '('
	RightParen   ::= ')'
	Equal        ::= '='

%End

%Start
	Token
%End

%Rules

	---------------------  Rules for Scanned Tokens --------------------------------
	-- The lexer creates an array list of tokens which is defined in the PrsStream class.
	-- A token has three attributes: a start offset, an end offset and a kind.
	--
	-- Only rules that produce complete tokens have actions to create token objects.
	-- When making a token, calls to the methods, $getToken(1) and $getRightSpan(),
	-- provide the offsets (i.e. the span) of a rule's right hand side (rhs) and thus of the token.
	-- For a rule of the form A ::= A1 A2 ... An, the start offset of the rhs of A is given by
	-- $getToken(1) or by $getLeftSpan() and the end offset by $getRightSpan().
	--
	-- Regarding rules for parsing in general, note that for a rhs symbol Ai, the
	-- method $getToken(i) returns the location of the leftmost character derived from Ai.
	-- The method $getLeftSpan(i) returns the same location unless Ai produces %empty in which case
	-- it returns the location of the last character derived before reducing Ai to %empty.
	-- The method $getRightSpan(i) returns the location of the rightmost character derived from Ai
	-- unless Ai produces %empty in which case it returns the location of the last character
	-- derived before reducing Ai to %empty.
	--------------------------------------------------------------------------------
	Token ::= Identifier
		/.$BeginAction
					checkForKeyWord();
		  $EndAction
		./

	-- Deprecated
	Token ::= '"' SLNotDQ '"'
		/.$BeginAction
					makeToken($_IDENTIFIER);
		  $EndAction
		./

	Token ::= '_' SingleQuote SLNotSQOpt SingleQuote
		/.$BeginAction
					makeToken($_QUOTED_IDENTIFIER);
		  $EndAction
		./

	Token ::= SingleQuote SLNotSQOpt SingleQuote
		/.$BeginAction
					makeToken($_STRING_LITERAL);
		  $EndAction
		./

	-- Deprecated
	Token ::= Acute SLNotSQOpt Acute
		/.$BeginAction
					makeToken($_STRING_LITERAL);
		  $EndAction
		./

	-- Deprecated
	Token ::= BackQuote SLNotSQOpt Acute
		/.$BeginAction
					makeToken($_STRING_LITERAL);
		  $EndAction
		./

	Token ::= IntegerLiteral
		/.$NoAction
		./

	Token ::= IntegerLiteral DotToken
		/.$NoAction
		./

	Token ::= IntegerLiteral DotDotToken
		/.$NoAction
		./

	Token ::= RealLiteral
		/.$BeginAction
					makeToken($_REAL_LITERAL);
		  $EndAction
		./

	Token ::= SLC
		/.$BeginAction
					makeComment($_SINGLE_LINE_COMMENT);
		  $EndAction
		./

    Token ::= '/' '*' Inside Stars '/'
        /.$BeginAction
                    makeComment($_MULTI_LINE_COMMENT);
          $EndAction
        ./

	Token ::= WS -- White Space is scanned but not added to output vector
		/.$BeginAction
					skipToken();
		  $EndAction
		./

	Token ::= '+'
		/.$BeginAction
					makeToken($_PLUS);
		  $EndAction
		./

	Token ::= '-'
		/.$BeginAction
					makeToken($_MINUS);
		  $EndAction
		./

	Token ::= '*'
		/.$BeginAction
					makeToken($_MULTIPLY);
		  $EndAction
		./

	Token ::= '/'
		/.$BeginAction
					makeToken($_DIVIDE);
		  $EndAction
		./

	Token ::= '('
		/.$BeginAction
					makeToken($_LPAREN);
		  $EndAction
		./

	Token ::= ')'
		/.$BeginAction
					makeToken($_RPAREN);
		  $EndAction
		./

	Token ::= '>'
		/.$BeginAction
					makeToken($_GREATER);
		  $EndAction
		./

	Token ::= '<'
		/.$BeginAction
					makeToken($_LESS);
		  $EndAction
		./

	Token ::= '='
		/.$BeginAction
					makeToken($_EQUAL);
		  $EndAction
		./

	Token ::= '>' '='
		/.$BeginAction
					makeToken($_GREATER_EQUAL);
		  $EndAction
		./

	Token ::= '<' '='
		/.$BeginAction
					makeToken($_LESS_EQUAL);
		  $EndAction
		./

	Token ::= '<' '>'
		/.$BeginAction
					makeToken($_NOT_EQUAL);
		  $EndAction
		./

	Token ::= '['
		/.$BeginAction
					makeToken($_LBRACKET);
		  $EndAction
		./

	Token ::= ']'
		/.$BeginAction
					makeToken($_RBRACKET);
		  $EndAction
		./

	Token ::= '{'
		/.$BeginAction
					makeToken($_LBRACE);
		  $EndAction
		./

	Token ::= '}'
		/.$BeginAction
					makeToken($_RBRACE);
		  $EndAction
		./

	Token ::= '-' '>'
		/.$BeginAction
					makeToken($_ARROW);
		  $EndAction
		./

	Token ::= '|'
		/.$BeginAction
					makeToken($_BAR);
		  $EndAction
		./

	Token ::= ','
		/.$BeginAction
					makeToken($_COMMA);
		  $EndAction
		./

	Token ::= ':'
		/.$BeginAction
					makeToken($_COLON);
		  $EndAction
		./

	Token ::= ':' ':'
		/.$BeginAction
					makeToken($_COLONCOLON);
		  $EndAction
		./

	Token ::= ';'
		/.$BeginAction
					makeToken($_SEMICOLON);
		  $EndAction
		./

	Token ::= DotToken
		/.$NoAction
		./

	DotToken ::= '.'
		/.$BeginAction
					makeToken($_DOT);
		  $EndAction
		./

	Token ::= DotDotToken
		/.$NoAction
		./

	DotDotToken ::= '.' '.'
		/.$BeginAction
					makeToken($_DOTDOT);
		  $EndAction
		./

    IntegerLiteral ::= Integer
		/.$BeginAction
					makeToken($_INTEGER_LITERAL);
		  $EndAction
		./

    RealLiteral -> Decimal
                 | Decimal Exponent
                 | Integer Exponent

    Inside ::= Inside Stars NotSlashOrStar
             | Inside '/'
             | Inside NotSlashOrStar
             | %empty

    Stars -> '*'
           | Stars '*'

    SLC -> '-' '-'
         | SLC NotEol

    Integer -> Digit
             | Integer Digit

    Decimal -> Integer '.' Integer

    Exponent -> LetterEe Integer
              | LetterEe '-' Integer
              | LetterEe '+' Integer

    WSChar -> Space
            | LF
            | CR
            | HT
            | FF

    Letter -> LowerCaseLetter
            | UpperCaseLetter
            | _
            | AfterASCIINotAcute

    LowerCaseLetter -> a | b | c | d | e | f | g | h | i | j | k | l | m |
                       n | o | p | q | r | s | t | u | v | w | x | y | z

    UpperCaseLetter -> A | B | C | D | E | F | G | H | I | J | K | L | M |
                       N | O | P | Q | R | S | T | U | V | W | X | Y | Z

    Digit -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

    LetterEe -> 'E'
              | 'e'

    WS -> WSChar
        | WS WSChar

    Identifier -> Letter
                | Identifier Letter
                | Identifier Digit
                | Identifier DollarSign

    SpecialNotStar -> '+' | '-' | '/' | '(' | ')' | '"' | '!' | '@' | '`' | '~' |
                      '%' | '&' | '^' | ':' | ';' | "'" | '\' | '|' | '{' | '}' |
                      '[' | ']' | '?' | ',' | '.' | '<' | '>' | '=' | '#' | DollarSign

    SpecialNotSlash -> '+' | '-' | -- exclude the star as well
                       '(' | ')' | '"' | '!' | '@' | '`' | '~' |
                       '%' | '&' | '^' | ':' | ';' | "'" | '\' | '|' | '{' | '}' |
                       '[' | ']' | '?' | ',' | '.' | '<' | '>' | '=' | '#' | DollarSign

    SpecialNotSQNotDQ -> '+' | '-' | '/' | '(' | ')' | '*' | '!' | '@' | '`' | '~' |
                         '%' | '&' | '^' | ':' | ';' | '|' | '{' | '}' |
                         '[' | ']' | '?' | ',' | '.' | '<' | '>' | '=' | '#' | DollarSign

    SpecialNotDQ -> SpecialNotSQNotDQ | "'"
    SpecialNotSQ -> SpecialNotSQNotDQ | '"'

    EscapedSymbols -> NotSQNotDQ | '"' | "'" | '\'
    BackslashEscapedSymbol -> '\' EscapedSymbols

    NotSlashOrStar -> Letter
                    | Digit
                    | SpecialNotSlash
                    | WSChar

    NotEol -> Letter
            | Digit
            | Space
            | '*'
            | SpecialNotStar
            | HT
            | FF
            | CtlCharNotWS

    NotSQNotDQ -> Letter
           | Digit
           | SpecialNotSQNotDQ
           | Space

    NotDQ -> Letter
           | Digit
           | SpecialNotDQ
           | Space
           | BackslashEscapedSymbol

    NotSQ -> Letter
           | Digit
           | SpecialNotSQ
           | Space
           | BackslashEscapedSymbol

	SLNotDQ -> NotDQ
	         | SLNotDQ NotDQ

	SLNotSQ -> NotSQ
	         | SLNotSQ NotSQ

	SLNotSQOpt -> %empty
	            | SLNotSQ

%End


text:
--
-- The $LANG_NAME$ Keyword Lexer
--
%options package=$PACKAGE_NAME$
%options template=$TEMPLATE$F.gi

%Include
    KWLexerLowerCaseMapF.gi
%End

%Export
    -- List all the keywords the kwlexer will export to the lexer and parser
    boolean
    double
    else
    false
    if
    int
    return
    true
    void
    while
%End

%Terminals
    a    b    c    d    e    f    g    h    i    j    k    l    m
    n    o    p    q    r    s    t    u    v    w    x    y    z
%End

%Start
    -- The Goal for the parser is a single Keyword
    Keyword
%End

%Rules
    Keyword ::= b o o l e a n  /.$setResult($_boolean);./
              | d o u b l e    /.$setResult($_double);./
              | e l s e        /.$setResult($_else);./
              | f a l s e      /.$setResult($_false);./
              | i f            /.$setResult($_if);./
              | i n t          /.$setResult($_int);./
              | v o i d        /.$setResult($_void);./
              | r e t u r n    /.$setResult($_return);./
              | t r u e        /.$setResult($_true);./
              | w h i l e      /.$setResult($_while);./
%End

ext: gi

max_stars_repo_name: kuafuwang/LPG-VScode

max_issues_repo_name: kuafuwang/LPG-VScode

max_forks_repo_name: kuafuwang/LPG-VScode


text:
#############################################################################
##
##                             equivalent mappings
##  stack.gi
##                                                          Sergio Siccha
##
##  Copyright 2017 by the authors.
##  This file is free software, see license file.
##
##  Implementation of MyStack
##
#############################################################################

###############################
# Operation StackCreate
# Input:
#   length -
# Filters:
#   IsInt
#
# Output:
#   stack;
###############################
InstallMethod( StackCreate, "Initialize empty stack of given length.",
[ IsInt ],
function( length )
  local stack;
  stack := rec( elements := [], last := 0 );
  stack.elements[ length+1 ] := fail; ## force allocation of storage
  Objectify( StackType, stack );
  return stack;
end );

###############################
# Operation StackPush
# Input:
#   obj -
# Filters:
#   IsObject
#
# Output:
#   none
###############################
InstallMethod( StackPush, "Push obj to stack.",
[ IsMyStack, IsObject ],
function( stack, obj )
  stack!.last := stack!.last + 1;
  stack!.elements[ stack!.last ] := obj;
end );

###############################
# Operation StackPop
# Input:
#   stack -
# Filters:
#   IsMyStack
#
# Output:
#   last element of stack
###############################
InstallMethod( StackPop, "Pop the last object that was added to stack",
[ IsMyStack ],
function( stack )
  stack!.last := stack!.last - 1;
  return stack!.elements[ stack!.last + 1 ];
end );

###############################
# Operation StackPopAll
# Input:
#   stack -
# Filters:
#   IsMyStack
#
# Output:
#   all elements of stack
###############################
InstallMethod( StackPopAll, "Pop all objects of stack.",
[ IsMyStack ],
function( stack )
  local last;
  stack!.last := 0;
  return stack!.elements{ [ 1 .. last ] };
end );

###############################
# Operation StackPeek
# Input:
#   stack -
# Filters:
#   IsMyStack
#
# Output:
#   last element of stack
###############################
InstallMethod( StackPeek, "Peek the last object that was added to stack",
[ IsMyStack ],
function( stack )
  return stack!.elements[ stack!.last ];
end );

###############################
# Operation StackIsEmpty
# Input:
#   stack -
# Filters:
#   IsMyStack
#
# Output:
#   stack!.last = 0;
###############################
InstallMethod( StackIsEmpty, "Checks whether stack is empty.",
[ IsMyStack ],
function( stack )
  return stack!.last = 0;
end );

max_stars_repo_name: ssiccha/equivalent-mappings

max_issues_repo_name: ssiccha/equivalent-mappings

max_forks_repo_name: ssiccha/equivalent-mappings


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

#F RHT( <log2(size)> ) - Rationalized Haar Transform non-terminal
#F
#F Definition: RHT(n) represents the (2^n x 2^n)-matrix defined recursively as:
#F             RHT(1) := DFT_2
#F             RHT(n) := [[ RHT(n-1) tensor [1, 1] ],
#F                        [ I_(n-1)  tensor [1 -1] ]]
#F Note:       I_(n-1) denotes the (2^(n-1) x 2^(n-1)) identity matrix
#F             DFT_2 denotes the matrix [[1, 1], [1, -1]]
#F Example:    RHT(6)
#F             RHT(6).transpose()
Class(RHT, NonTerminal, rec (
    abbrevs := [ n -> Checked(IsInt(n), n > 0, [n]) ],
    dims      := self >> [ 2^self.params[1], 2^self.params[1] ],
    terminate := self >> Cond(
	self.params[1] = 1,  F(2),
	self.transposed, Mat(RationalizedHaarTransform(2^self.params[1])).transpose(),
	                 Mat(RationalizedHaarTransform(2^self.params[1]))),
    isReal := True,
    SmallRandom := () -> [ Random([1..6]) ]
));

RulesFor(RHT, rec(
    #F RHT_Base: (base case) RHT_(2^1) = F_2
    #F
    RHT_Base := rec (
	info             := "RHT_(2^1) -> F_2",
	forTransposition := false,
	isApplicable     := P -> P[1] = 1,
	rule := (P, C) -> F(2)
    ),

    #F RHT_CooleyTukey: RHT_2^(n+1) = (RHT_2^(n) dirsum I_2^n) * (DFT_2 tensor I_2^n) * L
    #F
    RHT_CooleyTukey := rec (
	info             := "RHT_2^(n+1) -> (RHT_2^n dirsum I_n) * (F_2 tensor I_n)",
	isApplicable     := P -> P[1] > 1,
	allChildren      := P -> [[ RHT(P[1] - 1) ]],
	rule := (P, C) ->
	    Inplace(DirectSum(C[1], I(2 ^ (P[1]-1)))) *
	    Tensor(F(2), I(2 ^ (P[1]-1))) *
	    L(2^P[1], 2)
    )
));


text:
--
-- The Java Lexer
--
%Options list
%Options fp=JavaLexer
%options single_productions
%options template=LexerTemplateF.gi
%options filter=GJavaKWLexer.gi
%options lalr=4
$Define
    --
    -- Definition of macro used in the included file LexerBasicMapB.g
    --
    $kw_lexer_class /.$GJavaKWLexer./

$End

$Include
    LexerBasicMapF.gi
$End

--$Include
--    Differ.g
--$End

$Export

    IDENTIFIER

    IntegerLiteral
    LongLiteral
    FloatingPointLiteral
    DoubleLiteral
    CharacterLiteral
    StringLiteral
    PLUS_PLUS
    MINUS_MINUS
    EQUAL_EQUAL
    LESS_EQUAL
    GREATER_EQUAL
    NOT_EQUAL
    LEFT_SHIFT
    RIGHT_SHIFT
    UNSIGNED_RIGHT_SHIFT
    PLUS_EQUAL
    MINUS_EQUAL
    MULTIPLY_EQUAL
    DIVIDE_EQUAL
    AND_EQUAL
    OR_EQUAL
    XOR_EQUAL
    REMAINDER_EQUAL
    LEFT_SHIFT_EQUAL
    RIGHT_SHIFT_EQUAL
    UNSIGNED_RIGHT_SHIFT_EQUAL
    OR_OR
    AND_AND
    PLUS
    MINUS
    NOT
    REMAINDER
    XOR
    AND
    MULTIPLY
    OR
    TWIDDLE
    DIVIDE
    GREATER
    LESS
    LPAREN
    RPAREN
    LBRACE
    RBRACE
    LBRACKET
    RBRACKET
    SEMICOLON
    QUESTION
    AT
    COLON
    COMMA
    DOT
    EQUAL
    ELLIPSIS

$End

$Terminals
    CtlCharNotWS

    LF   CR   HT   FF

    a    b    c    d    e    f    g    h    i    j    k    l    m
    n    o    p    q    r    s    t    u    v    w    x    y    z
    _

    A    B    C    D    E    F    G    H    I    J    K    L    M
    N    O    P    Q    R    S    T    U    V    W    X    Y    Z

    0    1    2    3    4    5    6    7    8    9

    AfterASCII   ::= '\u0080..\ufffe'
    Space        ::= ' '
    LF           ::= NewLine
    CR           ::= Return
    HT           ::= HorizontalTab
    FF           ::= FormFeed
    DoubleQuote  ::= '"'
    SingleQuote  ::= "'"
    Percent      ::= '%'
    VerticalBar  ::= '|'
    Exclamation  ::= '!'
    AtSign       ::= '@'
    BackQuote    ::= '`'
    Tilde        ::= '~'
    Sharp        ::= '#'
    DollarSign   ::= '$'
    Ampersand    ::= '&'
    Caret        ::= '^'
    Colon        ::= ':'
    SemiColon    ::= ';'
    BackSlash    ::= '\'
    LeftBrace    ::= '{'
    RightBrace   ::= '}'
    LeftBracket  ::= '['
    RightBracket ::= ']'
    QuestionMark ::= '?'
    Comma        ::= ','
    Dot          ::= '.'
    LessThan     ::= '<'
    GreaterThan  ::= '>'
    Plus         ::= '+'
    Minus        ::= '-'
    Slash        ::= '/'
    Star         ::= '*'
    LeftParen    ::= '('
    RightParen   ::= ')'
    Equal        ::= '='

$End

%Notice
/.
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2007 IBM Corporation.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
//Contributors:
//    Philippe Charles (pcharles@us.ibm.com) - initial API and implementation

////////////////////////////////////////////////////////////////////////////////
./
%End

$Rules

    Token ::= Identifier
        /.$BeginAction
                    checkForKeyWord();
          $EndAction
        ./
    Token ::= '"' SLBody '"'
        /.$BeginAction
                    makeToken($_StringLiteral);
          $EndAction
        ./
    Token ::= "'" NotSQ "'"
        /.$BeginAction
                    makeToken($_CharacterLiteral);
          $EndAction
        ./
    Token ::= IntegerLiteral
        /.$BeginAction
                    makeToken($_IntegerLiteral);
          $EndAction
        ./
    Token ::= FloatingPointLiteral
        /.$BeginAction
                    makeToken($_FloatingPointLiteral);
          $EndAction
        ./
    Token ::= DoubleLiteral
        /.$BeginAction
                    makeToken($_DoubleLiteral);
          $EndAction
        ./
    Token ::= '/' '*' Inside Stars '/'
        /.$BeginAction
                    skipToken();
          $EndAction
        ./
    Token ::= SLC
        /.$BeginAction
                    skipToken();
          $EndAction
        ./
    Token ::= WS -- White Space is scanned but not added to output vector
        /.$BeginAction
                    skipToken();
          $EndAction
        ./
    Token ::= '+'
        /.$BeginAction
                    makeToken($_PLUS);
          $EndAction
        ./
    Token ::= '-'
        /.$BeginAction
                    makeToken($_MINUS);
          $EndAction
        ./

    Token ::= '*'
        /.$BeginAction
                    makeToken($_MULTIPLY);
          $EndAction
        ./

    Token ::= '/'
        /.$BeginAction
                    makeToken($_DIVIDE);
          $EndAction
        ./

    Token ::= '('
        /.$BeginAction
                    makeToken($_LPAREN);
          $EndAction
        ./

    Token ::= ')'
        /.$BeginAction
                    makeToken($_RPAREN);
          $EndAction
        ./

    Token ::= '='
        /.$BeginAction
                    makeToken($_EQUAL);
          $EndAction
        ./

    Token ::= ','
        /.$BeginAction
                    makeToken($_COMMA);
          $EndAction
        ./

    Token ::= ':'
        /.$BeginAction
                    makeToken($_COLON);
          $EndAction
        ./

    Token ::= ';'
        /.$BeginAction
                    makeToken($_SEMICOLON);
          $EndAction
        ./

    Token ::= '^'
        /.$BeginAction
                    makeToken($_XOR);
          $EndAction
        ./

    Token ::= '%'
        /.$BeginAction
                    makeToken($_REMAINDER);
          $EndAction
        ./

    Token ::= '~'
        /.$BeginAction
                    makeToken($_TWIDDLE);
          $EndAction
        ./

    Token ::= '|'
        /.$BeginAction
                    makeToken($_OR);
          $EndAction
        ./

    Token ::= '&'
        /.$BeginAction
                    makeToken($_AND);
          $EndAction
        ./

    Token ::= '<'
        /.$BeginAction
                    makeToken($_LESS);
          $EndAction
        ./

    Token ::= '>'
        /.$BeginAction
                    makeToken($_GREATER);
          $EndAction
        ./

    Token ::= '.'
        /.$BeginAction
                    makeToken($_DOT);
          $EndAction
        ./

    Token ::= '!'
        /.$BeginAction
                    makeToken($_NOT);
          $EndAction
        ./

    Token ::= '['
        /.$BeginAction
                    makeToken($_LBRACKET);
          $EndAction
        ./

    Token ::= ']'
        /.$BeginAction
                    makeToken($_RBRACKET);
          $EndAction
        ./

    Token ::= '{'
        /.$BeginAction
                    makeToken($_LBRACE);
          $EndAction
        ./

    Token ::= '}'
        /.$BeginAction
                    makeToken($_RBRACE);
          $EndAction
        ./

    Token ::= '?'
        /.$BeginAction
                    makeToken($_QUESTION);
          $EndAction
        ./

    Token ::= '@'
        /.$BeginAction
                    makeToken($_AT);
          $EndAction
        ./

    Token ::= '+' '+'
        /.$BeginAction
                    makeToken($_PLUS_PLUS);
          $EndAction
        ./

    Token ::= '-' '-'
        /.$BeginAction
                    makeToken($_MINUS_MINUS);
          $EndAction
        ./

    Token ::= '=' '='
        /.$BeginAction
                    makeToken($_EQUAL_EQUAL);
          $EndAction
        ./

    Token ::= '<' '='
        /.$BeginAction
                    makeToken($_LESS_EQUAL);
          $EndAction
        ./

    Token ::= '!' '='
        /.$BeginAction
                    makeToken($_NOT_EQUAL);
          $EndAction
        ./

    Token ::= '<' '<'
        /.$BeginAction
                    makeToken($_LEFT_SHIFT);
          $EndAction
        ./

    Token ::= '+' '='
        /.$BeginAction
                    makeToken($_PLUS_EQUAL);
          $EndAction
        ./

    Token ::= '-' '='
        /.$BeginAction
                    makeToken($_MINUS_EQUAL);
          $EndAction
        ./

    Token ::= '*' '='
        /.$BeginAction
                    makeToken($_MULTIPLY_EQUAL);
          $EndAction
        ./

    Token ::= '/' '='
        /.$BeginAction
                    makeToken($_DIVIDE_EQUAL);
          $EndAction
        ./

    Token ::= '&' '='
        /.$BeginAction
                    makeToken($_AND_EQUAL);
          $EndAction
        ./

    Token ::= '|' '='
        /.$BeginAction
                    makeToken($_OR_EQUAL);
          $EndAction
        ./

    Token ::= '^' '='
        /.$BeginAction
                    makeToken($_XOR_EQUAL);
          $EndAction
        ./

    Token ::= '%' '='
        /.$BeginAction
                    makeToken($_REMAINDER_EQUAL);
          $EndAction
        ./

    Token ::= '<' '<' '='
        /.$BeginAction
                    makeToken($_LEFT_SHIFT_EQUAL);
          $EndAction
        ./

    Token ::= '|' '|'
        /.$BeginAction
                    makeToken($_OR_OR);
          $EndAction
        ./

    Token ::= '&' '&'
        /.$BeginAction
                    makeToken($_AND_AND);
          $EndAction
        ./

    Token ::= '.' '.' '.'
        /.$BeginAction
                    makeToken($_ELLIPSIS);
          $EndAction
        ./

    IntegerLiteral -> Integer
                    | Integer LetterLl
                    | '0' LetterXx HexDigits
                    | '0' LetterXx HexDigits LetterLl

    DoubleLiteral -> Decimal
                   | Decimal LetterForD
                   | Decimal Exponent
                   | Decimal Exponent LetterForD
                   | Integer Exponent
                   | Integer Exponent LetterForD
                   | Integer LetterForD

    FloatingPointLiteral -> Decimal LetterForF
                          | Decimal Exponent LetterForF
                          | Integer Exponent LetterForF
                          | Integer LetterForF

    Inside ::= Inside Stars NotSlashOrStar
             | Inside '/'
             | Inside NotSlashOrStar
             | $empty

    Stars -> '*'
           | Stars '*'

    SLC ::= '/' '/'
          | SLC NotEol

    SLBody -> $empty
            | SLBody NotDQ

    Integer -> Digit
             | Integer Digit

    HexDigits -> HexDigit
               | HexDigits HexDigit

    Decimal ::= '.' Integer
              | Integer '.'
              | Integer '.' Integer

    Exponent ::= LetterEe Integer
               | LetterEe '+' Integer
               | LetterEe '-' Integer

    WSChar -> Space
            | LF
            | CR
            | HT
            | FF

    Letter -> LowerCaseLetter
            | UpperCaseLetter
            | _
            | '$'
            | '\u0080..\ufffe'

    LowerCaseLetter -> a | b | c | d | e | f | g | h | i | j | k | l | m |
                       n | o | p | q | r | s | t | u | v | w | x | y | z

    UpperCaseLetter -> A | B | C | D | E | F | G | H | I | J | K | L | M |
                       N | O | P | Q | R | S | T | U | V | W | X | Y | Z

    Digit -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

    OctalDigit -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7

    a..f -> a | b | c | d | e | f | A | B | C | D | E | F

    HexDigit -> Digit
              | a..f

    OctalDigits3 -> OctalDigit
                  | OctalDigit OctalDigit
                  | OctalDigit OctalDigit OctalDigit

    LetterForD -> 'D'
                | 'd'

    LetterForF -> 'F'
                | 'f'

    LetterLl ->  'L'
              | 'l'

    LetterEe -> 'E'
              | 'e'

    LetterXx -> 'X'
              | 'x'

    WS -> WSChar
        | WS WSChar

    Identifier -> Letter
                | Identifier Letter
                | Identifier Digit

    SpecialNotStar -> '+' | '-' | '/' | '(' | ')' | '"' | '!' | '@' | '`' | '~' |
                      '%' | '&' | '^' | ':' | ';' | "'" | '\' | '|' | '{' | '}' |
                      '[' | ']' | '?' | ',' | '.' | '<' | '>' | '=' | '#'

    SpecialNotSlash -> '+' | '-' | -- exclude the star as well
                       '(' | ')' | '"' | '!' | '@' | '`' | '~' |
                       '%' | '&' | '^' | ':' | ';' | "'" | '\' | '|' | '{' | '}' |
                       '[' | ']' | '?' | ',' | '.' | '<' | '>' | '=' | '#'

    SpecialNotDQ -> '+' | '-' | '/' | '(' | ')' | '*' | '!' | '@' | '`' | '~' |
                    '%' | '&' | '^' | ':' | ';' | "'" | '|' | '{' | '}' |
                    '[' | ']' | '?' | ',' | '.' | '<' | '>' | '=' | '#'

    SpecialNotSQ -> '+' | '-' | '*' | '(' | ')' | '"' | '!' | '@' | '`' | '~' |
                    '%' | '&' | '^' | ':' | ';' | '/' | '|' | '{' | '}' |
                    '[' | ']' | '?' | ',' | '.' | '<' | '>' | '=' | '#'

    NotSlashOrStar -> Letter
                    | Digit
                    | SpecialNotSlash
                    | WSChar

    Eol -> LF
         | CR

    NotEol -> Letter
            | Digit
            | Space
            | '*'
            | SpecialNotStar
            | HT
            | FF
            | CtlCharNotWS

    NotDQ -> Letter
           | Digit
           | SpecialNotDQ
           | Space
           | HT
           | FF
           | EscapeSequence
           | '\' u HexDigit HexDigit HexDigit HexDigit
           | '\' OctalDigit

    NotSQ -> Letter
           | Digit
           | SpecialNotSQ
           | Space
           | HT
           | FF
           | EscapeSequence
           | '\' u HexDigit HexDigit HexDigit HexDigit
           | '\' OctalDigits3

    EscapeSequence -> '\' b
                    | '\' t
                    | '\' n
                    | '\' f
                    | '\' r
                    | '\' '"'
                    | '\' "'"
                    | '\' '\'
$End

max_stars_repo_name: kuafuwang/LPGRuntimeCpp

max_issues_repo_name: kuafuwang/LPGRuntimeCpp

max_forks_repo_name: kuafuwang/LPGRuntimeCpp


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

_TL_applicable := (e, p1, p2, p3, p4) ->
    p1 = e.N and p2 = e.n and IsPosInt(p3 / e.l) and p4 = e.r;

SIMD_ISA_DB.buildRules := meth(self)
    local isa;
    for isa in self.active() do
        if self.verbose then Print("Building rules for ", isa, "...\n"); fi;
        isa.buildRules();
    od;
end;

SIMD_ISA.buildRules := meth(self)
    self.rules := rec();
    self.rules.binrules := let(binrules := BuildBinRules(self), Concat(
        binrules,
#        BuildBinRulesLxI(self, binrules, true, true),
        BuildBinRulesLxI(self, binrules, true, false),
        BuildBinRulesLxI(self, binrules, false, true)
    ));
    self.rules.unrules := BuildUnRules(self);
    self.rules.x_I_vby2 := Build_x_I_vby2(self);
    self.rules_built := true;
end;

SIMD_ISA.supportedTL := self >> List(Concat(self.rules.binrules, self.rules.unrules),
        e -> rec(l := e.perm.l, N := e.perm.N, n := e.perm.n, r := e.perm.r));

SIMD_ISA.getTL := (self, p) >> let(res := Filtered(Concat(self.rules.binrules, self.rules.unrules),
        e -> _TL_applicable(e.perm, p[1], p[2], p[3], p[4])), When(Length(res) >= 1, res[1], false));

L_x_I_vby2_code := function(instr, N, n, vby2, y, x)
    local ichain, l, v, l1, l2, op, i;
    v := 2*vby2;
    l := L(N, n).lambda();
    ichain := [];
    for i in [0..N/2-1] do
        l1 := EvalScalar(l.at(2*i).ev());
        l2 := EvalScalar(l.at(2*i+1).ev());
        op := instr[(l1 mod 2)+1][(l2 mod 2)+1];
        Add(ichain, assign(vref(y, v*i, v), op.instr(vref(x, v*QuoInt(l1, 2), v), vref(x, v*QuoInt(l2, 2), v), op.p)));
    od;

    return chain(ichain);
end;

NewRulesFor(TL, rec(
    SIMD_ISA_Bases1 := rec(
        forTransposition := false,
        applicable := (self, t) >> t.isTag(1, AVecReg) and
                                     let(isa := t.firstTag().isa, P:=t.params,
                                         isa.active and ForAny(isa.supportedTL(),
                         e -> _TL_applicable(e, P[1], P[2], P[3], P[4]))
                                     ),
        apply := function(nt,C,cnt)
                    local isa, tl, ll, vprm, P;
            P:=nt.params;
                    isa := nt.firstTag().isa;
                    tl := isa.getTL(P);
                    ll := P[3] / tl.perm.l;
                    vprm := tl.vperm;
                    return When(ll = 1, vprm, BlockVPerm(ll, isa.v, vprm, tl.perm.spl));
                end,
    ),

    SIMD_ISA_Bases2 := rec(
        forTransposition := false,
        applicable := (self, t) >> t.isTag(1, AVecReg) and
                                     let(isa := t.firstTag().isa,
                                         isa.active and t.params[4] = isa.v / 2 and
                                         Flat(isa.rules.x_I_vby2) <> []
                                     ) and not(t.params[1]=t.params[2] or t.params[2]=1),
         apply := function(nt,C,cnt)
                    local isa, vperm, P;
            P:=nt.params;
                    isa := nt.firstTag().isa;
                    vperm := VPerm(Tensor(L(P[1], P[2]), I(P[4])),
                                  (y, x) -> L_x_I_vby2_code(isa.rules.x_I_vby2, P[1], P[2], P[4], y, x),
                                   isa.v, P[1] * P[4] / isa.v);
                    return When(P[3] = 1, vperm, Tensor(I(P[3]), vperm));
                end
    )

));


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

_avxT := (t, opts) -> IsVecT(t) and IsBound(opts.vector) and let( isa := opts.vector.isa,
    Cond( t.t = TReal and t.size = 4, isa=AVX_4x64f,
          t.t = TReal and t.size = 8, isa=AVX_8x32f,
          t.t = TInt  and t.size = 4, isa=AVX_4x64f,
          t.t = TInt  and t.size = 8, isa=AVX_8x32f,
          t.t in [T_Real(64), T_Int(64), T_UInt(64)] and t.size=4, true,
          t.t in [T_Real(32), T_Int(32), T_UInt(32)] and t.size=8, true,
          false));


text:
#############################################################################
##
#W  utils.gi                   automgrp package                Yevgen Muntyan
##                                                             Dmytro Savchuk
##
#Y  Copyright (C) 2003 - 2018 Yevgen Muntyan, Dmytro Savchuk
##

#############################################################################
##
##  AG_PermFromTransformation( <tr> )
##
InstallGlobalFunction(AG_PermFromTransformation,
function(tr)
  if IsPerm(tr) then
    return tr;
  elif tr^-1=fail then
    Error(tr, " is not invertible");
  else
    return AsPermutation(tr);
  fi;
end);

#############################################################################
##
##  AG_PrintTransformation( <tr> )
##
InstallGlobalFunction(AG_PrintTransformation,
function(tr)
  local list, i;
  if IsPerm(tr) then
    Print(tr);
  else
    list := ImageListOfTransformation(tr);
    Print("[");
    for i in [1..Length(list)] do
      if i <> 1 then
        Print(",");
      fi;
      Print(list[i]);
    od;
    Print("]");
  fi;
end);

#############################################################################
##
##  AG_TransformationString( <tr> )
##
InstallGlobalFunction(AG_TransformationString,
function(tr)
  local list, i, str;
  if IsPerm(tr) then
    return String(tr);
  else
    list := ImageListOfTransformation(tr);
    str:="[";
    for i in [1..Length(list)] do
      if i <> 1 then
        Append(str, ",");
      fi;
      Append(str, String(list[i]));
    od;
    Append(str, "]");
  fi;
  return str;
end);

InstallGlobalFunction(AG_TrCmp,
function(p1, p2, d)
  local l1, l2, getlist;

  if IsIdenticalObj(p1, p2) then
    return 0;
  fi;

  getlist := function(p)
    local l;
    if IsTransformation(p) then
      return ImageListOfTransformation(p);
    else
      return Permuted([1..d],p);
    fi;
  end;

  l1 := getlist(p1);
  l2 := getlist(p2);

  if l1 = l2 then
    return 0;
  elif l1 < l2 then
    return -1;
  else
    return 1;
  fi;
end);

#############################################################################
##
##  AG_CalculateWord(<word>, <list>)
##
# XXX do not use this
InstallMethod(AG_CalculateWord, [IsAssocWord, IsList],
function(w, dom)
  local result, i;

  result := One(dom[1]);

  for i in [1..NumberSyllables(w)] do
    result := result * dom[GeneratorSyllable(w, i)]^ExponentSyllable(w, i);
  od;

  return result;
end);

#############################################################################
##
##  AG_CalculateWords(<words_list>, <list>)
##
InstallMethod(AG_CalculateWords, [IsList, IsList],
function(words, domain)
  local result, i;

  result := [];
  for i in [1..Length(words)] do
    result[i] := AG_CalculateWord(words[i], domain);
  od;

  return result;
end);

###############################################################################
##
##  AG_ReducedSphericalIndex(<ind>)
##
InstallGlobalFunction("AG_ReducedSphericalIndex",
function(M)
  local beg, per, beg_len, per_len, i;
  if IsEmpty(M.period) then return StructuralCopy(M); fi;
  beg := StructuralCopy(M.start);
  per := StructuralCopy(M.period);
  beg_len := Length(beg);
  per_len := Length(per);
  for i in Difference(DivisorsInt(per_len), [per_len]) do
    if per = Concatenation(List([1..per_len/i], j -> per{[1..i]})) then
      per := per{[1..i]};
      per_len := i;
      break;
    fi;
  od;
  while Length(beg) <> 0 and beg[beg_len] = per[per_len] do
    per := Concatenation([per[per_len]], per{[1..per_len-1]});
    beg := beg{[1..beg_len-1]};
    beg_len := beg_len - 1;
  od;
  return rec(start := beg, period := per);
end);

###############################################################################
##
##  AG_IsEqualSphericalIndex(<ind1>, <ind2>)
##
InstallGlobalFunction("AG_IsEqualSphericalIndex",
function(M1, M2)
  return AG_ReducedSphericalIndex(M1) = AG_ReducedSphericalIndex(M2);
end);

###############################################################################
##
##  AG_TopDegreeInSphericalIndex(<ind>)
##
InstallGlobalFunction("AG_TopDegreeInSphericalIndex",
function(M)
  if not IsEmpty(M.start) then return M.start[1];
  else return M.period[1]; fi;
end);

###############################################################################
##
##  AG_DegreeOfLevelInSphericalIndex(<ind>)
##
InstallGlobalFunction("AG_DegreeOfLevelInSphericalIndex",
function(M, k)
  local i;
  if Length(M.start) >= k then return M.start[k]; fi;
  i := RemInt(k-Length(M.start), Length(M.period));
  if i = 0 then i := Length(M.period); fi;
  return M.period[i];
end);

###############################################################################
##
##  AG_TreeLevelTuples(<ind>)
##  AG_TreeLevelTuples(<ind>, <n>)
##  AG_TreeLevelTuples(<start>, <period>, <n>)
##
InstallGlobalFunction("AG_TreeLevelTuples",
function(arg)
  local n, m, args, ind, start, period;

  if Length(arg) = 1 and IsList(arg[1]) then
    ind := arg[1];
    n := Length(ind);
    args := List([1..n], i -> [1..ind[i]]);
    Add(args, function(arg) return arg; end);
    return CallFuncList(ListX, args);
  elif Length(arg) = 2 and IsRecord(arg[1]) and IsPosInt(arg[2]) then
    return AG_TreeLevelTuples(arg[1].start, arg[1].period, arg[2]);
  elif Length(arg) = 3 and IsList(arg[1]) and IsList(arg[2]) and IsPosInt(arg[3]) then
    start := arg[1];
    period := arg[2];
    n := arg[3];
    m := n;
    ind := [];
    if Length(start) <> 0 then
      if n <= Length(start) then
        ind := start{[1..n]};
        m := 0;
      else
        ind := start;
        m := n - Length(start);
      fi;
    fi;
    if m > 0 then
      # TODO: why Append doesn't work???
#       Append(ind, Concatenation(List([1..Int(m/Length(period))], i -> period)));
#       Append(ind, period{[1..m-Int(m/Length(period))]});
      ind := Concatenation(ind,
        Concatenation(List([1..Int(m/Length(period))], i -> period)));
      ind := Concatenation(ind, period{[1..m-Int(m/Length(period))]});
    fi;
    args := List([1..n], i -> [1..ind[i]]);
    Add(args, function(arg) return arg; end);
    return CallFuncList(ListX, args);
  else
    Error("in AG_TreeLevelTuples\n",
          "  usage: AG_TreeLevelTuples([n_1, n_2, ..., n_k])\n",
          "         AG_TreeLevelTuples(<spher_ind>, k)\n",
          "         AG_TreeLevelTuples(start, period, k)\n");
  fi;
end);

#############################################################################
##
##  AG_AbelImageX
##  AG_AbelImageSpherTrans
##
InstallGlobalFunction(AG_AbelImageX,
function()
  if not IsReadOnlyGlobal("AG_AbelImageXvar") then
    AG_AbelImageXvar := Indeterminate(GF(2),"x");
    MakeReadOnlyGlobal("AG_AbelImageXvar");
  fi;
  return AG_AbelImageXvar;
end);

InstallGlobalFunction(AG_AbelImageSpherTrans,
function()
  return One(AG_AbelImageX())/ (One(AG_AbelImageX()) + AG_AbelImageX());
end);

#############################################################################
##
##  AG_AbelImageAutomatonInList(<list>)
##
InstallGlobalFunction(AG_AbelImageAutomatonInList,
function(list)
  local zero, one, x, m, mk, e, n, d, s, i, k, det, detk, result;

  n := Length(list);
  d := Length(list[1]) - 1;
  x := AG_AbelImageX();
  m := IdentityMat(n, x);
  e := [];
  zero := 0*x;
  one := x^0;

  for s in [1..n] do
    for i in [1..d] do
      #  if the family is defined by wreath recursion
      if IsList(list[s][i]) then
        for k in [1..Length(list[s][i])] do
          m[s][AbsInt(list[s][i][k])] := m[s][AbsInt(list[s][i][k])] + x;
        od;
      #  if the family is defined by automaton
      else
        m[s][list[s][i]] := m[s][list[s][i]] + x;
      fi;
    od;
    if SignPerm(list[s][d+1]) = 1 then e[s] := zero;
    else e[s] := one; fi;
  od;

  result := [];
  det := Determinant(m);
  for s in [1..n] do
    mk := StructuralCopy(m);
    for i in [1..n] do
      mk[i][s] := e[i];
    od;
    detk := Determinant(mk);
    result[s] := detk / det;
  od;

  return result;
end);

#E

max_stars_repo_name: gap-packages/automgrp

max_issues_repo_name: gap-packages/automgrp

max_forks_repo_name: gap-packages/automgrp


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

# Here we define shorter print functions for common constructs.
# Loading this file will cause more compact printing of formulas,
# but the output can not be pasted back into GAP.
#

Import(spl, code);
var.print := self >> Print(self.id);
fBase.print := (self,i,is) >> Print("[", self.params[2], "]_", self.N);
fTensor.print := FuncClassOper.infix_print(" X ");
fDirsum.print := FuncClassOper.infix_print(" + ");
fCompose.print := FuncClassOper.infix_print(" o ");
gammaTensor.print := FuncClassOper.infix_print(" [#] ");

Value.print := self >> Cond(IsString(self.v), Print("\"",self.v, "\""), Print(self.v));
mId.print := (self,i,is) >> Print("I", self.params[1], ":", self.params[2], "");
fId.print := (self,i,is) >> Print("I", self.params[1]);
Alt.print := (self,i,is) >> Print("<", self.params[1], "|", self.params[2], ">_", self.params[3]);
#Exp.print := self >> self.cprint();


text:
############################################################################
##
##  iterators.gi                   IRREDSOL                 Burkhard Höfling
##
##  Copyright © 2003–2016 Burkhard Höfling
##

############################################################################
##
#F  SelectionIrreducibleSolubleMatrixGroups(n, q, d, indices, orders, blockdims, max)
##
##  selects the subset of <indices> corresponding to those irreducible
##  matrix gropus whose orders are in <orders>, whose minimal block dims are in
##  <blockdims>. if max is true and d = 1, only the maximal soluble groups are returned,
##  if max is false, the non-maximal ones are returned.
##  To ignore one of the parameters orders, blockdims, max, set it to fail
##  If <indices> is fail, all groups are considered.
##
InstallGlobalFunction(SelectionIrreducibleSolubleMatrixGroups,
    function(n0, q0, d, indices, orders, blockdims, max)

        local n, q, p, descs, gddescs, i;

        n := n0/d;
        q := q0^d;

        # info comes from GL(n, q)

        LoadAbsolutelyIrreducibleSolubleGroupData(n, q);

        if indices = fail then
            indices := IndicesIrreducibleSolubleMatrixGroups(n0, q0, d);
        else
            indices := Intersection(indices, IndicesIrreducibleSolubleMatrixGroups(n0, q0, d));
        fi;

        if n = 1 then # from groups of degree 1 - defer to orders

            descs := IRREDSOL_DATA.GROUPS_DIM1 [q];

		 # evaluate max

            if max <> fail then
                if d > 1 then
                    Error("maximality information not available for groups which are not absolutely irreducible");
                fi;

			if max then
			    if Length(descs) in indices then
				  indices := [Length(descs)];
			    else
			        RemoveSet(indices, Length(descs));
                    fi;
			fi;
            fi;

		 # now look at orders
            if orders <> fail then
                indices := Filtered(indices, i -> descs[i][1] in orders);
            fi;

            # block dims

            if blockdims <> fail then
                if d = 1 then
                    if not 1 in blockdims then
                        indices := [];
                    fi;
                else
                    p := SmallestRootInt(q0);
                    i := PositionSet(DivisorsInt(LogInt(q, p)), LogInt(q0, p));
                    indices := Filtered(indices, k -> descs[k][2][i] in blockdims);
                fi;
            fi;

        else # n > 1

            # evluate max

            if max <> fail then
                if max then
                    indices := Intersection(indices, IRREDSOL_DATA.MAX[n][q]);
                else
                    indices := Difference(indices, IRREDSOL_DATA.MAX[n][q]);
                fi;
            fi;

            descs := IRREDSOL_DATA.GROUPS[n][q];
            gddescs := IRREDSOL_DATA.GUARDIANS[n][q];

            if orders <> fail then
                indices := Filtered(indices, i -> descs[i][4] in orders);
            fi;

            if blockdims <> fail then
                if d = 1 then
                    indices := Filtered(indices, i -> gddescs[descs[i][1]][4] in blockdims);
                else
                    p := SmallestRootInt(q0);
                    i := PositionSet(DivisorsInt(LogInt(q, p)), LogInt(q0, p));
                    indices := Filtered(indices, k -> descs[k][3][i] in blockdims);
                fi;
            fi;
        fi;

        MakeImmutable(indices);
        return indices;
    end);

############################################################################
##
#F  OrdersAbsolutelyIrreducibleSolubleMatrixGroups(n, q, blockdims, max)
##
##  returns a set. Each entry is a pair [order, count] describing how many
##  groups of that order are in the data base whose minimal block dims are in <blockdims>
##  if max is true, only the maximal soluble groups are counted, if max is
##  false, the non-maximal ones are returned.
##  To ignore one of the parameters blockdims, max, set it to fail
##
InstallGlobalFunction(OrdersAbsolutelyIrreducibleSolubleMatrixGroups,
    function(n, q, blockdims, max)

        local orders, descs, guardianDescs, desc, guardianDesc, grpinds, i, j, grp, o;

        LoadAbsolutelyIrreducibleSolubleGroupData(n,q);

        if n = 1 then
            if blockdims <> fail and not 1 in blockdims then
                return [];
            fi;
            if max = true then
                return [[IRREDSOL_DATA.GROUPS_DIM1 [q][Length(IRREDSOL_DATA.GROUPS_DIM1 [q])][1],1]];
            else
                orders :=  List(IRREDSOL_DATA.GROUPS_DIM1 [q], d -> [d[1],1]);
                if max = false then
                    Unbind(orders[Length(orders)]);
                fi;
                return orders;
            fi;
        fi;

        descs := IRREDSOL_DATA.GROUPS[n][q];
        guardianDescs := IRREDSOL_DATA.GUARDIANS[n][q];
        if max = true then
            grpinds := IRREDSOL_DATA.MAX[n][q];
        elif max = false then
            grpinds := Difference([1..Length(descs)], IRREDSOL_DATA.MAX[n][q]);
        else
            grpinds := [1..Length(descs)];
        fi;

        orders := [];

        for i in grpinds do
            desc := descs[i]; # description of group
            guardianDesc := guardianDescs[desc[1]]; # and corresponding guardian
            grp := Source (guardianDesc[3]); # pc group isomorphic with guardian
            if (blockdims = fail or guardianDesc[4] in blockdims) then
                o := OrderGroupByCanonicalPcgsByNumber(FamilyPcgs(grp), desc[2]);
                j := PositionSorted(orders, [o,1], function(a, b) return a[1] < b[1]; end);
                if IsBound(orders[j]) and orders[j][1] = o then
                    orders[j][2] := orders[j][2] + 1;
                else
                    Add(orders, [o,1], j);
                fi;
            fi;
        od;
        return orders;
    end);

############################################################################
##
#F  CheckAndExtractArguments(specialfuncs, checks, argl, caller)
##
##  This function tests whether argl is a list of even length in which the
##  entries at odd positions are functions.
##  For special functions in this list (each entry in specialfuncs is a list of synonyms
##  of such functions) it tests whether the following entry in argl satisfies the
##  function in checks corresponding to specailfunc, and that each specialfunc
##  only occurs once (including synonyms).
##
##  The function returns a record with entries specialvalues, functions, and values.
##  if specialvalues[i] is bound, it was the entry following a function in
##  specialfuncs[i]. The functions at odd positions in argl but not in specialfuncs
##  are returned in the record entry functions,
##  the following entries in argl are in the record entry values.
##
InstallGlobalFunction(CheckAndExtractArguments,
    function(specialfuncs, argl, caller)

        local funcs, vals, specialvals, i, f, j;

        if Length(argl) mod 2 <> 0 then
            Error("number of arguments of `", caller, "' must be even");
        fi;
        funcs := [];
        vals := [];
        specialvals := [];
        for i in [1,3..Length(argl)-1] do
            f := argl[i];
            if not IsFunction(f) then
                Error(i, "-th argument in function `", caller, "' must be a function");
            fi;
            if IsHomogeneousList(argl[i+1]) then
                argl[i+1] := Set(argl[i+1]);
            elif IsList(argl[i+1]) then
                argl[i+1] := ShallowCopy (argl[i+1]);
            else
                argl[i+1] := [argl[i+1]];
            fi;
            j := PositionProperty (specialfuncs, funclist -> f in funclist[1]);
            if j = fail then
                Add(funcs, f);
                Add(vals, argl[i+1]);
            elif IsBound(specialvals[j]) then
                Error("there may be only one occurrence of ", f, " in `", caller, "'");
            else
                if not ForAll (argl[i+1], x -> specialfuncs[j][2](x)) then
                    Error("inadmissible value for argument ", i+1, " in `", caller, "'");
                fi;
                specialvals[j] := argl[i+1];
            fi;
        od;
        return rec(specialvalues := specialvals, functions := funcs, values := vals);
    end);

############################################################################
##
#F  IteratorIrreducibleSolubleMatrixGroups(<func_1>, <val_1>, ...)
##
##  see the IRREDSOL manual
##
InstallGlobalFunction(IteratorIrreducibleSolubleMatrixGroups,
    function(arg)

        local r, p, q, k, iter, primes;

        r := CheckAndExtractArguments ([
                [[Degree, DegreeOfMatrixGroup, Dimension, DimensionOfMatrixGroup], IsPosInt],
                [[Characteristic, CharacteristicOfField], p -> IsPosInt(p) and IsPrimeInt(p)],
                [[Field, FieldOfMatrixGroup, TraceField], F -> IsField (F) and IsFinite (F)],
                [[Order, Size], IsPosInt],
                [[MinimalBlockDimension, MinimalBlockDimensionOfMatrixGroup], IsPosInt],
                 [[IsPrimitive, IsPrimitiveMatrixGroup, IsLinearlyPrimitive], x -> x in [true, false]],
                [[IsMaximalAbsolutelyIrreducibleSolubleMatrixGroup], x -> x in [true, false]],
                [[IsAbsolutelyIrreducibleMatrixGroup, IsAbsolutelyIrreducible], x -> x in [true, false]],
                [[SplittingField], F -> IsField (F) and IsFinite (F)]
            ],
            arg,
            "IteratorIrreducibleSolubleMatrixGroups");

        if ForAny (r.specialvalues, v -> IsEmpty(v)) then
            return Iterator ([]);
        fi;

        if not IsBound(r.specialvalues[1]) then
            Error("IteratorIrreducibleSolubleMatrixGroups: You must specify the degree(s) of the desired matrix groups");
        fi;

        if not IsBound(r.specialvalues[3]) then
            Error("IteratorIrreducibleSolubleMatrixGroups: You must specify the field(s) of the desired matrix groups");
        fi;

        # set up data for the iterator record

        iter := rec();
        if Length(r.functions) > 0 then
            iter.testfuncs := r.functions;
            iter.testvals := r.values;
        else
            iter.testfuncs := fail;
        fi;

        iter.dims := r.specialvalues[1];

        if IsBound(r.specialvalues[2]) then # if field characteristic is given
            iter.qs := Filtered(r.specialvalues[3], field -> SmallestRootInt(Size(field)) in r.specialvalues[2]);
        else
            iter.qs := List(r.specialvalues[3], Size);
        fi;

        if IsBound(r.specialvalues[4]) then
            iter.orders := r.specialvalues[4];
        else
            iter.orders := fail;
        fi;

        if IsBound(r.specialvalues[5]) then
            iter.blockdims := r.specialvalues[5];
        else
            iter.blockdims := fail;
        fi;

        if IsBound(r.specialvalues[6]) then
            if Length(r.specialvalues[6]) = 1 then
                iter.primitive := r.specialvalues[6][1];
            else
                Info(InfoWarning, 2, "IteratorIrreducibleSolubleMatrixGroups: `IsPrimitiveMatrixGroup' is redundant - will be ignored");
                iter.primitive := fail;
            fi;
        else
            iter.primitive := fail;
        fi;

        if IsBound(r.specialvalues[7]) then
            if Length(r.specialvalues[7]) > 1 then
                Info(InfoWarning, 2, "IteratorIrreducibleSolubleMatrixGroups: `IsMaximalAbsolutelyIrreducibleSolubleMatrixGroup' is redundant");
                iter.max := fail;
            else
                iter.max := r.specialvalues[7][1];
            fi;
        else
            iter.max := fail;
        fi;

        if IsBound(r.specialvalues[8]) then
            if Length(r.specialvalues[8]) > 1 then
                Info(InfoWarning, 2, "IteratorIrreducibleSolubleMatrixGroups: `IsAbsolutelyIrreducibleSolubleMatrixGroup' is redundant");
                iter.absirred := fail;
            else
                iter.absirred := r.specialvalues[8][1];
                if iter.max = true and iter.absirred = false then
                    Info(InfoWarning, 2, "IteratorIrreducibleSolubleMatrixGroups: values of `IsMaximalAbsolutelyIrreducibleSolubleMatrixGroup' ",
                        "and `IsAbsolutelyIrreducibleSolubleMatrixGroup' contradict each other");
                    return Iterator([]);
                fi;
            fi;
        else
            iter.absirred := fail;
        fi;

        if IsBound(r.specialvalues[9]) then
            iter.split := List(r.specialvalues[9], Size);
        else
            iter.split := fail;
        fi;

        if iter.max = true then
            iter.absirred := true;
        fi;

        # set up start position in iterator, always points to data of next group to read
        # if pos is outside indices, then the next value for d, dim and/or q has to be loaded
        # we mark both iter.d and iter.indices as empty, so that they will be reloaded
        # during the first call to IsDoneIterator

        iter.qi := 1;
        iter.dimi := 0;        # this gets incremented during the first call of IsDoneIterator
                                    # which will also load the data for iter.d and iter.indices
        iter.d := [];
        iter.di := 1;          # mark iter.d as empty
        iter.pos := 1;
        iter.indices := [];  # mark iter.indices as empty

        # add iterator methods

        iter.IsDoneIterator := function(iterator)

            # In order for IsDoneIterator to work in this case, we actually have to look
            # for a new group. If we find a group, it is stored for NextIterator

            local blockdims, dim, divs, d, q, min, max, G, H, gensH, repH, gensG, repG;

            # as a safety measure, make sure that IsDoneIterator can be called
            # after it has returned `true'

            if iterator!.qi > Length(iterator!.qs) then
                return true;
            fi;

            # find next group

            while not IsBound(iterator!.nextGroup) do
                while iterator!.pos > Length(iterator!.indices) do

                    iterator!.di := iterator!.di + 1;
                    while iterator!.di > Length(iterator!.d) do

                        # next dimension
                        iterator!.dimi := iterator!.dimi + 1;

                        if iterator!.dimi > Length(iterator!.dims) then
                            iterator!.dimi := 1;
                            iterator!.qi := iterator!.qi + 1;
                            if iterator!.qi > Length(iterator!.qs) then
                                return true;
                            fi;
                        fi;

                        Info(InfoIrredsol, 1, "searching subgroups of GL(", iterator!.dims[iterator!.dimi], ", ",
                            iterator!.qs[iterator!.qi], ")");

                        # we have a new dimension, store its divisors
                        iterator!.divsdim := DivisorsInt(iterator!.dims[iterator!.dimi]);

                        # set up degrees of splitting field for the construction of groups which are not absolutely irreducible

                        iterator!.di := 1;
                        if iterator!.absirred = true then
                            if iterator!.split = fail or iterator!.qs[iterator!.qi] in iterator!.split then
                                iterator!.d := [1];
                            else
                                iterator!.d := [];
                            fi;
                        else
                            if iterator!.split = fail then
                                iterator!.d := ShallowCopy (iterator!.divsdim);
                            else
                                q := iterator!.qs[iterator!.qi];
                                iterator!.d := Filtered(iterator!.divsdim, t -> q^t in iterator!.split);
                            fi;
                            if iterator!.absirred = false then
                                RemoveSet(iterator!.d, 1);
                            fi;
                        fi;
                    od;

                    dim := iterator!.dims[iterator!.dimi];
                    q := iterator!.qs[iterator!.qi];

                    # get relevant indices for new values of n, q, and d

                    d := iterator!.d[iterator!.di];

                    # merge information about block dims and primitivity

                    if iterator!.primitive = true then
                        if iterator!.blockdims = fail or dim in iterator!.blockdims then
                            blockdims := [dim];
                        else
                            continue;
                        fi;
                    else
                        if iterator!.blockdims = fail then
                            blockdims := ShallowCopy (iterator!.divsdim);
                        else
                            blockdims := Intersection(iterator!.divsdim, iterator!.blockdims);
                        fi;
                        if iterator!.primitive = false then
                            RemoveSet(blockdims, dim);
                        fi;
                    fi;

                    if d = 1 then #absolutely irreducible case
                        max := iterator!.max;
                    elif iterator!.max = true then
                        Error("internal error: iterator!.max is true but trying to construct groups which are not abs. irred");
                    else
                        max := fail;
                    fi;

                    Info(InfoIrredsol, 2, "searching subgroups of GL(", dim, ", ", q, ")",
                            " with splitting field GF(",q, "^",d,"), orders: ", iterator!.orders,
                            " and block dims ", blockdims, " max = ", max);

                    if IsAvailableAbsolutelyIrreducibleSolubleGroupData(dim/d, q^d) then
                        iterator!.indices := SelectionIrreducibleSolubleMatrixGroups(
                            dim, q, d, fail, iterator!.orders, blockdims, max);
                    else
                        Error("group data for GL(", dim/d, ", ",q^d,") is not available. Type \'return;\' to skip these subgroups.");
                        iterator!.indices :=  [];
                    fi;
                    iterator!.pos := 1;
                od;
                G := IrreducibleSolubleMatrixGroup(
                    iterator!.dims[iterator!.dimi],
                    iterator!.qs[iterator!.qi],
                    iterator!.d[iterator!.di],
                    iterator!.indices[iterator!.pos]);
                iterator!.pos := iterator!.pos + 1;

                if iterator!.testfuncs = fail or ForAll ([1..Length(iterator!.testfuncs)], i -> iterator!.testfuncs[i](G) in iterator!.testvals[i]) then
                    iterator!.nextGroup := G;
                fi;
            od;
            return false;
        end;
        iter.NextIterator := function(iterator)

            local G;

            if IsDoneIterator (iterator) then
                Error("iterator already at its end");
            else
                G := iterator!.nextGroup;
                Unbind(iterator!.nextGroup);
                return G;
            fi;
        end;
        iter.ShallowCopy := function(iterator)

                local r;

                # we need not copy lists in iterator, since these are never changed in place
                # and are not documented

                r := rec(
                    IsDoneIterator := iterator!.IsDoneIterator,
                    NextIterator := iterator!.NextIterator,
                    ShallowCopy := iterator!.ShallowCopy,
                    dims := iterator!.dims,
                    dimi := iterator!.dimi,
                    qs := iterator!.qs,
                    qi := iterator!.qi,
                    indices := iterator!.indices,
                    pos := iterator!.pos,
                    d := iterator!.d,
                    di := iterator!.di,
                    split := iterator!.split,
                    orders := iterator!.orders,
                    max := iterator!.max,
                    primitive := iterator!.primitive,
                    blockdims := iterator!.blockdims,
                    absirred := iterator!.absirred,
                    testfuncs := iterator!.testfuncs,
                    testvals := iterator!.testvals);

                if IsBound(iterator!.nextGroup) then
                    r.nextGroup := iterator!.nextGroup;
                fi;
                if IsBound(iterator!.divsdim) then
                    r.divsdim := iterator!.divsdim;
                fi;

                return     r;
            end;
        return IteratorByFunctions(iter);
    end);

############################################################################
##
#F  OneIrreducibleSolubleMatrixGroup(<func_1>, <val_1>, ...)
##
##  see the IRREDSOL manual
##
InstallGlobalFunction(OneIrreducibleSolubleMatrixGroup,
    function(arg)

        local iter;

        iter := CallFuncList(IteratorIrreducibleSolubleMatrixGroups, arg);
        if IsDoneIterator(iter) then
            return fail;
        else
            return NextIterator(iter);
        fi;
    end);

############################################################################
##
#F  AllIrreducibleSolubleMatrixGroups(<func_1>, <val_1>, ...)
##
##  see the IRREDSOL manual
##
InstallGlobalFunction(AllIrreducibleSolubleMatrixGroups,
    function(arg)

        local iter, l, G;

        iter := CallFuncList(IteratorIrreducibleSolubleMatrixGroups, arg);

        l := [];
        for G in iter do
            Add(l, G);
        od;
        return l;
    end);

############################################################################
##
#E
##

max_stars_repo_name: fingolfin/irredsol

max_issues_repo_name: fingolfin/irredsol

max_forks_repo_name: fingolfin/irredsol


text:
package main

import (
	"fmt"
)

type Baggins interface {
	WearRing() bool
}
type Gollum interface {
	Scowl() int
}
type hobbit struct {
	hasRing bool
}

func (h *hobbit) WearRing() bool {
	h.hasRing = !h.hasRing
	return h.hasRing
}

type Wolf struct {
	Claw    int
	HasRing bool
}

func (w *Wolf) Scowl() int {
	w.Claw++
	return w.Claw
}
func battle(g Gollum, b Baggins) (int, bool) {
	return g.Scowl(), b.WearRing()
}
func tryTheTypeSwitch(i interface{}) int {
	switch x := i.(type) {
	case Gollum:
		return x.Scowl()
	case Baggins:
		if x.WearRing() {
			return 1
		}
	}
	return 0
}
//func main() {
	w := &Wolf{}
	bilbo := &hobbit{}
	i0, b0 := battle(w, bilbo)
	i1, b1 := battle(w, bilbo)
	fmt.Printf("i0=%v, b0=%v\n", i0, b0)
	fmt.Printf("i1=%v, b1=%v\n", i1, b1)
	fmt.Printf("tried wolf=%v\n", tryTheTypeSwitch(w))
	fmt.Printf("tried bilbo=%v\n", tryTheTypeSwitch(bilbo))
//}

/*
i0=1, b0=true
i1=2, b1=false
tried wolf=3
tried bilbo=1
*/

max_stars_repo_name: gijit/gi-minimal

max_issues_repo_name: gijit/gi-minimal

max_forks_repo_name: gijit/gi-minimal


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

#F DFT(<size>, [<exp>]) - Discrete Fourier Transform non-terminal
#F                         gcd(size, exp) = 1
#F Definition: (n x n)-matrix [ e^((2*pi*exp*i)*k*l/n) | k,l = 0...n-1 ],
#F             observe that canonical root e^(2*pi*i/n) is exponentiated to <exp>
#F             default exp=1,
#              i = sqrt(-1)
#F Example, direct  : DFT(8) ,
#F          inverse : DFT(8, -1)
#F          rotated : DFT(8, 3)
#F
Class(DFT_NonTerm, TaggedNonTerminal, rec(
    abbrevs := [
    (n)       -> Checked(IsPosIntSym(n),
        [_unwrap(n), 1]),
    (n,k)     -> Checked(IsPosIntSym(n), IsIntSym(k), AnySyms(n,k) or Gcd(_unwrap(n),_unwrap(k))=1,
        [_unwrap(n), When(AnySyms(n,k), k, k mod _unwrap(n))])
    ],

    hashAs := self >> ObjId(self)(self.params[1], 1).withTags(self.getTags()),

    dims := self >> When(self.isReal(), 2* [ self.params[1], self.params[1] ], [ self.params[1], self.params[1] ]),

    terminate := self >> let(N := self.params[1], K := self.params[2],
        t := List([0..N-1], r -> List([0..N-1], c -> E(4*N)^(K*self.omega4pow(r,c)))),
            When(self.isReal(), MatAMat(RC(Mat(t)).toAMat()), Mat(t))),

    isReal := self >> false,
    SmallRandom := () -> Random([2..16]),
    LargeRandom := () -> 2 ^ Random([6..15]),

    normalizedArithCost := self >> let(n := self.params[1],
        floor(5.0 * n * log(n) / log(2.0))),

    TType := T_Complex(TUnknown)
));

Declare(DFT, DFT2, DFT3, DFT4);

Class(DFT, DFT_NonTerm, rec(
    transpose     := self >> DFT(self.params[1], self.params[2]).withTags(self.getTags()),
    conjTranspose := self >> DFT(self.params[1], -self.params[2]).withTags(self.getTags()),
    inverse := self >> self.conjTranspose(),
    omega4pow := (r,c) -> 4*r*c,
    printlatex := (self) >> Print(" \\DFT_{", self.params[1], "} ")
));

DFT1 := DFT;
IDFT := n -> DFT(n,-1);

Class(DFT2, DFT_NonTerm, rec(
    abbrevs := [
    (n)       -> Checked(IsPosIntSym(n),
        [_unwrap(n), 1]),
    (n,k)     -> Checked(IsPosIntSym(n), IsIntSym(k), AnySyms(n,k) or Gcd(_unwrap(n),_unwrap(k))=1,
        [_unwrap(n), When(AnySyms(n,k), k, k mod (2*_unwrap(n)))]),
    ],

    transpose     := self >> DFT3(self.params[1], self.params[2]).withTags(self.getTags()),
    conjTranspose := self >> DFT3(self.params[1], -self.params[2]).withTags(self.getTags()),
    inverse := self >> self.conjTranspose(),
    omega4pow := (r,c) -> 2*r*(2*c+1),
));

Class(DFT3, DFT_NonTerm, rec(
    abbrevs := [
    (n)       -> Checked(IsPosIntSym(n),
        [_unwrap(n), 1]),
    (n,k)     -> Checked(IsPosIntSym(n), IsIntSym(k), AnySyms(n,k) or Gcd(_unwrap(n),_unwrap(k))=1,
        [_unwrap(n), When(AnySyms(n,k), k, k mod (2*_unwrap(n)))]),
    ],

    transpose     := self >> DFT2(self.params[1], self.params[2]).withTags(self.getTags()),
    conjTranspose := self >> DFT2(self.params[1], -self.params[2]).withTags(self.getTags()),
    inverse := self >> self.conjTranspose(),
    omega4pow := (r,c) -> (2*r+1)*2*c,
));

Class(DFT4, DFT_NonTerm, rec(
    abbrevs := [
    (n)       -> Checked(IsPosIntSym(n),
        [_unwrap(n), 1]),
    (n,k)     -> Checked(IsPosIntSym(n), IsIntSym(k), AnySyms(n,k) or Gcd(_unwrap(n),_unwrap(k))=1,
        [_unwrap(n), When(AnySyms(n,k), k, k mod (4*_unwrap(n)))]),
    ],

    transpose     := self >> DFT4(self.params[1], self.params[2]).withTags(self.getTags()),
    conjTranspose := self >> DFT4(self.params[1], -self.params[2]).withTags(self.getTags()),
    inverse := self >> self.conjTranspose(),
    omega4pow := (r,c) -> (2*r+1)*(2*c+1),
));

paramFunc := function(i, m, f, n)
    local res;

#    res := List([0..m-1], e -> SubstBottomUp(Copy(f), i, g -> e));
    res := List([0..m-1], e -> f(e,m));
    res := diagDirsum(res);
    res := fCompose(res, fTensor(fBase(m, i), fId(n)));

    return res;
end;

#F -----------------------------------------------------------------------------
#F Tw1(n, d)
#F Tw1(n, d, k) : diagonal function for Cooley-Tukey FFT, namely
#F   <d> | <n> and
#F   Tw1(n, d, k) = direct_sum_(i = 1)^n/d diag(w_n^0, ..., w_n^(d-1)^i
#F   If the second version is used, w_n is replaced by w_n^k, gcd(<n>, <k>) = 1.
#F
#F -----------------------------------------------------------------------------
Tw1 := (n,d,k) -> Checked(
    IsPosIntSym(n), IsPosIntSym(d), IsIntSym(k),
    fCompose(dOmega(n,k),diagTensor(dLin(div(n,d), 1, 0, TInt), dLin(d, 1, 0, TInt))));

Tw2 := (n,d,k) -> Checked(
    IsPosIntSym(n), IsPosIntSym(d), IsIntSym(k),
    fCompose(dOmega(2*n,k),
         diagTensor(dLin(div(n,d), 2, 1, TInt), dLin(d, 1, 0, TInt))));

Tw3 := (n,d,k) -> Checked(
    IsPosIntSym(n), IsPosIntSym(d), IsIntSym(k),
    fCompose(dOmega(2*n,k),
         diagTensor(dLin(div(n,d), 1, 0, TInt), dLin(d, 2, 1, TInt))));

Tw4 := (n,d,k) -> Checked(
    IsPosIntSym(n), IsPosIntSym(d), IsIntSym(k),
    fCompose(dOmega(4*n,k),
         diagTensor(dLin(div(n,d), 2, 1, TInt), dLin(d, 2, 1, TInt))));

# j-row, i-col
Class(Twid, DiagFunc, rec(
    def := (N, n, rot, a, b, i) -> rec(size:=n),
    lambda := self >> let(
        N := self.params[1], n := self.size, rot := self.params[3],
        a := self.params[4], b := self.params[5], i := self.params[6],
        na := Numerator(a),   nb := Numerator(b),
        da := Denominator(a), db := Denominator(b),
        j := Ind(n),
        Lambda(j, omega(N*da*db, rot*(i*da+na)*(j*db+nb)))),

    range := self >> TComplex,
    domain := self >> self.params[2]
));

Class(ScaledTwid, DiagFunc, rec(
    def := (N, n, k, a, b, i, scaling) -> rec(size:=n),
    lambda := self >> let(N:=self.params[1], n:=self.size, k:=self.params[3],
        a := self.params[4], b := self.params[5], i := self.params[6], scaling := self.params[7],
        na := Numerator(a),   nb := Numerator(b),
        da := Denominator(a), db := Denominator(b),
        j := Ind(n),
        Lambda(j, scaling * omega(N*da*db, k*(i*da+na)*(j*db+nb)))),
    range := self >> TComplex
));

#F TC6(radix, iteration, exp) - diagonal generating function for Stockham algorithm
#F					generates the omega-matrix as described in Van Loin - radix 4 Stockham framework
#F					first parameter of dLin stands for the total dimension of returned function
TC6 := (r, iter, exp) -> Checked(
    IsPosIntSym(r), IsInt(exp),
	fCompose(dOmegaPow(r^(iter+1), 1, exp), dLin(r^iter, 1, 0, TInt)));

#F TC5(radix, iteration) - diagonal generating function for Stockham algorithm - generates a diagonal function
#DP: IsInt(iter) can't be checked, because iter is calculated based on a free variable and not yet evaluated here
TC5 := (r, iter) -> Checked(
    IsPosIntSym(r),
    diagDirsum(fConst(r^iter,1), fCompose(dOmega(r^(iter+1), 1), dLin(r^iter, 1, 0, TInt))));

#F TC4(radix, iteration) - diagonal generating function for Stockham algorithm
#F					generates the omega-matrix as described in Van Loin - Stockham Autosort Network
Class(TC4, DiagFunc, rec(
    abbrevs := [ (rdx, iter, exp) -> [rdx, iter, exp],
	         (rdx, iter, exp) -> [rdx, iter, exp]],
    def := (rdx, iter, exp) -> rec(size := rdx^iter),

    lambda := self >> let(rdx:=self.params[1],
	iter:=self.params[2], n:=rdx^(iter+1), i:=Ind(rdx^iter), exp:=self.params[3],	#n = L (van Loin), i = L/rdx (van Loin)
	Lambda(i, omega(n,i)^exp)),

    range := self >> TInt,
));

Class(Stockham_radix, DiagFunc, rec(
    gen := meth(self, rdx, j)
		local diag;

        if IsInt(rdx) and rdx=2 then
			diag := diagDirsum(TC6(rdx, j, 0), TC6(rdx, j, 1));
		elif rdx = 4 then
			diag := diagDirsum(TC6(rdx, j, 0), TC6(rdx, j, 1), TC6(rdx, j, 2), TC6(rdx, j, 3));
		elif rdx = 8 then
			diag := diagDirsum(TC6(rdx, j, 0), TC6(rdx, j, 1), TC6(rdx, j, 2), TC6(rdx, j, 3), TC6(rdx, j, 4), TC6(rdx, j, 5), TC6(rdx, j, 6), TC6(rdx, j, 7));
		elif rdx = 16 then
			diag := diagDirsum(TC6(rdx, j, 0), TC6(rdx, j, 1), TC6(rdx, j, 2), TC6(rdx, j, 3), TC6(rdx, j, 4), TC6(rdx, j, 5), TC6(rdx, j, 6), TC6(rdx, j, 7),
								TC6(rdx, j, 8), TC6(rdx, j, 9), TC6(rdx, j, 10), TC6(rdx, j, 11), TC6(rdx, j, 12), TC6(rdx, j, 13), TC6(rdx, j, 14), TC6(rdx, j, 15));
		elif rdx > 16 then
            Error("Radix > 16 not supported");
        fi;

        return diag;
    end,

    extract := meth(self, list, elems)
		local i, lc, stride;

		lc := [];
		stride := Length(list)/elems;

		for i in [0..elems-1] do
			lc[i+1] := list[1 + i*stride];
		od;

		return lc;
    end,
));

#F TC2(size, radix, c, k) - diagonal generating function for Pease algorithm
#F
#F TC2 is (5) in Jeremy's Pease paper.
#F
#
# Note: due to current limitations, Spiral is unable to evaluate the
# dimensions of this function properly.
#
# example: TDiag(fPrecompute(TC(N, rdx, j, m)))
#
TC2 := (n, r, c, k) -> Checked(
    IsPosIntSym(n), IsPosIntSym(r), IsPosIntSym(k),
    fCompose(dOmega(n / r^c, k),
	diagTensor(diagTensor(dLin(n/(r^(c+1)), 1, 0, TInt), fConst(r^c, 1)),
		dLin(r, 1, 0, TInt))));

#F TC(size, radix, c, k) - diagonal generating function for Pease algorithm
#F
#F TC is (5) in Jeremy's Pease paper.
#F
Class(TC, DiagFunc, rec(
    abbrevs := [ (n, r, c) -> [n, r, c, 1],
	         (n, r, c, k) -> [n, r, c, k]],
    def := (n, r, c, k) -> rec(size := n),
    lambda := self >> let(n:=self.params[1], r:=self.params[2],
	c:=self.params[3], k:=self.params[4], i:=Ind(n),
	Lambda(i, omega(n/(r^c), k*idiv(i, r^(c+1)) * imod(i, r)))),

    domain := (self) >> self.params[1],
    range := self >> TComplex,
));

#F TCBase(size, radix, k) - diagonal base function for Pease algorithm.
#F This is equivalent to:
#F      L(size,radix) * TC(size, radix, 0, k) * L(size, size/radix).
#F
#F TC is (5) in Jeremy's Pease paper.
#F
Class(TCBase, DiagFunc, rec(
    abbrevs := [ (n, r) -> [n, r, 0, 1],
	         (n, r, k) -> [n, r, 0, k]],
    def := (n, r, c, k) -> rec(size := n-(n/r)),
    lambda := self >> let(n:=self.params[1], r:=self.params[2],
	c:=self.params[3], k:=self.params[4], i:=Ind(n - n/r),
	Lambda(i, omega(n/(r^c), k*idiv(
	    idiv((i+n/r), (r^c)), (n/r^(c+1))) *
		imod(idiv((i+n/r), (r^c)), n/(r^(c+1)))))
		),

    range := self >> TComplex,

));

# TI(n, r, c) - Diagonal generating function for Iterative FFT algorithm
#    where r is the radix, n = size, and c is the iteration
Class(TI, DiagFunc, rec(

    abbrevs := [ (n, r, c) -> [n, r, c, 1],
                 (n, r, c, k) -> [n, r, c, k] ],

    def := (n, r, c, k) -> rec(size := n/(r^c)),
    lambda := self >> let(n:=self.params[1], r:=self.params[2],
	c := self.params[3], k:=self.params[4],
	TC(n/(r^c), r, 0, k).lambda()),

    range := self >> TComplex,
    domain := self >> self.params[1]/(self.params[2]^self.params[3]),
));

# TIFold(n, r, c) - Diagonal generating function for Iterative FFT algorithm
#    where r is the radix, n = size, and c is the iteration.  This is
#    the same as TI, except we will implement it differently because the
#    surrounding structure is not wide enough to perform all the optimizations.
Class(TIFold, DiagFunc, rec(

    abbrevs := [ (n,r,c) -> [n,r, c, 1],
           [ (n, r, c, k) -> [n, r, c, k]]],

    def := (n, r, c, k) -> rec(size := n/(r^c)),
    lambda := self >> let(n:=self.params[1], r:=self.params[2],
	c := self.params[3], k:=self.params[4],
	TC(n/(r^c), r, 0).lambda()),

    range := self >> TComplex,

));

#F ZDFT( <size>, <rshift>, <lshift> )
#F    Discrete Fourier Transform with a cyclic shift on
#F    one or both sides
Class(ZDFT, NonTerminal, rec(
    abbrevs := [ (n,r,l) -> Checked(IsInt(n), n > 0, [n, r, l]) ],
    dims := self >> [ self.params[1], self.params[1] ],

    terminate := self >> let(N:=self.params[1], K:=self.params[2],
    Mat(List([0..N-1],
         r -> List([0..N-1], c -> E(N)^(K*r*c))))),

    transpose := self >> self.__bases__[1](self.params[1], self.params[3], self.params[2]),
    isReal := False,
    SmallRandom := () -> Random([2..16]),
    LargeRandom := () -> 2 ^ Random([6..15])
));

#
# BRDFT(k) = BR(k)*DFT(k)
# This is the same as DRDFT(k,2) = DR(k,2)*DRDFT(k,2)
Class(BRDFT, NonTerminal, rec
(
  abbrevs   := [ (n) -> Checked(IsPosInt(n), [n, []]) ],
#D                 (n, pv) -> Checked(IsPosInt(n), IsList(pv), [n, pv]) ],
  dims      := self >> let(size := self.params[1], [size, size]),
  terminate := self >> Compose(DR(self.params[1], 2), DFT(self.params[1])),
  transpose := self >> Copy(self),
  isReal    := self >> true,
  SmallRandom := () -> Random([2..5]),
  LargeRandom := () -> Random([6..15]),
#D  setpv := meth(self, pv)
#D    local s;
#D    s:= Copy(self);
#D    s.params[2] := pv;
#D    return s;
#D  end,
#D  tagpos := 2

));

#
# DFTBR(k, r) = DFT(k)*BR(k, r)
# This is the same as DFTDR(k,2) = DRDFT(k,2)*BR(k,2)
Class(DFTBR, NonTerminal, rec(
  abbrevs   := [ (n) -> Checked(IsPosInt(n), [n, []]) ],
#D                 (n, pv) -> Checked(IsPosInt(n), IsList(pv), [n, pv]) ],
  dims      := self >> let(size := self.params[1], [size, size]),
  terminate := self >> Compose(DFT(self.params[1]), DR(self.params[1], 2)),
  transpose := self >> Copy(self),
  isReal    := self >> false,
  SmallRandom := () -> Random([2..5]),
  LargeRandom := () -> Random([6..15]),
#D  setpv := meth(self, pv)
#D    local s;
#D    s:= Copy(self);
#D    s.params[2] := pv;
#D    return s;
#D  end,
#D  tagpos := 2

));

Class(DRDFT_Base, TaggedNonTerminal, rec(
  abbrevs   := [ (n,k, r)      -> Checked(IsPosIntSym(n), IsPosIntSym(r), IsInt(k), [n, k, r]) ],
#D                 (n, r, pv) -> Checked(IsPosIntSym(n), IsPosIntSym(r), IsList(pv), [n, r, pv]) ],
  dims      := self >> let(size := self.params[1], [size, size]),
  isReal    := self >> false,
  SmallRandom := () -> Random([2..5]),
  LargeRandom := () -> Random([6..15]),
#D  setpv := meth(self, pv)
#D    local s;
#D    s:= Copy(self);
#D    s.params[3] := pv;
#D    return s;
#D  end,
#D  tagpos := 3
));

Declare(DFTDR);

# DRDFT(n, k, r) = DR(n, r)*DFT(n, k)
#
Class(DRDFT, DRDFT_Base, rec(
  terminate := self >> Compose(DR(self.params[1], self.params[3]), DFT(self.params[1], self.params[2])),
  transpose := self >> ApplyFunc(DFTDR, self.params).withTags(self.getTags()),
));

#
# DFTDR(n, k, r) = DFT(n,k)*DR(n, r)
Class(DFTDR, DRDFT_Base, rec(
  terminate := self >> Compose(DFT(self.params[1], self.params[2]), DR(self.params[1], self.params[3])),
  transpose := self >> ApplyFunc(DRDFT, self.params).withTags(self.getTags()),
));


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

Class(ScratchWrap, rec(
    __call__ := (self, size, nsgmts, linesize) >> Checked(
        Is2Power(size), Is2Power(nsgmts), Is2Power(linesize),

        WithBases(self, rec(
            operations := PrintOps,
            size := size,
            nsgmts := nsgmts,
            linesize := linesize
        ))
    ),

    wrap := (self, r, t, opts) >> let(
        tags := [ALStore(self.size, 1, self.linesize)]
            :: When(IsBound(r.node) and IsBound(r.node.getTags), r.node.getTags(), []),
        tt := GT(r.node, GTPar, GTPar, [1]).withTags(tags),
        rr := AllApplicableRules(tt, opts.breakdownRules),

        Checked(rr <> [],
            rr[1](tt, r))
    ),

    twrap := (self, t, opts) >> let(
        tags := [ALStore(self.size, 1, self.linesize)]
            :: When(IsBound(t._children) and IsBound(t.child(1).getTags), t.child(1).getTags(), []),
        tt := TTensorI(t, self.nsgmts, APar, APar).withTags(tags),

        tt
    ),

    print := (self) >> Print(self.name, "(", self.size, ", ", self.nsgmts, ", ", self.linesize, ")"),
));


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

Class(VWrapBase, rec(
    opts := (self, t, opts) >> opts,
));

Class(VWrapId, VWrapBase, rec(
    __call__ := self >> self,
    wrap := (self,r,t,opts) >> r,
    twrap := (self,t,opts) >> t
));

Class(DPWrapper, SumsBase, BaseContainer, rec(

    _short_print := true,

    new := (self, spl, wrap) >> SPL(WithBases(self, rec(
        _children  := [spl],
        dimensions := spl.dimensions,
        wrap       := wrap,
        ))),

    rChildren := self >> [self._children[1], self.wrap],

    rSetChild := meth(self, n, newC)
        if n=1 then self._children[1] := newC;
        elif n=2 then self.wrap := newC;
        else Error("<n> must be in [1..2]");
        fi;
    end,

    sums := self >> self._children[1].sums(),

    print := (self, i, is) >> Cond(self._short_print,
        Print(self.__name__, "(", self._children[1].print(i+is, is), ", ", self.wrap, ")"),
        Print(self.__name__, "(\n", Blanks(i+is),
	    self._children[1].print(i+is, is), ",\n", Blanks(i+is), self.wrap, "\n", Blanks(i), ")")),

    HashId := self >> let(h := [ When(IsBound(self._children[1].HashId), self._children[1].HashId(), self._children[1]) ],
        When(IsBound(self.tags), Concatenation(h, self.tags), h)),

    vcost := self >> self.child(1).vcost()
));

#F DPSWrapper - wrapper for stackable VWraps;
#F all stackable wrappers applied to formula in _DPSPLRec, innermost first.

Class(DPSWrapper, DPWrapper);

ClassSPL.setWrap := (self, wrap) >> DPWrapper(self, wrap).takeAobj(self);
ClassSPL.addWrap := (self, wrap) >> DPSWrapper(self, wrap).takeAobj(self);


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

# LocalConfig is configured in the user's local _spiral.g (Linux/Unix)
# or _spiral_win.g (Windows) in the Spiral root directory
#
# At a minimum, cpuinfo and osinfo need to be set, see one of those
# above mentioned config files for reference

Declare(LocalConfig, SpiralDefaults);
Class(LocalConfig, rec(
    info := meth(self)
                Print("\nPID: ", GetPid(), "\n");
            end,

    appendSym := self >> When(IsBound(self.osinfo.isWindows) and self.osinfo.isWindows(), "%*", "$*"),

    compilerinfo := rec(
        compiler:= "",
        defaultMode := "none",
        modes := rec(none := ""),
        alignmentSpecifier := ()->"",
        info := ()->Print("compiler info not set"),
    ),

    cpuinfo := rec(
        cpuname:="",
        vendor:="",
        freq:=0,
        default_lang:="",
        isWindows := False,
        isLinux := False,
        is32bit := False,
        is64bit := False,
        nproc := 1,
        SIMDname := False,
        info := ()->Print("CPU info not set"),
        SIMD := () -> spiral.platforms.SIMDArchitectures
    ),

    osinfo := rec(info := ()->Print("OS info not set"),
        isWindows := False,
        isLinux := False,
        isDarwin := False,
        isCygwin := False),

    svninfo := rec(version := "unknown",
        modified := "unknown",
        mixed := "unknown",
        isInit := false,
        info := self >> When(self.isInit, Print("SVN: ", self.version, When(self.modified, " (modified)", "")), Print("SVN info not set"))
    ),

    getOpts := arg >> arg[1].cpuinfo.getOpts(Drop(arg, 1)),

    setTitle := meth(arg)
                    local self, title;
                    self := arg[1];
                    if not IsBound(self.osinfo.setTitle) then return false; fi;
                    if Length(arg)=1 then title := ""; else title := Concat(" - ", arg[2]); fi;
                    self.osinfo.setTitle(Concat("Spiral 5.0", title));
                    return true;
                end
));

HighPerfMixin := rec(
    useDeref := true,
    compileStrategy := compiler.IndicesCS2,
    propagateNth := false
);

SpiralDefaults := CopyFields(SpiralDefaults, rec(
    includes := ["<include/omega64.h>"],
    precision       := "double",
    generateInitFunc := true,
    XType := code.TPtr(code.TReal),
    YType := code.TPtr(code.TReal),
    unifyStoredDataType := false, # false | "input" | "output"
                                  # if non-false, then unifies the datatype of
                                  # precomputed data with the datatype of input (X)
                                  # or output (Y)
    # we implement complex transforms using real vector of 2x size
    dataType        := "real",
    globalUnrolling := 32,
    faultTolerant   := false,
    printWebMeasure := false,

    # compiler options
    finalBinSplit := false,
    declareConstants := false,
    doScalarReplacement := false,
    propagateNth := true,
    inplace := false,

    doSumsUnification := false,
    arrayDataModifier := "static",
    scalarDataModifier := "",
    arrayBufModifier := "static",
    funcModifier := "", # for example "__decl" or "__fastcall"
    valuePostfix := "",

    # How much information Spiral is printing on the terminal.
    # Currently rather few functions are using this.
    verbosity := 1,

    # list of include files in generated C code, eg. ["<math.h>"]
    includes := [],

    formulaStrategies := rec(
        sigmaSpl := [ sigma.StandardSumsRules ],
        preRC    := [],
        rc       := [ sigma.StandardSumsRules ],
        postProcess := [
        (s, opts) -> compiler.BlockSums(opts.globalUnrolling, s),
        (s, opts) -> sigma.Process_fPrecompute(s, opts)
        ]
    ),

    baseHashes := [],
    subParams := [],

    sumsgen := sigma.DefaultSumsGen,
    # breakdownRules limits the used breakdown rules.
    # It must be a record of the form
    # rec(
    #   nonTerm := [ breakdown_rule1, breakdown_rule2, ...],
    #   DFT := [ DFT_Base, DFT_CT ]  <-- example
    # ).
    #
    # By default we set it to ApplicableTable for backwards compatibility with
    # older svn revisions.
    #
    # Functions SwitchRulesOn/Off will work only with breakdownRules==ApplicableTable.
    breakdownRules := formgen.ApplicableTable,

    compileStrategy := compiler.IndicesCS,
    simpIndicesInside := [code.nth, code.tcast, code.deref],
    useDeref := true,
    generateComplexCode := false,

    unparser := compiler.CUnparserProg,
    codegen := compiler.DefaultCodegen,
    TCharCtype :=  "char",
    TUCharCtype := "unsigned char",
    TUIntCtype := "unsigned int",
    TULongLongCtype := "unsigned long long",
    TRealCtype := "double",

    operations := rec(Print := s -> Print("<Spiral options record>")),

    highPerf := self >> CopyFields(self, HighPerfMixin),

    coldcache := false,
));

CplxSpiralDefaults := CopyFields(SpiralDefaults, rec(
    includes := ["<include/complex_gcc_sse2.h>"],
    unparser := compiler.CMacroUnparserProg,
    XType := code.TPtr(code.TComplex),
    YType := code.TPtr(code.TComplex),
    dataType := "complex",
    generateComplexCode := true,
    c99 := rec(
        I := "__I__",
        re := "creal",
        im := "cimag"
        )
));

IntelC99Mixin := rec(
    includes := ["<include/omega64c.h>"],
    unparser := compiler.CUnparserProg,
    XType := code.TPtr(code.TComplex),
    YType := code.TPtr(code.TComplex),
    dataType := "complex",
    generateComplexCode := true,
    c99 := rec(
        I := "__I__",
        re := "creal",
        im := "cimag"
        ),
    TComplexCtype := "_Complex double",
    TRealCtype := "double",
);

IBMC99Mixin := rec(
    includes := ["<include/omega64c.h>"],
    unparser := compiler.CUnparserProg,
    XType := code.TPtr(code.TComplex),
    YType := code.TPtr(code.TComplex),
    dataType := "complex",
    generateComplexCode := true,
    c99 := rec(
        I := "__I",
        re := "_creal",
        im := "_cimag"
        ),
    TComplexCtype := "_Complex double",
    TRealCtype := "double",
    postalign := n -> Print("    __alignx(16,", n, ");\n")
);

# How do we determine if we're running on Windows or Linux?
#Try(Load(iswindows));
#Try(Load(islinux));

#  NOTE: I'd like to pull that out into a function call, but failed to use load/include/read inside a function... => ask YSV
#if LocalConfig.osinfo.isWindows() then
#    Exec(let(sdir:=Conf("spiral_dir"), Concat("SubWCRev.exe ", sdir, " ", Concat(sdir, "\\spiral\\svn_win.src ", sdir, "\\spiral\\svn_info.g > NUL"))));
#    Load(svn_info);
#fi;
#if LocalConfig.osinfo.isLinux() then
# NOTE: For now, assume that any non-windows system is a linux system.
#else
 #   Exec(let(sdir:=Conf("spiral_dir"), Concat(". ", sdir, "/spiral/svn_linux.src ", sdir, " > ", sdir, "/spiral/svn_info.g")));
#    Load(svn_info);
#fi;

compiler.Unparser.fileinfo := meth(self, opts)
    local info;

#    if IsBound(opts.fileinfo) then
#        info := opts.fileinfo;
#        Print("/*\tCPU: ");
#        LocalConfig.cpuinfo.info();
#        Print("\n\tOS: ");
#        LocalConfig.osinfo.info();
#        Print("\n\t");
#        LocalConfig.svninfo.info();
#        if IsBound(opts.profile) then
#            Print("\n\tprofile: ", opts.profile.name, ", ", opts.profile.makeopts.CFLAGS);
#        else
#            Print("\n\tlanguage: ", opts.language);
#        fi;
#        PrintLine("\n\ttimestamp: ", let(t:=Date(), Concat(t[2]," ",StringInt(t[3]),", ",StringInt(t[1]), "; ",StringInt(t[4]),":",StringInt(t[5]),":",StringInt(t[6]))),
#            "\n\ttransform: ", info.algorithm.node , "\n\t",
#            "source file: \"", info.file, "(.c)\"\n\t",
#            "performance: ", info.cycles, " cycles, ", spiral._compute_mflops(info.flops, info.cycles), " Mflop/s\n",
#            "\nalgorithm: ", info.algorithm, "\n",
#        "*/\n");
#    fi;

    if IsBound(opts.fileinfo) then
        info := opts.fileinfo;
        if IsBound(opts.profile) then
            Print("/*\tprofile: ", opts.profile.name, ", ", opts.profile.makeopts.CFLAGS);
        else
            Print("/*\tlanguage: ", opts.language);
        fi;
        PrintLine("\n\ttimestamp: ", let(t:=Date(), Concat(t[2]," ",StringInt(t[3]),", ",StringInt(t[1]), "; ",StringInt(t[4]),":",StringInt(t[5]),":",StringInt(t[6]))),
            "\n",
            "\nalgorithm: ", info.algorithm, "\n",
        "*/\n");
    fi;
end;