// Copyright 2024 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package ast

import (
	"iter"
	"strconv"
)

type internable interface {
	bool | string | int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64
}

type interned struct {
	Refs *internedRefs
}

type internedRefs struct {
	AnyPrefixMatch    Ref
	AnySuffixMatch    Ref
	EndsWith          Ref
	Equal             Ref
	Equality          Ref
	GlobMatch         Ref
	InternalPrint     Ref
	InternalTestCase  Ref
	Member            Ref
	MemberWithKey     Ref
	Or                Ref
	Print             Ref
	RegoMetadataChain Ref
	RegoMetadataRule  Ref
	StartsWith        Ref
}

// NOTE! Great care must be taken **not** to modify the terms returned
// from these functions, as they are shared across all callers.
// This package is currently considered experimental, and may change
// at any time without notice.

var (
	Interned = &interned{
		Refs: &internedRefs{
			AnyPrefixMatch:    AnyPrefixMatch.Ref(),
			AnySuffixMatch:    AnySuffixMatch.Ref(),
			EndsWith:          EndsWith.Ref(),
			Equal:             Equal.Ref(),
			Equality:          Equality.Ref(),
			GlobMatch:         GlobMatch.Ref(),
			InternalPrint:     InternalPrint.Ref(),
			InternalTestCase:  InternalTestCase.Ref(),
			Member:            Member.Ref(),
			MemberWithKey:     MemberWithKey.Ref(),
			Or:                Or.Ref(),
			Print:             Print.Ref(),
			RegoMetadataChain: RegoMetadataChain.Ref(),
			RegoMetadataRule:  RegoMetadataRule.Ref(),
			StartsWith:        StartsWith.Ref(),
		},
	}

	InternedNullValue Value = Null{}
	InternedNullTerm        = NewTerm(InternedNullValue)

	InternedBooleanTrueValue  Value = Boolean(true)
	InternedBooleanFalseValue Value = Boolean(false)
	InternedEmptyStringValue  Value = String("")
	InternedEmptyArrayValue   Value = NewArray()
	InternedEmptyRefValue     Value = Ref{}
	InternedEmptyObjectValue  Value = NewObject()
	InternedEmptySetValue     Value = NewSet()

	InternedBooleanTrue  = NewTerm(InternedBooleanTrueValue)
	InternedBooleanFalse = NewTerm(InternedBooleanFalseValue)
	InternedEmptyString  = NewTerm(InternedEmptyStringValue)
	InternedEmptyObject  = NewTerm(InternedEmptyObjectValue)
	InternedEmptyArray   = NewTerm(InternedEmptyArrayValue)
	InternedEmptySet     = NewTerm(InternedEmptySetValue)

	// since this is by far the most common negative number
	minusOneValue Value = Number("-1")
	minusOneTerm        = NewTerm(minusOneValue)

	internedStringValues = map[string]Value{"": InternedEmptyStringValue}
	internedStringTerms  = map[string]*Term{"": InternedEmptyString}

	internedVarValues = map[string]Value{
		"input":    Var("input"),
		"data":     Var("data"),
		"args":     Var("args"),
		"schema":   Var("schema"),
		"key":      Var("key"),
		"value":    Var("value"),
		"future":   Var("future"),
		"rego":     Var("rego"),
		"set":      Var("set"),
		"internal": Var("internal"),
		"else":     Var("else"),

		"a": Var("a"), "b": Var("b"), "c": Var("c"),
		"i": Var("i"), "j": Var("j"),
		"k": Var("k"), "v": Var("v"),
		"x": Var("x"), "y": Var("y"), "z": Var("z"),

		"allow": Var("allow"), "deny": Var("deny"),
	}
)

// InternStringTerm interns the given strings as terms. Note that Interning is
// considered experimental and should not be relied upon by external code.
// WARNING: This must **only** be called at initialization time, as the
// interned terms are shared globally, and the underlying map is not thread-safe.
func InternStringTerm(str ...string) {
	for _, s := range str {
		if _, ok := internedStringValues[s]; ok {
			continue
		}

		internedStringValues[s] = String(s)
		internedStringTerms[s] = &Term{Value: internedStringValues[s]}
	}
}

// InternVarValue interns the given variable names as Var Values. Note that Interning is
// considered experimental and should not be relied upon by external code.
// WARNING: This must **only** be called at initialization time, as the
// interned terms are shared globally, and the underlying map is not thread-safe.
func InternVarValue(names ...string) {
	for _, name := range names {
		if _, ok := internedVarValues[name]; ok {
			continue
		}

		internedVarValues[name] = Var(name)
	}
}

// HasInternedValue returns true if the given value is interned, otherwise false.
func HasInternedValue[T internable](v T) bool {
	switch value := any(v).(type) {
	case bool:
		return true
	case int:
		return HasInternedIntNumberTerm(value)
	case int8:
		return HasInternedIntNumberTerm(int(value))
	case int16:
		return HasInternedIntNumberTerm(int(value))
	case int32:
		return HasInternedIntNumberTerm(int(value))
	case int64:
		return HasInternedIntNumberTerm(int(value))
	case uint:
		return HasInternedIntNumberTerm(int(value))
	case uint8:
		return HasInternedIntNumberTerm(int(value))
	case uint16:
		return HasInternedIntNumberTerm(int(value))
	case uint32:
		return HasInternedIntNumberTerm(int(value))
	case uint64:
		return HasInternedIntNumberTerm(int(value))
	case string:
		_, ok := internedStringTerms[value]
		return ok
	}
	return false
}

// InternedValue returns an interned Value for scalar v, if the value is
// interned. If the value is not interned, a new Value is returned.
func InternedValue[T internable](v T) Value {
	return InternedValueOr(v, newValue)
}

// InternedVarValue returns an interned Var Value for the given name. If the
// name is not interned, a new Var Value is returned.
func InternedVarValue(name string) Value {
	if v, ok := internedVarValues[name]; ok {
		return v
	}

	return Var(name)
}

// InternedValueOr returns an interned Value for scalar v. Calls supplier
// to produce a Value if the value is not interned.
func InternedValueOr[T internable](v T, supplier func(T) Value) Value {
	switch value := any(v).(type) {
	case bool:
		return internedBooleanValue(value)
	case string:
		return internedStringValue(value)
	case int:
		return internedIntNumberValue(value)
	case int8:
		return internedIntNumberValue(int(value))
	case int16:
		return internedIntNumberValue(int(value))
	case int32:
		return internedIntNumberValue(int(value))
	case int64:
		return internedIntNumberValue(int(value))
	case uint:
		return internedIntNumberValue(int(value))
	case uint8:
		return internedIntNumberValue(int(value))
	case uint16:
		return internedIntNumberValue(int(value))
	case uint32:
		return internedIntNumberValue(int(value))
	case uint64:
		return internedIntNumberValue(int(value))
	}
	return supplier(v)
}

func newValue[T internable](v T) Value {
	switch value := any(v).(type) {
	case bool:
		return Boolean(value)
	case string:
		return String(value)
	case int:
		return Number(strconv.Itoa(value))
	case int8:
		return Number(strconv.Itoa(int(value)))
	case int16:
		return Number(strconv.Itoa(int(value)))
	case int32:
		return Number(strconv.Itoa(int(value)))
	case int64:
		return Number(strconv.Itoa(int(value)))
	case uint:
		return Number(strconv.Itoa(int(value)))
	case uint8:
		return Number(strconv.Itoa(int(value)))
	case uint16:
		return Number(strconv.Itoa(int(value)))
	case uint32:
		return Number(strconv.Itoa(int(value)))
	case uint64:
		return Number(strconv.Itoa(int(value)))
	default:
		panic("unreachable")
	}
}

// Interned returns a possibly interned term for the given scalar value.
// If the value is not interned, a new term is created for that value.
func InternedTerm[T internable](v T) *Term {
	switch value := any(v).(type) {
	case bool:
		return internedBooleanTerm(value)
	case string:
		return internedStringTerm(value)
	case int:
		return internedIntNumberTerm(value)
	case int8:
		return internedIntNumberTerm(int(value))
	case int16:
		return internedIntNumberTerm(int(value))
	case int32:
		return internedIntNumberTerm(int(value))
	case int64:
		return internedIntNumberTerm(int(value))
	case uint:
		return internedIntNumberTerm(int(value))
	case uint8:
		return internedIntNumberTerm(int(value))
	case uint16:
		return internedIntNumberTerm(int(value))
	case uint32:
		return internedIntNumberTerm(int(value))
	case uint64:
		return internedIntNumberTerm(int(value))
	default:
		panic("unreachable")
	}
}

// InternedItem works just like [Item] but returns interned terms for both
// key and value where possible. This is mostly useful for making tests less
// verbose.
func InternedItem[K, V internable](key K, value V) [2]*Term {
	return [2]*Term{InternedTerm(key), InternedTerm(value)}
}

// InternedIntFromString returns a term with the given integer value if the string
// maps to an interned term. If the string does not map to an interned term, nil is
// returned.
func InternedIntNumberTermFromString(s string) *Term {
	if term, ok := stringToIntNumberTermMap[s]; ok {
		return term
	}

	return nil
}

// InternedIntRange returns a sequence of interned integer number terms
// from start (inclusive) to end (exclusive). For values outside of the
// interned range, non-interned IntNumberTerms are returned.
func InternedIntRange(start, end int) iter.Seq[*Term] {
	return func(yield func(*Term) bool) {
		for i := start; i < end; i++ {
			if !yield(internedIntNumberTerm(i)) {
				return
			}
		}
	}
}

// HasInternedIntNumberTerm returns true if the given integer value maps to an interned
// term, otherwise false.
func HasInternedIntNumberTerm(i int) bool {
	return i >= -1 && i < len(intNumberTerms)
}

// InternedStringTermFromNumber returns an interned string term whose value is
// the number's decimal string representation, if that string is interned.
// Returns nil otherwise.
//
// This is an optimisation for the base-10 format_int fast path: for numbers
// like Number("99") the string we want to output is exactly string(n), so we
// can skip strconv.ParseInt and look up the result directly.
func InternedStringTermFromNumber(n Number) *Term {
	return internedStringTerms[string(n)]
}

// Returns an interned string term representing the integer value i, if
// interned. If not, creates a new StringTerm for the integer value.
func InternedIntegerString(i int) *Term {
	// Cheapest option - we don't need to call strconv.Itoa
	if HasInternedIntNumberTerm(i) {
		if interned, ok := internedStringTerms[IntNumberTerm(i).String()]; ok {
			return interned
		}
	}

	// Next cheapest option — the string could still be interned if the store
	// has been extended with more terms than we cucrrently intern.
	s := strconv.Itoa(i)
	if interned, ok := internedStringTerms[s]; ok {
		return interned
	}

	// Nope, create a new term
	return StringTerm(s)
}

func internedBooleanValue(b bool) Value {
	if b {
		return InternedBooleanTrueValue
	}

	return InternedBooleanFalseValue
}

func internedStringValue(s string) Value {
	if v, ok := internedStringValues[s]; ok {
		return v
	}

	return String(s)
}

// InternedBooleanTerm returns an interned term with the given boolean value.
func internedBooleanTerm(b bool) *Term {
	if b {
		return InternedBooleanTrue
	}

	return InternedBooleanFalse
}

func internedIntNumberValue(i int) Value {
	if i >= 0 && i < len(intNumberTerms) {
		return intNumberValues[i]
	}

	if i == -1 {
		return minusOneValue
	}

	return Number(strconv.Itoa(i))
}

// InternedIntNumberTerm returns a term with the given integer value. The term is
// cached between -1 to 512, and for values outside of that range, this function
// is equivalent to IntNumberTerm.
func internedIntNumberTerm(i int) *Term {
	if i >= 0 && i < len(intNumberTerms) {
		return intNumberTerms[i]
	}

	if i == -1 {
		return minusOneTerm
	}

	return &Term{Value: internedIntNumberValue(i)}
}

// InternedStringTerm returns an interned term with the given string value. If the
// provided string is not interned, a new term is created for that value. It does *not*
// modify the global interned terms map.
func internedStringTerm(s string) *Term {
	if term, ok := internedStringTerms[s]; ok {
		return term
	}

	return StringTerm(s)
}

func init() {
	InternStringTerm(
		// Numbers
		"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
		"11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
		"21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38",
		"39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56",
		"57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74",
		"75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92",
		"93", "94", "95", "96", "97", "98", "99", "100",
		// Types
		"null", "boolean", "number", "string", "array", "object", "set", "var", "ref", "true", "false",
		// Runtime
		"config", "env", "version", "commit", "authorization_enabled", "skip_known_schema_check",
		// Annotations
		"annotations", "scope", "title", "entrypoint", "description", "organizations", "authors", "related_resources",
		"schemas", "custom", "name", "email", "schema", "definition", "document", "package", "rule", "subpackages",
		// Debug
		"text", "value", "bindings", "expressions",
		// Various
		"data", "input", "result", "keywords", "path", "v1", "error", "partial",
		// HTTP
		"code", "message", "status_code", "method", "url", "uri", "body", "raw_body", "headers", "query_params",
		// URI
		"scheme", "hostname", "port", "raw_path", "raw_query", "fragment",
		// JWT
		"enc", "cty", "iss", "exp", "nbf", "aud", "secret", "cert",
		// Decisions
		"revision", "labels", "decision_id", "bundles", "query", "mapped_result", "nd_builtin_cache",
		"erased", "masked", "requested_by", "timestamp", "metrics", "req_id",

		// Whitespace
		" ", "\n", "\t",
	)
}

var stringToIntNumberTermMap = map[string]*Term{
	"-1":  minusOneTerm,
	"0":   intNumberTerms[0],
	"1":   intNumberTerms[1],
	"2":   intNumberTerms[2],
	"3":   intNumberTerms[3],
	"4":   intNumberTerms[4],
	"5":   intNumberTerms[5],
	"6":   intNumberTerms[6],
	"7":   intNumberTerms[7],
	"8":   intNumberTerms[8],
	"9":   intNumberTerms[9],
	"10":  intNumberTerms[10],
	"11":  intNumberTerms[11],
	"12":  intNumberTerms[12],
	"13":  intNumberTerms[13],
	"14":  intNumberTerms[14],
	"15":  intNumberTerms[15],
	"16":  intNumberTerms[16],
	"17":  intNumberTerms[17],
	"18":  intNumberTerms[18],
	"19":  intNumberTerms[19],
	"20":  intNumberTerms[20],
	"21":  intNumberTerms[21],
	"22":  intNumberTerms[22],
	"23":  intNumberTerms[23],
	"24":  intNumberTerms[24],
	"25":  intNumberTerms[25],
	"26":  intNumberTerms[26],
	"27":  intNumberTerms[27],
	"28":  intNumberTerms[28],
	"29":  intNumberTerms[29],
	"30":  intNumberTerms[30],
	"31":  intNumberTerms[31],
	"32":  intNumberTerms[32],
	"33":  intNumberTerms[33],
	"34":  intNumberTerms[34],
	"35":  intNumberTerms[35],
	"36":  intNumberTerms[36],
	"37":  intNumberTerms[37],
	"38":  intNumberTerms[38],
	"39":  intNumberTerms[39],
	"40":  intNumberTerms[40],
	"41":  intNumberTerms[41],
	"42":  intNumberTerms[42],
	"43":  intNumberTerms[43],
	"44":  intNumberTerms[44],
	"45":  intNumberTerms[45],
	"46":  intNumberTerms[46],
	"47":  intNumberTerms[47],
	"48":  intNumberTerms[48],
	"49":  intNumberTerms[49],
	"50":  intNumberTerms[50],
	"51":  intNumberTerms[51],
	"52":  intNumberTerms[52],
	"53":  intNumberTerms[53],
	"54":  intNumberTerms[54],
	"55":  intNumberTerms[55],
	"56":  intNumberTerms[56],
	"57":  intNumberTerms[57],
	"58":  intNumberTerms[58],
	"59":  intNumberTerms[59],
	"60":  intNumberTerms[60],
	"61":  intNumberTerms[61],
	"62":  intNumberTerms[62],
	"63":  intNumberTerms[63],
	"64":  intNumberTerms[64],
	"65":  intNumberTerms[65],
	"66":  intNumberTerms[66],
	"67":  intNumberTerms[67],
	"68":  intNumberTerms[68],
	"69":  intNumberTerms[69],
	"70":  intNumberTerms[70],
	"71":  intNumberTerms[71],
	"72":  intNumberTerms[72],
	"73":  intNumberTerms[73],
	"74":  intNumberTerms[74],
	"75":  intNumberTerms[75],
	"76":  intNumberTerms[76],
	"77":  intNumberTerms[77],
	"78":  intNumberTerms[78],
	"79":  intNumberTerms[79],
	"80":  intNumberTerms[80],
	"81":  intNumberTerms[81],
	"82":  intNumberTerms[82],
	"83":  intNumberTerms[83],
	"84":  intNumberTerms[84],
	"85":  intNumberTerms[85],
	"86":  intNumberTerms[86],
	"87":  intNumberTerms[87],
	"88":  intNumberTerms[88],
	"89":  intNumberTerms[89],
	"90":  intNumberTerms[90],
	"91":  intNumberTerms[91],
	"92":  intNumberTerms[92],
	"93":  intNumberTerms[93],
	"94":  intNumberTerms[94],
	"95":  intNumberTerms[95],
	"96":  intNumberTerms[96],
	"97":  intNumberTerms[97],
	"98":  intNumberTerms[98],
	"99":  intNumberTerms[99],
	"100": intNumberTerms[100],
	"101": intNumberTerms[101],
	"102": intNumberTerms[102],
	"103": intNumberTerms[103],
	"104": intNumberTerms[104],
	"105": intNumberTerms[105],
	"106": intNumberTerms[106],
	"107": intNumberTerms[107],
	"108": intNumberTerms[108],
	"109": intNumberTerms[109],
	"110": intNumberTerms[110],
	"111": intNumberTerms[111],
	"112": intNumberTerms[112],
	"113": intNumberTerms[113],
	"114": intNumberTerms[114],
	"115": intNumberTerms[115],
	"116": intNumberTerms[116],
	"117": intNumberTerms[117],
	"118": intNumberTerms[118],
	"119": intNumberTerms[119],
	"120": intNumberTerms[120],
	"121": intNumberTerms[121],
	"122": intNumberTerms[122],
	"123": intNumberTerms[123],
	"124": intNumberTerms[124],
	"125": intNumberTerms[125],
	"126": intNumberTerms[126],
	"127": intNumberTerms[127],
	"128": intNumberTerms[128],
	"129": intNumberTerms[129],
	"130": intNumberTerms[130],
	"131": intNumberTerms[131],
	"132": intNumberTerms[132],
	"133": intNumberTerms[133],
	"134": intNumberTerms[134],
	"135": intNumberTerms[135],
	"136": intNumberTerms[136],
	"137": intNumberTerms[137],
	"138": intNumberTerms[138],
	"139": intNumberTerms[139],
	"140": intNumberTerms[140],
	"141": intNumberTerms[141],
	"142": intNumberTerms[142],
	"143": intNumberTerms[143],
	"144": intNumberTerms[144],
	"145": intNumberTerms[145],
	"146": intNumberTerms[146],
	"147": intNumberTerms[147],
	"148": intNumberTerms[148],
	"149": intNumberTerms[149],
	"150": intNumberTerms[150],
	"151": intNumberTerms[151],
	"152": intNumberTerms[152],
	"153": intNumberTerms[153],
	"154": intNumberTerms[154],
	"155": intNumberTerms[155],
	"156": intNumberTerms[156],
	"157": intNumberTerms[157],
	"158": intNumberTerms[158],
	"159": intNumberTerms[159],
	"160": intNumberTerms[160],
	"161": intNumberTerms[161],
	"162": intNumberTerms[162],
	"163": intNumberTerms[163],
	"164": intNumberTerms[164],
	"165": intNumberTerms[165],
	"166": intNumberTerms[166],
	"167": intNumberTerms[167],
	"168": intNumberTerms[168],
	"169": intNumberTerms[169],
	"170": intNumberTerms[170],
	"171": intNumberTerms[171],
	"172": intNumberTerms[172],
	"173": intNumberTerms[173],
	"174": intNumberTerms[174],
	"175": intNumberTerms[175],
	"176": intNumberTerms[176],
	"177": intNumberTerms[177],
	"178": intNumberTerms[178],
	"179": intNumberTerms[179],
	"180": intNumberTerms[180],
	"181": intNumberTerms[181],
	"182": intNumberTerms[182],
	"183": intNumberTerms[183],
	"184": intNumberTerms[184],
	"185": intNumberTerms[185],
	"186": intNumberTerms[186],
	"187": intNumberTerms[187],
	"188": intNumberTerms[188],
	"189": intNumberTerms[189],
	"190": intNumberTerms[190],
	"191": intNumberTerms[191],
	"192": intNumberTerms[192],
	"193": intNumberTerms[193],
	"194": intNumberTerms[194],
	"195": intNumberTerms[195],
	"196": intNumberTerms[196],
	"197": intNumberTerms[197],
	"198": intNumberTerms[198],
	"199": intNumberTerms[199],
	"200": intNumberTerms[200],
	"201": intNumberTerms[201],
	"202": intNumberTerms[202],
	"203": intNumberTerms[203],
	"204": intNumberTerms[204],
	"205": intNumberTerms[205],
	"206": intNumberTerms[206],
	"207": intNumberTerms[207],
	"208": intNumberTerms[208],
	"209": intNumberTerms[209],
	"210": intNumberTerms[210],
	"211": intNumberTerms[211],
	"212": intNumberTerms[212],
	"213": intNumberTerms[213],
	"214": intNumberTerms[214],
	"215": intNumberTerms[215],
	"216": intNumberTerms[216],
	"217": intNumberTerms[217],
	"218": intNumberTerms[218],
	"219": intNumberTerms[219],
	"220": intNumberTerms[220],
	"221": intNumberTerms[221],
	"222": intNumberTerms[222],
	"223": intNumberTerms[223],
	"224": intNumberTerms[224],
	"225": intNumberTerms[225],
	"226": intNumberTerms[226],
	"227": intNumberTerms[227],
	"228": intNumberTerms[228],
	"229": intNumberTerms[229],
	"230": intNumberTerms[230],
	"231": intNumberTerms[231],
	"232": intNumberTerms[232],
	"233": intNumberTerms[233],
	"234": intNumberTerms[234],
	"235": intNumberTerms[235],
	"236": intNumberTerms[236],
	"237": intNumberTerms[237],
	"238": intNumberTerms[238],
	"239": intNumberTerms[239],
	"240": intNumberTerms[240],
	"241": intNumberTerms[241],
	"242": intNumberTerms[242],
	"243": intNumberTerms[243],
	"244": intNumberTerms[244],
	"245": intNumberTerms[245],
	"246": intNumberTerms[246],
	"247": intNumberTerms[247],
	"248": intNumberTerms[248],
	"249": intNumberTerms[249],
	"250": intNumberTerms[250],
	"251": intNumberTerms[251],
	"252": intNumberTerms[252],
	"253": intNumberTerms[253],
	"254": intNumberTerms[254],
	"255": intNumberTerms[255],
	"256": intNumberTerms[256],
	"257": intNumberTerms[257],
	"258": intNumberTerms[258],
	"259": intNumberTerms[259],
	"260": intNumberTerms[260],
	"261": intNumberTerms[261],
	"262": intNumberTerms[262],
	"263": intNumberTerms[263],
	"264": intNumberTerms[264],
	"265": intNumberTerms[265],
	"266": intNumberTerms[266],
	"267": intNumberTerms[267],
	"268": intNumberTerms[268],
	"269": intNumberTerms[269],
	"270": intNumberTerms[270],
	"271": intNumberTerms[271],
	"272": intNumberTerms[272],
	"273": intNumberTerms[273],
	"274": intNumberTerms[274],
	"275": intNumberTerms[275],
	"276": intNumberTerms[276],
	"277": intNumberTerms[277],
	"278": intNumberTerms[278],
	"279": intNumberTerms[279],
	"280": intNumberTerms[280],
	"281": intNumberTerms[281],
	"282": intNumberTerms[282],
	"283": intNumberTerms[283],
	"284": intNumberTerms[284],
	"285": intNumberTerms[285],
	"286": intNumberTerms[286],
	"287": intNumberTerms[287],
	"288": intNumberTerms[288],
	"289": intNumberTerms[289],
	"290": intNumberTerms[290],
	"291": intNumberTerms[291],
	"292": intNumberTerms[292],
	"293": intNumberTerms[293],
	"294": intNumberTerms[294],
	"295": intNumberTerms[295],
	"296": intNumberTerms[296],
	"297": intNumberTerms[297],
	"298": intNumberTerms[298],
	"299": intNumberTerms[299],
	"300": intNumberTerms[300],
	"301": intNumberTerms[301],
	"302": intNumberTerms[302],
	"303": intNumberTerms[303],
	"304": intNumberTerms[304],
	"305": intNumberTerms[305],
	"306": intNumberTerms[306],
	"307": intNumberTerms[307],
	"308": intNumberTerms[308],
	"309": intNumberTerms[309],
	"310": intNumberTerms[310],
	"311": intNumberTerms[311],
	"312": intNumberTerms[312],
	"313": intNumberTerms[313],
	"314": intNumberTerms[314],
	"315": intNumberTerms[315],
	"316": intNumberTerms[316],
	"317": intNumberTerms[317],
	"318": intNumberTerms[318],
	"319": intNumberTerms[319],
	"320": intNumberTerms[320],
	"321": intNumberTerms[321],
	"322": intNumberTerms[322],
	"323": intNumberTerms[323],
	"324": intNumberTerms[324],
	"325": intNumberTerms[325],
	"326": intNumberTerms[326],
	"327": intNumberTerms[327],
	"328": intNumberTerms[328],
	"329": intNumberTerms[329],
	"330": intNumberTerms[330],
	"331": intNumberTerms[331],
	"332": intNumberTerms[332],
	"333": intNumberTerms[333],
	"334": intNumberTerms[334],
	"335": intNumberTerms[335],
	"336": intNumberTerms[336],
	"337": intNumberTerms[337],
	"338": intNumberTerms[338],
	"339": intNumberTerms[339],
	"340": intNumberTerms[340],
	"341": intNumberTerms[341],
	"342": intNumberTerms[342],
	"343": intNumberTerms[343],
	"344": intNumberTerms[344],
	"345": intNumberTerms[345],
	"346": intNumberTerms[346],
	"347": intNumberTerms[347],
	"348": intNumberTerms[348],
	"349": intNumberTerms[349],
	"350": intNumberTerms[350],
	"351": intNumberTerms[351],
	"352": intNumberTerms[352],
	"353": intNumberTerms[353],
	"354": intNumberTerms[354],
	"355": intNumberTerms[355],
	"356": intNumberTerms[356],
	"357": intNumberTerms[357],
	"358": intNumberTerms[358],
	"359": intNumberTerms[359],
	"360": intNumberTerms[360],
	"361": intNumberTerms[361],
	"362": intNumberTerms[362],
	"363": intNumberTerms[363],
	"364": intNumberTerms[364],
	"365": intNumberTerms[365],
	"366": intNumberTerms[366],
	"367": intNumberTerms[367],
	"368": intNumberTerms[368],
	"369": intNumberTerms[369],
	"370": intNumberTerms[370],
	"371": intNumberTerms[371],
	"372": intNumberTerms[372],
	"373": intNumberTerms[373],
	"374": intNumberTerms[374],
	"375": intNumberTerms[375],
	"376": intNumberTerms[376],
	"377": intNumberTerms[377],
	"378": intNumberTerms[378],
	"379": intNumberTerms[379],
	"380": intNumberTerms[380],
	"381": intNumberTerms[381],
	"382": intNumberTerms[382],
	"383": intNumberTerms[383],
	"384": intNumberTerms[384],
	"385": intNumberTerms[385],
	"386": intNumberTerms[386],
	"387": intNumberTerms[387],
	"388": intNumberTerms[388],
	"389": intNumberTerms[389],
	"390": intNumberTerms[390],
	"391": intNumberTerms[391],
	"392": intNumberTerms[392],
	"393": intNumberTerms[393],
	"394": intNumberTerms[394],
	"395": intNumberTerms[395],
	"396": intNumberTerms[396],
	"397": intNumberTerms[397],
	"398": intNumberTerms[398],
	"399": intNumberTerms[399],
	"400": intNumberTerms[400],
	"401": intNumberTerms[401],
	"402": intNumberTerms[402],
	"403": intNumberTerms[403],
	"404": intNumberTerms[404],
	"405": intNumberTerms[405],
	"406": intNumberTerms[406],
	"407": intNumberTerms[407],
	"408": intNumberTerms[408],
	"409": intNumberTerms[409],
	"410": intNumberTerms[410],
	"411": intNumberTerms[411],
	"412": intNumberTerms[412],
	"413": intNumberTerms[413],
	"414": intNumberTerms[414],
	"415": intNumberTerms[415],
	"416": intNumberTerms[416],
	"417": intNumberTerms[417],
	"418": intNumberTerms[418],
	"419": intNumberTerms[419],
	"420": intNumberTerms[420],
	"421": intNumberTerms[421],
	"422": intNumberTerms[422],
	"423": intNumberTerms[423],
	"424": intNumberTerms[424],
	"425": intNumberTerms[425],
	"426": intNumberTerms[426],
	"427": intNumberTerms[427],
	"428": intNumberTerms[428],
	"429": intNumberTerms[429],
	"430": intNumberTerms[430],
	"431": intNumberTerms[431],
	"432": intNumberTerms[432],
	"433": intNumberTerms[433],
	"434": intNumberTerms[434],
	"435": intNumberTerms[435],
	"436": intNumberTerms[436],
	"437": intNumberTerms[437],
	"438": intNumberTerms[438],
	"439": intNumberTerms[439],
	"440": intNumberTerms[440],
	"441": intNumberTerms[441],
	"442": intNumberTerms[442],
	"443": intNumberTerms[443],
	"444": intNumberTerms[444],
	"445": intNumberTerms[445],
	"446": intNumberTerms[446],
	"447": intNumberTerms[447],
	"448": intNumberTerms[448],
	"449": intNumberTerms[449],
	"450": intNumberTerms[450],
	"451": intNumberTerms[451],
	"452": intNumberTerms[452],
	"453": intNumberTerms[453],
	"454": intNumberTerms[454],
	"455": intNumberTerms[455],
	"456": intNumberTerms[456],
	"457": intNumberTerms[457],
	"458": intNumberTerms[458],
	"459": intNumberTerms[459],
	"460": intNumberTerms[460],
	"461": intNumberTerms[461],
	"462": intNumberTerms[462],
	"463": intNumberTerms[463],
	"464": intNumberTerms[464],
	"465": intNumberTerms[465],
	"466": intNumberTerms[466],
	"467": intNumberTerms[467],
	"468": intNumberTerms[468],
	"469": intNumberTerms[469],
	"470": intNumberTerms[470],
	"471": intNumberTerms[471],
	"472": intNumberTerms[472],
	"473": intNumberTerms[473],
	"474": intNumberTerms[474],
	"475": intNumberTerms[475],
	"476": intNumberTerms[476],
	"477": intNumberTerms[477],
	"478": intNumberTerms[478],
	"479": intNumberTerms[479],
	"480": intNumberTerms[480],
	"481": intNumberTerms[481],
	"482": intNumberTerms[482],
	"483": intNumberTerms[483],
	"484": intNumberTerms[484],
	"485": intNumberTerms[485],
	"486": intNumberTerms[486],
	"487": intNumberTerms[487],
	"488": intNumberTerms[488],
	"489": intNumberTerms[489],
	"490": intNumberTerms[490],
	"491": intNumberTerms[491],
	"492": intNumberTerms[492],
	"493": intNumberTerms[493],
	"494": intNumberTerms[494],
	"495": intNumberTerms[495],
	"496": intNumberTerms[496],
	"497": intNumberTerms[497],
	"498": intNumberTerms[498],
	"499": intNumberTerms[499],
	"500": intNumberTerms[500],
	"501": intNumberTerms[501],
	"502": intNumberTerms[502],
	"503": intNumberTerms[503],
	"504": intNumberTerms[504],
	"505": intNumberTerms[505],
	"506": intNumberTerms[506],
	"507": intNumberTerms[507],
	"508": intNumberTerms[508],
	"509": intNumberTerms[509],
	"510": intNumberTerms[510],
	"511": intNumberTerms[511],
	"512": intNumberTerms[512],
}

var intNumberValues = [...]Value{
	Number("0"),
	Number("1"),
	Number("2"),
	Number("3"),
	Number("4"),
	Number("5"),
	Number("6"),
	Number("7"),
	Number("8"),
	Number("9"),
	Number("10"),
	Number("11"),
	Number("12"),
	Number("13"),
	Number("14"),
	Number("15"),
	Number("16"),
	Number("17"),
	Number("18"),
	Number("19"),
	Number("20"),
	Number("21"),
	Number("22"),
	Number("23"),
	Number("24"),
	Number("25"),
	Number("26"),
	Number("27"),
	Number("28"),
	Number("29"),
	Number("30"),
	Number("31"),
	Number("32"),
	Number("33"),
	Number("34"),
	Number("35"),
	Number("36"),
	Number("37"),
	Number("38"),
	Number("39"),
	Number("40"),
	Number("41"),
	Number("42"),
	Number("43"),
	Number("44"),
	Number("45"),
	Number("46"),
	Number("47"),
	Number("48"),
	Number("49"),
	Number("50"),
	Number("51"),
	Number("52"),
	Number("53"),
	Number("54"),
	Number("55"),
	Number("56"),
	Number("57"),
	Number("58"),
	Number("59"),
	Number("60"),
	Number("61"),
	Number("62"),
	Number("63"),
	Number("64"),
	Number("65"),
	Number("66"),
	Number("67"),
	Number("68"),
	Number("69"),
	Number("70"),
	Number("71"),
	Number("72"),
	Number("73"),
	Number("74"),
	Number("75"),
	Number("76"),
	Number("77"),
	Number("78"),
	Number("79"),
	Number("80"),
	Number("81"),
	Number("82"),
	Number("83"),
	Number("84"),
	Number("85"),
	Number("86"),
	Number("87"),
	Number("88"),
	Number("89"),
	Number("90"),
	Number("91"),
	Number("92"),
	Number("93"),
	Number("94"),
	Number("95"),
	Number("96"),
	Number("97"),
	Number("98"),
	Number("99"),
	Number("100"),
	Number("101"),
	Number("102"),
	Number("103"),
	Number("104"),
	Number("105"),
	Number("106"),
	Number("107"),
	Number("108"),
	Number("109"),
	Number("110"),
	Number("111"),
	Number("112"),
	Number("113"),
	Number("114"),
	Number("115"),
	Number("116"),
	Number("117"),
	Number("118"),
	Number("119"),
	Number("120"),
	Number("121"),
	Number("122"),
	Number("123"),
	Number("124"),
	Number("125"),
	Number("126"),
	Number("127"),
	Number("128"),
	Number("129"),
	Number("130"),
	Number("131"),
	Number("132"),
	Number("133"),
	Number("134"),
	Number("135"),
	Number("136"),
	Number("137"),
	Number("138"),
	Number("139"),
	Number("140"),
	Number("141"),
	Number("142"),
	Number("143"),
	Number("144"),
	Number("145"),
	Number("146"),
	Number("147"),
	Number("148"),
	Number("149"),
	Number("150"),
	Number("151"),
	Number("152"),
	Number("153"),
	Number("154"),
	Number("155"),
	Number("156"),
	Number("157"),
	Number("158"),
	Number("159"),
	Number("160"),
	Number("161"),
	Number("162"),
	Number("163"),
	Number("164"),
	Number("165"),
	Number("166"),
	Number("167"),
	Number("168"),
	Number("169"),
	Number("170"),
	Number("171"),
	Number("172"),
	Number("173"),
	Number("174"),
	Number("175"),
	Number("176"),
	Number("177"),
	Number("178"),
	Number("179"),
	Number("180"),
	Number("181"),
	Number("182"),
	Number("183"),
	Number("184"),
	Number("185"),
	Number("186"),
	Number("187"),
	Number("188"),
	Number("189"),
	Number("190"),
	Number("191"),
	Number("192"),
	Number("193"),
	Number("194"),
	Number("195"),
	Number("196"),
	Number("197"),
	Number("198"),
	Number("199"),
	Number("200"),
	Number("201"),
	Number("202"),
	Number("203"),
	Number("204"),
	Number("205"),
	Number("206"),
	Number("207"),
	Number("208"),
	Number("209"),
	Number("210"),
	Number("211"),
	Number("212"),
	Number("213"),
	Number("214"),
	Number("215"),
	Number("216"),
	Number("217"),
	Number("218"),
	Number("219"),
	Number("220"),
	Number("221"),
	Number("222"),
	Number("223"),
	Number("224"),
	Number("225"),
	Number("226"),
	Number("227"),
	Number("228"),
	Number("229"),
	Number("230"),
	Number("231"),
	Number("232"),
	Number("233"),
	Number("234"),
	Number("235"),
	Number("236"),
	Number("237"),
	Number("238"),
	Number("239"),
	Number("240"),
	Number("241"),
	Number("242"),
	Number("243"),
	Number("244"),
	Number("245"),
	Number("246"),
	Number("247"),
	Number("248"),
	Number("249"),
	Number("250"),
	Number("251"),
	Number("252"),
	Number("253"),
	Number("254"),
	Number("255"),
	Number("256"),
	Number("257"),
	Number("258"),
	Number("259"),
	Number("260"),
	Number("261"),
	Number("262"),
	Number("263"),
	Number("264"),
	Number("265"),
	Number("266"),
	Number("267"),
	Number("268"),
	Number("269"),
	Number("270"),
	Number("271"),
	Number("272"),
	Number("273"),
	Number("274"),
	Number("275"),
	Number("276"),
	Number("277"),
	Number("278"),
	Number("279"),
	Number("280"),
	Number("281"),
	Number("282"),
	Number("283"),
	Number("284"),
	Number("285"),
	Number("286"),
	Number("287"),
	Number("288"),
	Number("289"),
	Number("290"),
	Number("291"),
	Number("292"),
	Number("293"),
	Number("294"),
	Number("295"),
	Number("296"),
	Number("297"),
	Number("298"),
	Number("299"),
	Number("300"),
	Number("301"),
	Number("302"),
	Number("303"),
	Number("304"),
	Number("305"),
	Number("306"),
	Number("307"),
	Number("308"),
	Number("309"),
	Number("310"),
	Number("311"),
	Number("312"),
	Number("313"),
	Number("314"),
	Number("315"),
	Number("316"),
	Number("317"),
	Number("318"),
	Number("319"),
	Number("320"),
	Number("321"),
	Number("322"),
	Number("323"),
	Number("324"),
	Number("325"),
	Number("326"),
	Number("327"),
	Number("328"),
	Number("329"),
	Number("330"),
	Number("331"),
	Number("332"),
	Number("333"),
	Number("334"),
	Number("335"),
	Number("336"),
	Number("337"),
	Number("338"),
	Number("339"),
	Number("340"),
	Number("341"),
	Number("342"),
	Number("343"),
	Number("344"),
	Number("345"),
	Number("346"),
	Number("347"),
	Number("348"),
	Number("349"),
	Number("350"),
	Number("351"),
	Number("352"),
	Number("353"),
	Number("354"),
	Number("355"),
	Number("356"),
	Number("357"),
	Number("358"),
	Number("359"),
	Number("360"),
	Number("361"),
	Number("362"),
	Number("363"),
	Number("364"),
	Number("365"),
	Number("366"),
	Number("367"),
	Number("368"),
	Number("369"),
	Number("370"),
	Number("371"),
	Number("372"),
	Number("373"),
	Number("374"),
	Number("375"),
	Number("376"),
	Number("377"),
	Number("378"),
	Number("379"),
	Number("380"),
	Number("381"),
	Number("382"),
	Number("383"),
	Number("384"),
	Number("385"),
	Number("386"),
	Number("387"),
	Number("388"),
	Number("389"),
	Number("390"),
	Number("391"),
	Number("392"),
	Number("393"),
	Number("394"),
	Number("395"),
	Number("396"),
	Number("397"),
	Number("398"),
	Number("399"),
	Number("400"),
	Number("401"),
	Number("402"),
	Number("403"),
	Number("404"),
	Number("405"),
	Number("406"),
	Number("407"),
	Number("408"),
	Number("409"),
	Number("410"),
	Number("411"),
	Number("412"),
	Number("413"),
	Number("414"),
	Number("415"),
	Number("416"),
	Number("417"),
	Number("418"),
	Number("419"),
	Number("420"),
	Number("421"),
	Number("422"),
	Number("423"),
	Number("424"),
	Number("425"),
	Number("426"),
	Number("427"),
	Number("428"),
	Number("429"),
	Number("430"),
	Number("431"),
	Number("432"),
	Number("433"),
	Number("434"),
	Number("435"),
	Number("436"),
	Number("437"),
	Number("438"),
	Number("439"),
	Number("440"),
	Number("441"),
	Number("442"),
	Number("443"),
	Number("444"),
	Number("445"),
	Number("446"),
	Number("447"),
	Number("448"),
	Number("449"),
	Number("450"),
	Number("451"),
	Number("452"),
	Number("453"),
	Number("454"),
	Number("455"),
	Number("456"),
	Number("457"),
	Number("458"),
	Number("459"),
	Number("460"),
	Number("461"),
	Number("462"),
	Number("463"),
	Number("464"),
	Number("465"),
	Number("466"),
	Number("467"),
	Number("468"),
	Number("469"),
	Number("470"),
	Number("471"),
	Number("472"),
	Number("473"),
	Number("474"),
	Number("475"),
	Number("476"),
	Number("477"),
	Number("478"),
	Number("479"),
	Number("480"),
	Number("481"),
	Number("482"),
	Number("483"),
	Number("484"),
	Number("485"),
	Number("486"),
	Number("487"),
	Number("488"),
	Number("489"),
	Number("490"),
	Number("491"),
	Number("492"),
	Number("493"),
	Number("494"),
	Number("495"),
	Number("496"),
	Number("497"),
	Number("498"),
	Number("499"),
	Number("500"),
	Number("501"),
	Number("502"),
	Number("503"),
	Number("504"),
	Number("505"),
	Number("506"),
	Number("507"),
	Number("508"),
	Number("509"),
	Number("510"),
	Number("511"),
	Number("512"),
}

var intNumberTerms = [...]*Term{
	{Value: intNumberValues[0]},
	{Value: intNumberValues[1]},
	{Value: intNumberValues[2]},
	{Value: intNumberValues[3]},
	{Value: intNumberValues[4]},
	{Value: intNumberValues[5]},
	{Value: intNumberValues[6]},
	{Value: intNumberValues[7]},
	{Value: intNumberValues[8]},
	{Value: intNumberValues[9]},
	{Value: intNumberValues[10]},
	{Value: intNumberValues[11]},
	{Value: intNumberValues[12]},
	{Value: intNumberValues[13]},
	{Value: intNumberValues[14]},
	{Value: intNumberValues[15]},
	{Value: intNumberValues[16]},
	{Value: intNumberValues[17]},
	{Value: intNumberValues[18]},
	{Value: intNumberValues[19]},
	{Value: intNumberValues[20]},
	{Value: intNumberValues[21]},
	{Value: intNumberValues[22]},
	{Value: intNumberValues[23]},
	{Value: intNumberValues[24]},
	{Value: intNumberValues[25]},
	{Value: intNumberValues[26]},
	{Value: intNumberValues[27]},
	{Value: intNumberValues[28]},
	{Value: intNumberValues[29]},
	{Value: intNumberValues[30]},
	{Value: intNumberValues[31]},
	{Value: intNumberValues[32]},
	{Value: intNumberValues[33]},
	{Value: intNumberValues[34]},
	{Value: intNumberValues[35]},
	{Value: intNumberValues[36]},
	{Value: intNumberValues[37]},
	{Value: intNumberValues[38]},
	{Value: intNumberValues[39]},
	{Value: intNumberValues[40]},
	{Value: intNumberValues[41]},
	{Value: intNumberValues[42]},
	{Value: intNumberValues[43]},
	{Value: intNumberValues[44]},
	{Value: intNumberValues[45]},
	{Value: intNumberValues[46]},
	{Value: intNumberValues[47]},
	{Value: intNumberValues[48]},
	{Value: intNumberValues[49]},
	{Value: intNumberValues[50]},
	{Value: intNumberValues[51]},
	{Value: intNumberValues[52]},
	{Value: intNumberValues[53]},
	{Value: intNumberValues[54]},
	{Value: intNumberValues[55]},
	{Value: intNumberValues[56]},
	{Value: intNumberValues[57]},
	{Value: intNumberValues[58]},
	{Value: intNumberValues[59]},
	{Value: intNumberValues[60]},
	{Value: intNumberValues[61]},
	{Value: intNumberValues[62]},
	{Value: intNumberValues[63]},
	{Value: intNumberValues[64]},
	{Value: intNumberValues[65]},
	{Value: intNumberValues[66]},
	{Value: intNumberValues[67]},
	{Value: intNumberValues[68]},
	{Value: intNumberValues[69]},
	{Value: intNumberValues[70]},
	{Value: intNumberValues[71]},
	{Value: intNumberValues[72]},
	{Value: intNumberValues[73]},
	{Value: intNumberValues[74]},
	{Value: intNumberValues[75]},
	{Value: intNumberValues[76]},
	{Value: intNumberValues[77]},
	{Value: intNumberValues[78]},
	{Value: intNumberValues[79]},
	{Value: intNumberValues[80]},
	{Value: intNumberValues[81]},
	{Value: intNumberValues[82]},
	{Value: intNumberValues[83]},
	{Value: intNumberValues[84]},
	{Value: intNumberValues[85]},
	{Value: intNumberValues[86]},
	{Value: intNumberValues[87]},
	{Value: intNumberValues[88]},
	{Value: intNumberValues[89]},
	{Value: intNumberValues[90]},
	{Value: intNumberValues[91]},
	{Value: intNumberValues[92]},
	{Value: intNumberValues[93]},
	{Value: intNumberValues[94]},
	{Value: intNumberValues[95]},
	{Value: intNumberValues[96]},
	{Value: intNumberValues[97]},
	{Value: intNumberValues[98]},
	{Value: intNumberValues[99]},
	{Value: intNumberValues[100]},
	{Value: intNumberValues[101]},
	{Value: intNumberValues[102]},
	{Value: intNumberValues[103]},
	{Value: intNumberValues[104]},
	{Value: intNumberValues[105]},
	{Value: intNumberValues[106]},
	{Value: intNumberValues[107]},
	{Value: intNumberValues[108]},
	{Value: intNumberValues[109]},
	{Value: intNumberValues[110]},
	{Value: intNumberValues[111]},
	{Value: intNumberValues[112]},
	{Value: intNumberValues[113]},
	{Value: intNumberValues[114]},
	{Value: intNumberValues[115]},
	{Value: intNumberValues[116]},
	{Value: intNumberValues[117]},
	{Value: intNumberValues[118]},
	{Value: intNumberValues[119]},
	{Value: intNumberValues[120]},
	{Value: intNumberValues[121]},
	{Value: intNumberValues[122]},
	{Value: intNumberValues[123]},
	{Value: intNumberValues[124]},
	{Value: intNumberValues[125]},
	{Value: intNumberValues[126]},
	{Value: intNumberValues[127]},
	{Value: intNumberValues[128]},
	{Value: intNumberValues[129]},
	{Value: intNumberValues[130]},
	{Value: intNumberValues[131]},
	{Value: intNumberValues[132]},
	{Value: intNumberValues[133]},
	{Value: intNumberValues[134]},
	{Value: intNumberValues[135]},
	{Value: intNumberValues[136]},
	{Value: intNumberValues[137]},
	{Value: intNumberValues[138]},
	{Value: intNumberValues[139]},
	{Value: intNumberValues[140]},
	{Value: intNumberValues[141]},
	{Value: intNumberValues[142]},
	{Value: intNumberValues[143]},
	{Value: intNumberValues[144]},
	{Value: intNumberValues[145]},
	{Value: intNumberValues[146]},
	{Value: intNumberValues[147]},
	{Value: intNumberValues[148]},
	{Value: intNumberValues[149]},
	{Value: intNumberValues[150]},
	{Value: intNumberValues[151]},
	{Value: intNumberValues[152]},
	{Value: intNumberValues[153]},
	{Value: intNumberValues[154]},
	{Value: intNumberValues[155]},
	{Value: intNumberValues[156]},
	{Value: intNumberValues[157]},
	{Value: intNumberValues[158]},
	{Value: intNumberValues[159]},
	{Value: intNumberValues[160]},
	{Value: intNumberValues[161]},
	{Value: intNumberValues[162]},
	{Value: intNumberValues[163]},
	{Value: intNumberValues[164]},
	{Value: intNumberValues[165]},
	{Value: intNumberValues[166]},
	{Value: intNumberValues[167]},
	{Value: intNumberValues[168]},
	{Value: intNumberValues[169]},
	{Value: intNumberValues[170]},
	{Value: intNumberValues[171]},
	{Value: intNumberValues[172]},
	{Value: intNumberValues[173]},
	{Value: intNumberValues[174]},
	{Value: intNumberValues[175]},
	{Value: intNumberValues[176]},
	{Value: intNumberValues[177]},
	{Value: intNumberValues[178]},
	{Value: intNumberValues[179]},
	{Value: intNumberValues[180]},
	{Value: intNumberValues[181]},
	{Value: intNumberValues[182]},
	{Value: intNumberValues[183]},
	{Value: intNumberValues[184]},
	{Value: intNumberValues[185]},
	{Value: intNumberValues[186]},
	{Value: intNumberValues[187]},
	{Value: intNumberValues[188]},
	{Value: intNumberValues[189]},
	{Value: intNumberValues[190]},
	{Value: intNumberValues[191]},
	{Value: intNumberValues[192]},
	{Value: intNumberValues[193]},
	{Value: intNumberValues[194]},
	{Value: intNumberValues[195]},
	{Value: intNumberValues[196]},
	{Value: intNumberValues[197]},
	{Value: intNumberValues[198]},
	{Value: intNumberValues[199]},
	{Value: intNumberValues[200]},
	{Value: intNumberValues[201]},
	{Value: intNumberValues[202]},
	{Value: intNumberValues[203]},
	{Value: intNumberValues[204]},
	{Value: intNumberValues[205]},
	{Value: intNumberValues[206]},
	{Value: intNumberValues[207]},
	{Value: intNumberValues[208]},
	{Value: intNumberValues[209]},
	{Value: intNumberValues[210]},
	{Value: intNumberValues[211]},
	{Value: intNumberValues[212]},
	{Value: intNumberValues[213]},
	{Value: intNumberValues[214]},
	{Value: intNumberValues[215]},
	{Value: intNumberValues[216]},
	{Value: intNumberValues[217]},
	{Value: intNumberValues[218]},
	{Value: intNumberValues[219]},
	{Value: intNumberValues[220]},
	{Value: intNumberValues[221]},
	{Value: intNumberValues[222]},
	{Value: intNumberValues[223]},
	{Value: intNumberValues[224]},
	{Value: intNumberValues[225]},
	{Value: intNumberValues[226]},
	{Value: intNumberValues[227]},
	{Value: intNumberValues[228]},
	{Value: intNumberValues[229]},
	{Value: intNumberValues[230]},
	{Value: intNumberValues[231]},
	{Value: intNumberValues[232]},
	{Value: intNumberValues[233]},
	{Value: intNumberValues[234]},
	{Value: intNumberValues[235]},
	{Value: intNumberValues[236]},
	{Value: intNumberValues[237]},
	{Value: intNumberValues[238]},
	{Value: intNumberValues[239]},
	{Value: intNumberValues[240]},
	{Value: intNumberValues[241]},
	{Value: intNumberValues[242]},
	{Value: intNumberValues[243]},
	{Value: intNumberValues[244]},
	{Value: intNumberValues[245]},
	{Value: intNumberValues[246]},
	{Value: intNumberValues[247]},
	{Value: intNumberValues[248]},
	{Value: intNumberValues[249]},
	{Value: intNumberValues[250]},
	{Value: intNumberValues[251]},
	{Value: intNumberValues[252]},
	{Value: intNumberValues[253]},
	{Value: intNumberValues[254]},
	{Value: intNumberValues[255]},
	{Value: intNumberValues[256]},
	{Value: intNumberValues[257]},
	{Value: intNumberValues[258]},
	{Value: intNumberValues[259]},
	{Value: intNumberValues[260]},
	{Value: intNumberValues[261]},
	{Value: intNumberValues[262]},
	{Value: intNumberValues[263]},
	{Value: intNumberValues[264]},
	{Value: intNumberValues[265]},
	{Value: intNumberValues[266]},
	{Value: intNumberValues[267]},
	{Value: intNumberValues[268]},
	{Value: intNumberValues[269]},
	{Value: intNumberValues[270]},
	{Value: intNumberValues[271]},
	{Value: intNumberValues[272]},
	{Value: intNumberValues[273]},
	{Value: intNumberValues[274]},
	{Value: intNumberValues[275]},
	{Value: intNumberValues[276]},
	{Value: intNumberValues[277]},
	{Value: intNumberValues[278]},
	{Value: intNumberValues[279]},
	{Value: intNumberValues[280]},
	{Value: intNumberValues[281]},
	{Value: intNumberValues[282]},
	{Value: intNumberValues[283]},
	{Value: intNumberValues[284]},
	{Value: intNumberValues[285]},
	{Value: intNumberValues[286]},
	{Value: intNumberValues[287]},
	{Value: intNumberValues[288]},
	{Value: intNumberValues[289]},
	{Value: intNumberValues[290]},
	{Value: intNumberValues[291]},
	{Value: intNumberValues[292]},
	{Value: intNumberValues[293]},
	{Value: intNumberValues[294]},
	{Value: intNumberValues[295]},
	{Value: intNumberValues[296]},
	{Value: intNumberValues[297]},
	{Value: intNumberValues[298]},
	{Value: intNumberValues[299]},
	{Value: intNumberValues[300]},
	{Value: intNumberValues[301]},
	{Value: intNumberValues[302]},
	{Value: intNumberValues[303]},
	{Value: intNumberValues[304]},
	{Value: intNumberValues[305]},
	{Value: intNumberValues[306]},
	{Value: intNumberValues[307]},
	{Value: intNumberValues[308]},
	{Value: intNumberValues[309]},
	{Value: intNumberValues[310]},
	{Value: intNumberValues[311]},
	{Value: intNumberValues[312]},
	{Value: intNumberValues[313]},
	{Value: intNumberValues[314]},
	{Value: intNumberValues[315]},
	{Value: intNumberValues[316]},
	{Value: intNumberValues[317]},
	{Value: intNumberValues[318]},
	{Value: intNumberValues[319]},
	{Value: intNumberValues[320]},
	{Value: intNumberValues[321]},
	{Value: intNumberValues[322]},
	{Value: intNumberValues[323]},
	{Value: intNumberValues[324]},
	{Value: intNumberValues[325]},
	{Value: intNumberValues[326]},
	{Value: intNumberValues[327]},
	{Value: intNumberValues[328]},
	{Value: intNumberValues[329]},
	{Value: intNumberValues[330]},
	{Value: intNumberValues[331]},
	{Value: intNumberValues[332]},
	{Value: intNumberValues[333]},
	{Value: intNumberValues[334]},
	{Value: intNumberValues[335]},
	{Value: intNumberValues[336]},
	{Value: intNumberValues[337]},
	{Value: intNumberValues[338]},
	{Value: intNumberValues[339]},
	{Value: intNumberValues[340]},
	{Value: intNumberValues[341]},
	{Value: intNumberValues[342]},
	{Value: intNumberValues[343]},
	{Value: intNumberValues[344]},
	{Value: intNumberValues[345]},
	{Value: intNumberValues[346]},
	{Value: intNumberValues[347]},
	{Value: intNumberValues[348]},
	{Value: intNumberValues[349]},
	{Value: intNumberValues[350]},
	{Value: intNumberValues[351]},
	{Value: intNumberValues[352]},
	{Value: intNumberValues[353]},
	{Value: intNumberValues[354]},
	{Value: intNumberValues[355]},
	{Value: intNumberValues[356]},
	{Value: intNumberValues[357]},
	{Value: intNumberValues[358]},
	{Value: intNumberValues[359]},
	{Value: intNumberValues[360]},
	{Value: intNumberValues[361]},
	{Value: intNumberValues[362]},
	{Value: intNumberValues[363]},
	{Value: intNumberValues[364]},
	{Value: intNumberValues[365]},
	{Value: intNumberValues[366]},
	{Value: intNumberValues[367]},
	{Value: intNumberValues[368]},
	{Value: intNumberValues[369]},
	{Value: intNumberValues[370]},
	{Value: intNumberValues[371]},
	{Value: intNumberValues[372]},
	{Value: intNumberValues[373]},
	{Value: intNumberValues[374]},
	{Value: intNumberValues[375]},
	{Value: intNumberValues[376]},
	{Value: intNumberValues[377]},
	{Value: intNumberValues[378]},
	{Value: intNumberValues[379]},
	{Value: intNumberValues[380]},
	{Value: intNumberValues[381]},
	{Value: intNumberValues[382]},
	{Value: intNumberValues[383]},
	{Value: intNumberValues[384]},
	{Value: intNumberValues[385]},
	{Value: intNumberValues[386]},
	{Value: intNumberValues[387]},
	{Value: intNumberValues[388]},
	{Value: intNumberValues[389]},
	{Value: intNumberValues[390]},
	{Value: intNumberValues[391]},
	{Value: intNumberValues[392]},
	{Value: intNumberValues[393]},
	{Value: intNumberValues[394]},
	{Value: intNumberValues[395]},
	{Value: intNumberValues[396]},
	{Value: intNumberValues[397]},
	{Value: intNumberValues[398]},
	{Value: intNumberValues[399]},
	{Value: intNumberValues[400]},
	{Value: intNumberValues[401]},
	{Value: intNumberValues[402]},
	{Value: intNumberValues[403]},
	{Value: intNumberValues[404]},
	{Value: intNumberValues[405]},
	{Value: intNumberValues[406]},
	{Value: intNumberValues[407]},
	{Value: intNumberValues[408]},
	{Value: intNumberValues[409]},
	{Value: intNumberValues[410]},
	{Value: intNumberValues[411]},
	{Value: intNumberValues[412]},
	{Value: intNumberValues[413]},
	{Value: intNumberValues[414]},
	{Value: intNumberValues[415]},
	{Value: intNumberValues[416]},
	{Value: intNumberValues[417]},
	{Value: intNumberValues[418]},
	{Value: intNumberValues[419]},
	{Value: intNumberValues[420]},
	{Value: intNumberValues[421]},
	{Value: intNumberValues[422]},
	{Value: intNumberValues[423]},
	{Value: intNumberValues[424]},
	{Value: intNumberValues[425]},
	{Value: intNumberValues[426]},
	{Value: intNumberValues[427]},
	{Value: intNumberValues[428]},
	{Value: intNumberValues[429]},
	{Value: intNumberValues[430]},
	{Value: intNumberValues[431]},
	{Value: intNumberValues[432]},
	{Value: intNumberValues[433]},
	{Value: intNumberValues[434]},
	{Value: intNumberValues[435]},
	{Value: intNumberValues[436]},
	{Value: intNumberValues[437]},
	{Value: intNumberValues[438]},
	{Value: intNumberValues[439]},
	{Value: intNumberValues[440]},
	{Value: intNumberValues[441]},
	{Value: intNumberValues[442]},
	{Value: intNumberValues[443]},
	{Value: intNumberValues[444]},
	{Value: intNumberValues[445]},
	{Value: intNumberValues[446]},
	{Value: intNumberValues[447]},
	{Value: intNumberValues[448]},
	{Value: intNumberValues[449]},
	{Value: intNumberValues[450]},
	{Value: intNumberValues[451]},
	{Value: intNumberValues[452]},
	{Value: intNumberValues[453]},
	{Value: intNumberValues[454]},
	{Value: intNumberValues[455]},
	{Value: intNumberValues[456]},
	{Value: intNumberValues[457]},
	{Value: intNumberValues[458]},
	{Value: intNumberValues[459]},
	{Value: intNumberValues[460]},
	{Value: intNumberValues[461]},
	{Value: intNumberValues[462]},
	{Value: intNumberValues[463]},
	{Value: intNumberValues[464]},
	{Value: intNumberValues[465]},
	{Value: intNumberValues[466]},
	{Value: intNumberValues[467]},
	{Value: intNumberValues[468]},
	{Value: intNumberValues[469]},
	{Value: intNumberValues[470]},
	{Value: intNumberValues[471]},
	{Value: intNumberValues[472]},
	{Value: intNumberValues[473]},
	{Value: intNumberValues[474]},
	{Value: intNumberValues[475]},
	{Value: intNumberValues[476]},
	{Value: intNumberValues[477]},
	{Value: intNumberValues[478]},
	{Value: intNumberValues[479]},
	{Value: intNumberValues[480]},
	{Value: intNumberValues[481]},
	{Value: intNumberValues[482]},
	{Value: intNumberValues[483]},
	{Value: intNumberValues[484]},
	{Value: intNumberValues[485]},
	{Value: intNumberValues[486]},
	{Value: intNumberValues[487]},
	{Value: intNumberValues[488]},
	{Value: intNumberValues[489]},
	{Value: intNumberValues[490]},
	{Value: intNumberValues[491]},
	{Value: intNumberValues[492]},
	{Value: intNumberValues[493]},
	{Value: intNumberValues[494]},
	{Value: intNumberValues[495]},
	{Value: intNumberValues[496]},
	{Value: intNumberValues[497]},
	{Value: intNumberValues[498]},
	{Value: intNumberValues[499]},
	{Value: intNumberValues[500]},
	{Value: intNumberValues[501]},
	{Value: intNumberValues[502]},
	{Value: intNumberValues[503]},
	{Value: intNumberValues[504]},
	{Value: intNumberValues[505]},
	{Value: intNumberValues[506]},
	{Value: intNumberValues[507]},
	{Value: intNumberValues[508]},
	{Value: intNumberValues[509]},
	{Value: intNumberValues[510]},
	{Value: intNumberValues[511]},
	{Value: intNumberValues[512]},
}
