9:20: cannot use type *tensor.Number[float64] as type tree.Node
1:47: cannot use type *tensor.Number[float64] as type tree.Node
1:47: cannot use type *tensor.Number[float64] as type tree.Node
1:47: cannot use type *tensor.Number[float64] as type tree.Node
21:20: cannot use type *tensor.Number[float64] as type tree.Node
[{"Name":"Browser","URL":"browser","Title":"Browser","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Lab"],"Specials":{},"Description":"See \u003ccode\u003eexamples/planets\u003c/code\u003e and \u003ccode\u003eexamples/simstats\u003c/code\u003e for example uses of the \u003cstrong\u003eBrowser\u003c/strong\u003e graphical interface. Go API docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/lab#Browser\" target=\"_blank\"\u003elab.Browser\u003c/a\u003e","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eBrowser\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-1\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee \u003ccode\u003eexamples/planets\u003c/code\u003e and \u003ccode\u003eexamples/simstats\u003c/code\u003e for example uses of the \u003cstrong\u003eBrowser\u003c/strong\u003e graphical interface. Go API docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/lab#Browser\" target=\"_blank\"\u003elab.Browser\u003c/a\u003e\u003c/p\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cstretch id=\"content-buttons-go-131\" style=\"display:flex;flex-direction:row;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;font-weight:thin;text-align:start\"\u003e\u003c/stretch\u003e\u003ca id=\"content-buttons-go-132\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"datatree\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"M686-450H160v-60h526L438-758l42-42 320 320-320 320-42-42 248-248Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003eNext\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Cluster","URL":"cluster","Title":"Cluster","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Stats"],"Specials":{},"Description":"\u003cstrong\u003eCluster\u003c/strong\u003e computes agglomerative clustering. Go docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/stats/cluster\" target=\"_blank\"\u003estats/cluster\u003c/a\u003e","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eCluster\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-2\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eCluster\u003c/strong\u003e computes agglomerative clustering. Go docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/stats/cluster\" target=\"_blank\"\u003estats/cluster\u003c/a\u003e\u003c/p\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cstretch id=\"content-buttons-go-131\" style=\"display:flex;flex-direction:row;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;font-weight:thin;text-align:start\"\u003e\u003c/stretch\u003e\u003ca id=\"content-buttons-go-132\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"glm\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"M686-450H160v-60h526L438-758l42-42 320 320-320 320-42-42 248-248Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003eNext\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Compression tutorial","URL":"compression-tutorial","Title":"Compression tutorial","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Tutorials"],"Specials":{},"Description":"This tutorial provides a simple example of \u003cstrong\u003ecompressing\u003c/strong\u003e a small vector using a precomputed orthogonal \u003ca href=\"matrix\" target=\"_blank\"\u003ematrix\u003c/a\u003e as a new basis. Through that simple example, this tutorial demonstrates the capacities of Cogent Lab.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eCompression tutorial\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-3\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThis tutorial provides a simple example of \u003cstrong\u003ecompressing\u003c/strong\u003e a small vector using a precomputed orthogonal \u003ca href=\"matrix\" target=\"_blank\"\u003ematrix\u003c/a\u003e as a new basis. Through that simple example, this tutorial demonstrates the capacities of Cogent Lab.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe start with a data vector, \u003cstrong\u003ex\u003c/strong\u003e:\u003c/p\u003e\u003ctextarea id=\"editor-2\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e# x := [0.53766714, 1.83388501, -2.25884686, 0.86217332, 0.31876524, -1.3076883, -0.43359202, 0.34262447]\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-3\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe can \u003ca href=\"plot\" target=\"_blank\"\u003eplot\u003c/a\u003e \u003cstrong\u003ex\u003c/strong\u003e:\u003c/p\u003e\u003ctextarea id=\"editor-5\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003efig1 := lab.NewPlot(b)\nplots.NewPointLine(fig1, x)\nplots.NewLine(fig1, #zeros(8)#)\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-6\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cplot id=\"plot-0\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:384px;width:512px;height:384px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003c/div\u003e\u003cp id=\"text-7\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe can add in our precomputed orthogonal matrix, \u003cstrong\u003eU\u003c/strong\u003e, which will serve as our new basis for \u003cstrong\u003ex\u003c/strong\u003e.\u003c/p\u003e\u003ctextarea id=\"editor-8\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e# U := [[0.35355339, 0.49039264, 0.46193977, 0.41573481, 0.35355339, 0.27778512, 0.19134172, 0.09754516], [0.35355339, 0.41573481, 0.19134172, -0.09754516, -0.35355339, -0.49039264, -0.46193977, -0.27778512], [0.35355339, 0.27778512, -0.19134172, -0.49039264, -0.35355339, 0.09754516, 0.46193977, 0.41573481], [0.35355339, 0.09754516, -0.46193977, -0.27778512, 0.35355339, 0.41573481, -0.19134172, -0.49039264], [0.35355339, -0.09754516, -0.46193977, 0.27778512, 0.35355339, -0.41573481, -0.19134172, 0.49039264], [0.35355339, -0.27778512, -0.19134172, 0.49039264, -0.35355339, -0.09754516, 0.46193977, -0.41573481], [0.35355339, -0.41573481, 0.19134172, 0.09754516, -0.35355339, 0.49039264, -0.46193977, 0.27778512], [0.35355339, -0.49039264, 0.46193977, -0.41573481, 0.35355339, -0.27778512, 0.19134172, -0.09754516]]\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-9\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cp id=\"text-10\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe can plot each column vector of \u003cstrong\u003eU\u003c/strong\u003e:\u003c/p\u003e\u003ctextarea id=\"editor-11\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003efr := core.NewFrame(b)\nfr.Styler(func(s *styles.Style) {\n\ts.Direction = styles.Column\n\ts.Gap.Y.Dp(2)\n})\nfor i := range 8 {\n\t# v := U[:, i]\n\tfig2 := plot.New()\n\tpw := plotcore.NewPlot(fr).SetPlot(fig2)\n\tpw.Styler(func(s *styles.Style) {\n\t\ts.Min.Y.Dp(80)\n\t})\n\tplot.Styler(v, func(s *plot.Style) {\n\t\ts.Plot.Axis.On = false\n\t\ts.Range.SetMin(-0.5).SetMax(0.5)\n\t})\n\tplots.NewPointLine(fig2, v)\n\tplots.NewLine(fig2, #zeros(8)#)\n}\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-12\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"frame-0\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cplot id=\"plot-0\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:80px;width:512px;height:80px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003cplot id=\"plot-1\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:80px;width:512px;height:80px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003cplot id=\"plot-2\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:80px;width:512px;height:80px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003cplot id=\"plot-3\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:80px;width:512px;height:80px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003cplot id=\"plot-4\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:80px;width:512px;height:80px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003cplot id=\"plot-5\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:80px;width:512px;height:80px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003cplot id=\"plot-6\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:80px;width:512px;height:80px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003cplot id=\"plot-7\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:80px;width:512px;height:80px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003c/div\u003e\u003c/div\u003e\u003cp id=\"text-13\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNext, we can compute the vector \u003cstrong\u003ea\u003c/strong\u003e, which represents \u003cstrong\u003ex\u003c/strong\u003e in terms of the \u003cstrong\u003eU\u003c/strong\u003e basis (such that \u003cspan class=\"math inline\"\u003e\\(x = Ua\\)\u003c/span\u003e). This is just \u003cspan class=\"math inline\"\u003e\\(a = U^{-1}x\\)\u003c/span\u003e, as computed below:\u003c/p\u003e\u003ctextarea id=\"editor-14\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e# a := matrix.Inverse(U) @ x\ncore.NewText(b).SetText(a.String())\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-15\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"font-weight:normal;line-height:1.5;text-align:start\"\u003e[8] -0.03712734872 0.8271057473 0.8114806423 0.175395094 1.494637182 \n -0.9246413458 -2.351901711 -1.272758945 \n\u003c/p\u003e\u003c/div\u003e\u003cp id=\"text-16\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo compress the data, we will define a function that zeroes all but the \u003cem\u003en\u003c/em\u003e elements of \u003cstrong\u003ea\u003c/strong\u003e with the highest absolute values:\u003c/p\u003e\u003ctextarea id=\"editor-17\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003efunc compress(n int) tensor.Tensor {\n\tsorted := tensor.NewSliced(a)\n\tsorted.SortFunc(0, func(tsr tensor.Tensor, i, j int) int {\n\t\treturn cmp.Compare(math.Abs(tsr.Float1D(j)), math.Abs(tsr.Float1D(i)))\n\t})\n\t# top := sorted[:n]\n\t# res := zeros(8)\n\tfor i := range 8 {\n\t\tif tensor.ContainsFloat(top, #a[i]#) {\n\t\t\t# res[i] = a[i]\n\t\t} else {\n\t\t\t# res[i] = 0\n\t\t}\n\t}\t\n\treturn res\n}\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-18\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cp id=\"text-19\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThen, we will make \u003cstrong\u003ea2\u003c/strong\u003e, the result of \u003ccode\u003ecompress(2)\u003c/code\u003e (so the two most important elements are included):\u003c/p\u003e\u003ctextarea id=\"editor-20\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ea2 := compress(2)\ncore.NewText(b).SetText(a2.String())\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-21\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"font-weight:normal;line-height:1.5;text-align:start\"\u003e[8] 0 0 0 0 1.494637182 \n 0 -2.351901711 0 \n\u003c/p\u003e\u003c/div\u003e\u003cp id=\"text-22\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFrom \u003cstrong\u003ea2\u003c/strong\u003e, we can compute and plot \u003cstrong\u003ex2\u003c/strong\u003e, the approximation of \u003cstrong\u003ex\u003c/strong\u003e based on the two most important elements of \u003cstrong\u003ea\u003c/strong\u003e:\u003c/p\u003e\u003ctextarea id=\"editor-23\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e# x2 := U @ a2\ncore.NewText(b).SetText(x2.String())\nfig1a := lab.NewPlotFrom(fig1, b)\nplot.Styler(x2, func(s *plot.Style) {\n\ts.Point.Shape = plot.Pyramid\n})\nplots.NewPointLine(fig1a, x2)\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-24\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"font-weight:normal;line-height:1.5;text-align:start\"\u003e[8] 0.07841712375 0.5580028932 -1.614870978 0.9784509612 0.9784509612 \n -1.614870978 0.5580028932 0.07841712375 \n\u003c/p\u003e\u003cplot id=\"plot-1\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:384px;width:512px;height:384px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003c/div\u003e\u003cp id=\"text-25\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe can do the same thing for \u003cstrong\u003ea4\u003c/strong\u003e and \u003cstrong\u003ex4\u003c/strong\u003e, with the four most important elements of \u003cstrong\u003ea\u003c/strong\u003e:\u003c/p\u003e\u003ctextarea id=\"editor-26\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ea4 := compress(4)\ncore.NewText(b).SetText(a4.String())\n# x4 := U @ a4\ncore.NewText(b).SetText(x4.String())\nfig1b := lab.NewPlotFrom(fig1a, b)\nplot.Styler(x4, func(s *plot.Style) {\n\ts.Point.Shape = plot.Cross\n})\nplots.NewPointLine(fig1b, x4)\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-27\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"font-weight:normal;line-height:1.5;text-align:start\"\u003e[8] 0 0 0 0 1.494637182 \n -0.9246413458 -2.351901711 -1.272758945 \n\u003c/p\u003e\u003cp id=\"text-1\" style=\"font-weight:normal;line-height:1.5;text-align:start\"\u003e[8] -0.3025859583 1.3649937 -2.234195464 1.218196986 0.7387049365 \n -0.9955464921 -0.2489879136 0.4594202058 \n\u003c/p\u003e\u003cplot id=\"plot-2\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:512px;min-height:384px;width:512px;height:384px;font-weight:thin;text-align:start\"\u003e\u003c/plot\u003e\u003c/div\u003e\u003cp id=\"text-28\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe can also compute \u003cstrong\u003ex8\u003c/strong\u003e, which just uses \u003cstrong\u003ea\u003c/strong\u003e without anything removed:\u003c/p\u003e\u003ctextarea id=\"editor-29\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e# x8 := U @ a\ncore.NewText(b).SetText(x8.String())\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-30\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"font-weight:normal;line-height:1.5;text-align:start\"\u003e[8] 0.53766714 1.83388501 -2.25884686 0.86217332 0.31876524 -1.3076883 \n -0.43359202 0.34262447 \n\u003c/p\u003e\u003c/div\u003e\u003cp id=\"text-31\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe can find the error of \u003cstrong\u003ex8\u003c/strong\u003e relative to \u003cstrong\u003ex\u003c/strong\u003e, which is very small since nothing is compressed:\u003c/p\u003e\u003ctextarea id=\"editor-32\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003efunc relativeError(y tensor.Tensor) tensor.Tensor {\n\t# return sqrt(stats.Sum((x-y)**2)/stats.Sum(x**2))\n}\ncore.NewText(b).SetText(\"x8 error: \"+relativeError(x8).String())\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-33\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"font-weight:normal;line-height:1.5;text-align:start\"\u003ex8 error: 4.612726499e-16\u003c/p\u003e\u003c/div\u003e\u003cp id=\"text-34\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe can do the same for \u003cstrong\u003ex4\u003c/strong\u003e and \u003cstrong\u003ex2\u003c/strong\u003e:\u003c/p\u003e\u003ctextarea id=\"editor-35\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ecore.NewText(b).SetText(\"x4 error: \"+relativeError(x4).String())\ncore.NewText(b).SetText(\"x2 error: \"+relativeError(x2).String())\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-36\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"font-weight:normal;line-height:1.5;text-align:start\"\u003ex4 error: 0.3440342032\u003c/p\u003e\u003cp id=\"text-1\" style=\"font-weight:normal;line-height:1.5;text-align:start\"\u003ex2 error: 0.5757042318\u003c/p\u003e\u003c/div\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Datatree","URL":"datatree","Title":"Datatree","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Lab"],"Specials":{},"Description":"\u003cstrong\u003eDataTree\u003c/strong\u003e provides a \u003ca href=\"https://cogentcore.org/core/filetree\" target=\"_blank\"\u003ecore/filetree\u003c/a\u003e with support for standard data types, including viewing a \u003ca href=\"tensorfs\" target=\"_blank\"\u003etensorfs\u003c/a\u003e virtual filesystem, as part of a data \u003ca href=\"browser\" target=\"_blank\"\u003eBrowser\u003c/a\u003e.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eDatatree\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-4\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eDataTree\u003c/strong\u003e provides a \u003ca href=\"https://cogentcore.org/core/filetree\" target=\"_blank\"\u003ecore/filetree\u003c/a\u003e with support for standard data types, including viewing a \u003ca href=\"tensorfs\" target=\"_blank\"\u003etensorfs\u003c/a\u003e virtual filesystem, as part of a data \u003ca href=\"browser\" target=\"_blank\"\u003eBrowser\u003c/a\u003e.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eGo API docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/lab#DataTree\" target=\"_blank\"\u003elab.DataTree\u003c/a\u003e\u003c/p\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ca id=\"content-buttons-go-123\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"browser\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"m274-450 248 248-42 42-320-320 320-320 42 42-248 248h526v60H274Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003ePrevious\u003c/p\u003e\u003c/a\u003e\u003cstretch id=\"content-buttons-go-131\" style=\"display:flex;flex-direction:row;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;font-weight:thin;text-align:start\"\u003e\u003c/stretch\u003e\u003ca id=\"content-buttons-go-132\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"tabs\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"M686-450H160v-60h526L438-758l42-42 320 320-320 320-42-42 248-248Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003eNext\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Glm","URL":"glm","Title":"Glm","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Stats"],"Specials":{},"Description":"\u003cstrong\u003eglm\u003c/strong\u003e computes generalized linear models. Go docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/stats/glm\" target=\"_blank\"\u003estats/glm\u003c/a\u003e","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eGlm\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-5\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eglm\u003c/strong\u003e computes generalized linear models. Go docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/stats/glm\" target=\"_blank\"\u003estats/glm\u003c/a\u003e\u003c/p\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ca id=\"content-buttons-go-123\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"cluster\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"m274-450 248 248-42 42-320-320 320-320 42 42-248 248h526v60H274Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003ePrevious\u003c/p\u003e\u003c/a\u003e\u003cstretch id=\"content-buttons-go-131\" style=\"display:flex;flex-direction:row;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;font-weight:thin;text-align:start\"\u003e\u003c/stretch\u003e\u003ca id=\"content-buttons-go-132\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"histogram\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"M686-450H160v-60h526L438-758l42-42 320 320-320 320-42-42 248-248Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003eNext\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Goal","URL":"goal","Title":"Goal","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":null,"Specials":{},"Description":"\u003cstrong\u003eGoal\u003c/strong\u003e is the \u003cem\u003eGo augmented language\u003c/em\u003e with support for two additional modes, in addition to standard Go:","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eGoal\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-6\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eGoal\u003c/strong\u003e is the \u003cem\u003eGo augmented language\u003c/em\u003e with support for two additional modes, in addition to standard Go:\u003c/p\u003e\u003cul id=\"frame-1\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"shell\" target=\"_blank\"\u003e$ shell mode $\u003c/a\u003e that operates like a standard command-line shell (e.g., \u003ccode\u003ebash\u003c/code\u003e), with space-separated elements and standard shell functionality including input / output redirection. Goal automatically detects most instances of shell mode based on the syntax of the line, but it can always be explicitly indicated with surrounding \u003ccode\u003e$\u003c/code\u003es.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"math\" target=\"_blank\"\u003e# math mode #\u003c/a\u003e that supports Python-like concise mathematical expressions operating on \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e elements.\u003c/p\u003e\u003c/ul\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eHere is an example of shell-mode mixing Go and shell code:\u003c/p\u003e\u003ctextarea id=\"editor-3\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003efor i, f := range goalib.SplitLines($ls -la$) { // ls executes, returns string\n echo {i} {strings.ToLower(f)} // {} surrounds Go within shell\n}\n\n\u003c/textarea\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003ewhere Go-code is explicitly indicated by the \u003ccode\u003e{}\u003c/code\u003e braces.\u003c/p\u003e\u003cp id=\"text-5\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eHere is an example of math-mode:\u003c/p\u003e\u003ctextarea id=\"editor-6\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e# x := 1. / (1. + exp(-wts[:, :, :n] * acts[:]))\n\n\u003c/textarea\u003e\u003cp id=\"text-7\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can also intermix math within Go code:\u003c/p\u003e\u003ctextarea id=\"editor-8\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003efor _, x := range #[1,2,3]# {\n fmt.Println(#x**2#)\n}\n\n\u003c/textarea\u003e\u003cp id=\"text-9\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eGoal can be used in an interpreted mode by using the \u003ca href=\"https://github.com/traefik/yaegi\" target=\"_blank\"\u003eyaegi\u003c/a\u003e Go interpreter (and can be used as your shell executable in a terminal), and it can also replace the standard \u003ccode\u003ego\u003c/code\u003e compiler in command-line mode, to build compiled executables using the extended Goal syntax.\u003c/p\u003e\u003cp id=\"text-10\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eA key design feature of Goal is that it always \u003cem\u003etranspiles directly to Go\u003c/em\u003e in a purely syntactically driven way, so the output of Goal is pure Go code.\u003c/p\u003e\u003cp id=\"text-11\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eGoal can also be used in conjunction with \u003ca href=\"gosl\" target=\"_blank\"\u003egosl\u003c/a\u003e to build programs that transparently run on GPU hardware in addition to standard CPUs (as standard Go programs).\u003c/p\u003e\u003ch2 id=\"goal-pages\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eGoal pages\u003c/h2\u003e\u003cul id=\"frame-13\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"math\" target=\"_blank\"\u003eMath\u003c/a\u003e\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"shell\" target=\"_blank\"\u003eShell\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Gosl","URL":"gosl","Title":"Gosl","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":null,"Specials":{},"Description":"\u003cstrong\u003eGosl\u003c/strong\u003e allows you to write Go programs that run on \u003ca href=\"gpu\" target=\"_blank\"\u003eGPU\u003c/a\u003e hardware, by transpiling Go into the WGSL shader language used by \u003ca href=\"https://www.w3.org/TR/webgpu/\" target=\"_blank\"\u003eWebGPU\u003c/a\u003e, thereby establishing the \u003cem\u003eGo shader language\u003c/em\u003e.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eGosl\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-7\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eGosl\u003c/strong\u003e allows you to write Go programs that run on \u003ca href=\"gpu\" target=\"_blank\"\u003eGPU\u003c/a\u003e hardware, by transpiling Go into the WGSL shader language used by \u003ca href=\"https://www.w3.org/TR/webgpu/\" target=\"_blank\"\u003eWebGPU\u003c/a\u003e, thereby establishing the \u003cem\u003eGo shader language\u003c/em\u003e.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eGosl uses the \u003ca href=\"https://github.com/cogentcore/core/tree/main/gpu\" target=\"_blank\"\u003ecore gpu\u003c/a\u003e compute shader system, and operates within the overall \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e framework of an augmented version of the Go language.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe relevant regions of Go code to be run on the GPU are tagged using the \u003ccode\u003e//gosl:start\u003c/code\u003e and \u003ccode\u003e//gosl:end\u003c/code\u003e comment directives, and this code must only use basic expressions and concrete types that will compile correctly in a GPU shader (see \u003ca href=\"gosl#Restrictions\" target=\"_blank\"\u003eRestrictions\u003c/a\u003e below). Method functions and pass-by-reference pointer arguments to \u003ccode\u003estruct\u003c/code\u003e types are supported and incur no additional compute cost due to inlining (see notes below for more detail).\u003c/p\u003e\u003cp id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/examples/basic\" target=\"_blank\"\u003eexamples/basic\u003c/a\u003e and \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/examples/rand\" target=\"_blank\"\u003eexamples/rand\u003c/a\u003e for complete working examples.\u003c/p\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTypically, \u003ccode\u003egosl\u003c/code\u003e is called from a \u003ccode\u003ego generate\u003c/code\u003e command, e.g., by including this comment directive:\u003c/p\u003e\u003ctextarea id=\"editor-5\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e//go:generate gosl \n\n\u003c/textarea\u003e\u003cp id=\"text-6\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo install the \u003ccode\u003egosl\u003c/code\u003e command:\u003c/p\u003e\u003ctextarea id=\"editor-7\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e$ go install cogentcore.org/lab/gosl/@latest\n\n\u003c/textarea\u003e\u003cp id=\"text-8\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIt is also strongly recommended to install the \u003ccode\u003enaga\u003c/code\u003e WGSL compiler from \u003ca href=\"https://github.com/gfx-rs/wgpu\" target=\"_blank\"\u003ewgpu\u003c/a\u003e and the \u003ccode\u003etint\u003c/code\u003e compiler from \u003ca href=\"https://dawn.googlesource.com/dawn/\" target=\"_blank\"\u003edawn\u003c/a\u003e Both of these are used if available to validate the generated GPU shader code. It is much faster to fix the issues at generation time rather than when trying to run the app later. Once code passes validation in both of these compilers, it should load fine in your app, and if the Go version runs correctly, there is a good chance of at least some reasonable behavior on the GPU.\u003c/p\u003e\u003ch2 id=\"usage\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eUsage\u003c/h2\u003e\u003cp id=\"text-10\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThere are two key elements for GPU-enabled code:\u003c/p\u003e\u003col id=\"frame-11\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e1. One or more \u003ca href=\"gosl#Kernels\" target=\"_blank\"\u003eKernels\u003c/a\u003e compute functions that take an \u003cem\u003eindex\u003c/em\u003e argument and perform computations for that specific index of data, \u003cem\u003ein parallel\u003c/em\u003e. \u003cstrong\u003eGPU computation is effectively just a parallel \u003ccode\u003efor\u003c/code\u003e loop\u003c/strong\u003e. On the GPU, each such kernel is implemented by its own separate compute shader code, and one of the main functions of \u003ccode\u003egosl\u003c/code\u003e is to generate this code from the Go sources, in the automatically created \u003ccode\u003eshaders/\u003c/code\u003e directory.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e2. \u003ca href=\"gosl#Global variables\" target=\"_blank\"\u003eGlobal variables\u003c/a\u003e on which the kernel functions \u003cem\u003eexclusively\u003c/em\u003e operate: all relevant data must be specifically copied from the CPU to the GPU and back. As explained in the \u003ca href=\"gpu\" target=\"_blank\"\u003eGPU\u003c/a\u003e docs, each GPU compute shader is effectively a \u003cem\u003estandalone\u003c/em\u003e program operating on these global variables. To replicate this environment on the CPU, so the code works in both contexts, we need to make these variables global in the CPU (Go) environment as well.\u003c/p\u003e\u003c/ol\u003e\u003cp id=\"text-12\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003egosl\u003c/code\u003e generates a file named \u003ccode\u003egosl.go\u003c/code\u003e in your package directory that initializes the GPU with all of the global variables, and functions for running the kernels and syncing the gobal variable data back and forth between the CPu and GPU.\u003c/p\u003e\u003ch2 id=\"kernels\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eKernels\u003c/h2\u003e\u003cp id=\"text-14\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eEach distinct compute kernel must be tagged with a \u003ccode\u003e//gosl:kernel\u003c/code\u003e comment directive, as in this example (from \u003ccode\u003eexamples/basic\u003c/code\u003e):\u003c/p\u003e\u003ctextarea id=\"editor-15\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e// Compute does the main computation.\nfunc Compute(i uint32) { //gosl:kernel\n\tParams[0].IntegFromRaw(int(i))\n}\n\n\u003c/textarea\u003e\u003cp id=\"text-16\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe kernel functions receive a \u003ccode\u003euint32\u003c/code\u003e index argument, and use this to index into the global variables containing the relevant data. Typically the kernel code itself just calls other relevant function(s) using the index, as in the above example. Critically, \u003cem\u003eall\u003c/em\u003e of the data that a kernel function ultimately depends on must be contained with the global variables, and these variables must have been sync’d up to the GPU from the CPU prior to running the kernel (more on this below).\u003c/p\u003e\u003cp id=\"text-17\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn the CPU mode, the kernel is effectively run in a \u003ccode\u003efor\u003c/code\u003e loop like this:\u003c/p\u003e\u003ctextarea id=\"editor-18\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e\tfor i := range n {\n\t\tCompute(uint32(i))\n\t}\n\n\u003c/textarea\u003e\u003cp id=\"text-19\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eA parallel goroutine-based mechanism is actually used, but conceptually this is what it does, on both the CPU and the GPU. To reiterate: \u003cstrong\u003eGPU computation is effectively just a parallel for loop\u003c/strong\u003e.\u003c/p\u003e\u003ch2 id=\"global-variables\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eGlobal variables\u003c/h2\u003e\u003cp id=\"text-21\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe global variables on which the kernels operate are declared in the usual Go manner, as a single \u003ccode\u003evar\u003c/code\u003e block, which is marked at the top using the \u003ccode\u003e//gosl:vars\u003c/code\u003e comment directive:\u003c/p\u003e\u003ctextarea id=\"editor-22\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e//gosl:vars\nvar (\n\t// Params are the parameters for the computation.\n\t//gosl:read-only\n\tParams []ParamStruct\n\n\t// Data is the data on which the computation operates.\n\t// 2D: outer index is data, inner index is: Raw, Integ, Exp vars.\n\t//gosl:dims 2\n\tData *tensor.Float32\n)\n\u003c/textarea\u003e\u003cp id=\"text-23\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAll such variables must be either:\u003c/p\u003e\u003col id=\"frame-24\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e1. A \u003ccode\u003eslice\u003c/code\u003e of GPU-alignment compatible \u003ccode\u003estruct\u003c/code\u003e types, such as \u003ccode\u003eParamStruct\u003c/code\u003e in the above example. In general such structs should be marked as \u003ccode\u003e//gosl:read-only\u003c/code\u003e due to various challenges associated with writing to structs, detailed below.\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e2. A \u003ccode\u003etensor\u003c/code\u003e of a GPU-compatible elemental data type (\u003ccode\u003efloat32\u003c/code\u003e, \u003ccode\u003euint32\u003c/code\u003e, or \u003ccode\u003eint32\u003c/code\u003e), with the number of dimensions indicated by the \u003ccode\u003e//gosl:dims \u003cn\u003e\u003c/code\u003e tag as shown above. This is the preferred type for writable data.\u003c/li\u003e\u003c/ol\u003e\u003cp id=\"text-25\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can also just declare a slice of elemental GPU-compatible data values such as \u003ccode\u003efloat32\u003c/code\u003e, but it is generally preferable to use the tensor instead, because it has built-in support for higher-dimensional indexing in a way that is transparent between CPU and GPU.\u003c/p\u003e\u003ch3 id=\"tensor-data\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eTensor data\u003c/h3\u003e\u003cp id=\"text-27\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eOn the GPU, the tensor data is represented using a simple flat array of the basic data type. To index into this array, the \u003cem\u003estrides\u003c/em\u003e for each dimension are encoded in a special \u003ccode\u003eTensorStrides\u003c/code\u003e tensor that is managed by \u003ccode\u003egosl\u003c/code\u003e, in the generated \u003ccode\u003egosl.go\u003c/code\u003e file. \u003ccode\u003egosl\u003c/code\u003e automatically generates the appropriate indexing code using these strides (which is why the number of dimensions is needed).\u003c/p\u003e\u003cp id=\"text-28\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWhenever the strides of any tensor variable change, and at least once at initialization, your code must call the function that copies the current strides up to the GPU:\u003c/p\u003e\u003ctextarea id=\"editor-29\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e\tToGPUTensorStrides()\n\n\u003c/textarea\u003e\u003ch3 id=\"multiple-tensor-variables-for-large-data\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eMultiple tensor variables for large data\u003c/h3\u003e\u003cp id=\"text-31\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe size of each memory buffer is limited by the GPU, to a maximum of at most 4GB on modern GPU hardware. Therefore, if you need to have any single tensor that holds more than this amount of data, then a bank of multiple vars are required. \u003ccode\u003egosl\u003c/code\u003e provides helper functions to make this relatively straightforward.\u003c/p\u003e\u003cp id=\"text-32\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO: this could be encoded in the TensorStrides. It will always be the outer-most index that determines when it gets over threshold, which all can be pre-computed.\u003c/p\u003e\u003ch3 id=\"systems-and-groups\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eSystems and Groups\u003c/h3\u003e\u003cp id=\"text-34\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eEach kernel belongs to a \u003ccode\u003egpu.ComputeSystem\u003c/code\u003e, and each such system has one specific configuration of memory variables. In general, it is best to use a single set of global variables, and perform as much of the computation as possible on this set of variables, to minimize the number of memory transfers. However, if necessary, multiple systems can be defined, using an optional additional system name argument for the \u003ccode\u003eargs\u003c/code\u003e and \u003ccode\u003ekernel\u003c/code\u003e tags.\u003c/p\u003e\u003cp id=\"text-35\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn addition, the vars can be organized into \u003cem\u003egroups\u003c/em\u003e, which generally should have similar memory syncing behavior, as documented in the \u003ca href=\"https://github.com/cogentcore/core/tree/main/gpu\" target=\"_blank\"\u003ecore gpu\u003c/a\u003e system.\u003c/p\u003e\u003cp id=\"text-36\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eHere’s an example with multiple groups:\u003c/p\u003e\u003ctextarea id=\"editor-37\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e//gosl:vars [system name]\nvar (\n // Layer-level parameters\n //gosl:group -uniform Params\n Layers []LayerParam // note: struct with appropriate memory alignment\n\n // Path-level parameters\n Paths []PathParam \n\n // Unit state values\n //gosl:group Units\n Units tensor.Float32\n \n // Synapse weight state values\n Weights tensor.Float32\n)\n\u003c/textarea\u003e\u003ch2 id=\"memory-syncing\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eMemory syncing\u003c/h2\u003e\u003cp id=\"text-39\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eEach global variable gets an automatically-generated \u003ccode\u003e*Var\u003c/code\u003e enum (e.g., \u003ccode\u003eDataVar\u003c/code\u003e for global variable named \u003ccode\u003eData\u003c/code\u003e), that used for the memory syncing functions, to make it easy to specify any number of such variables to sync, which is by far the most efficient. All of this is in the generated \u003ccode\u003egosl.go\u003c/code\u003e file. For example:\u003c/p\u003e\u003ctextarea id=\"editor-40\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e\tToGPU(ParamsVar, DataVar)\n\n\u003c/textarea\u003e\u003cp id=\"text-41\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSpecifies that the current contents of \u003ccode\u003eParams\u003c/code\u003e and \u003ccode\u003eData\u003c/code\u003e are to be copied up to the GPU, which is guaranteed to complete by the time the next kernel run starts, within a given system.\u003c/p\u003e\u003ch2 id=\"kernel-running\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eKernel running\u003c/h2\u003e\u003cp id=\"text-43\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAs with memory transfers, it is much more efficient to run multiple kernels in sequence, all operating on the current data variables, followed by a single sync of the updated global variable data that has been computed. Thus, there are separate functions for specifying the kernels to run, followed by a single “Done” function that actually submits the entire batch of kernels, along with memory sync commands to get the data back from the GPU. For example:\u003c/p\u003e\u003ctextarea id=\"editor-44\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e RunCompute1(n)\n RunCompute2(n)\n ...\n RunDone(Data1Var, Data2Var) // launch all kernels and get data back to given vars\n\n\u003c/textarea\u003e\u003cp id=\"text-45\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFor CPU mode, \u003ccode\u003eRunDone\u003c/code\u003e is a no-op, and it just runs each kernel during each \u003ccode\u003eRun\u003c/code\u003e command.\u003c/p\u003e\u003cp id=\"text-46\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIt is absolutely essential to understand that \u003cem\u003eall data must already be on the GPU\u003c/em\u003e at the start of the first Run command, and that any CPU-based computation between these calls is completely irrelevant for the GPU. Thus, it typically makes sense to just have a sequence of Run commands grouped together into a logical unit, with the relevant \u003ccode\u003eToGPU\u003c/code\u003e calls at the start and the final \u003ccode\u003eRunDone\u003c/code\u003e grabs everything of relevance back from the GPU.\u003c/p\u003e\u003ch2 id=\"gpu-relevant-code-taggng\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eGPU relevant code taggng\u003c/h2\u003e\u003cp id=\"text-48\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn a large GPU-based application, you should organize your code as you normally would in any standard Go application, distributing it across different files and packages. The GPU-relevant parts of each of those files can be tagged with the gosl tags:\u003c/p\u003e\u003ctextarea id=\"editor-49\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e//gosl:start\n\n\u003c Go code to be translated \u003e\n\n//gosl:end\n\u003c/textarea\u003e\u003cp id=\"text-50\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eto make this code available to all of the shaders that are generated.\u003c/p\u003e\u003cp id=\"text-51\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eUse the \u003ccode\u003e//gosl:import \"package/path\"\u003c/code\u003e directive to import GPU-relevant code from other packages, similar to the standard Go import directive. It is assumed that many other Go imports are not GPU relevant, so this separate directive is required.\u003c/p\u003e\u003cp id=\"text-52\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIf any \u003ccode\u003eenums\u003c/code\u003e variables are defined, pass the \u003ccode\u003e-gosl\u003c/code\u003e flag to the \u003ccode\u003ecore generate\u003c/code\u003e command to ensure that the \u003ccode\u003eN\u003c/code\u003e value is tagged with \u003ccode\u003e//gosl:start\u003c/code\u003e and \u003ccode\u003e//gosl:end\u003c/code\u003e tags.\u003c/p\u003e\u003cp id=\"text-53\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eIMPORTANT:\u003c/strong\u003e all \u003ccode\u003e.go\u003c/code\u003e and \u003ccode\u003e.wgsl\u003c/code\u003e files are removed from the \u003ccode\u003eshaders\u003c/code\u003e directory prior to processing to ensure everything there is current – always specify a different source location for any custom \u003ccode\u003e.wgsl\u003c/code\u003e files that are included.\u003c/p\u003e\u003ch1 id=\"command-line-usage\" style=\"margin:0.25em;font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eCommand line usage\u003c/h1\u003e\u003ctextarea id=\"editor-55\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003egosl [flags] \n\n\u003c/textarea\u003e\u003cp id=\"text-56\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe flags are:\u003c/p\u003e\u003ctextarea id=\"editor-57\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e -debug\n \tenable debugging messages while running\n -exclude string\n \tcomma-separated list of names of functions to exclude from exporting to WGSL (default \"Update,Defaults\")\n -keep\n \tkeep temporary converted versions of the source files, for debugging\n -out string\n \toutput directory for shader code, relative to where gosl is invoked -- must not be an empty string (default \"shaders\")\n\n\u003c/textarea\u003e\u003cp id=\"text-58\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003egosl\u003c/code\u003e always operates on the current directory, looking for all files with \u003ccode\u003e//gosl:\u003c/code\u003e tags, and accumulating all the \u003ccode\u003eimport\u003c/code\u003e files that they include, etc.\u003c/p\u003e\u003cp id=\"text-59\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAny \u003ccode\u003estruct\u003c/code\u003e types encountered will be checked for 16-byte alignment of sub-types and overall sizes as an even multiple of 16 bytes (4 \u003ccode\u003efloat32\u003c/code\u003e or \u003ccode\u003eint32\u003c/code\u003e values), which is the alignment used in WGSL and glsl shader languages, and the underlying GPU hardware presumably. Look for error messages on the output from the gosl run. This ensures that direct byte-wise copies of data between CPU and GPU will be successful. The fact that \u003ccode\u003egosl\u003c/code\u003e operates directly on the original CPU-side Go code uniquely enables it to perform these alignment checks, which are otherwise a major source of difficult-to-diagnose bugs.\u003c/p\u003e\u003ch1 id=\"restrictions\" style=\"margin:0.25em;font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eRestrictions\u003c/h1\u003e\u003cp id=\"text-61\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn general shader code should be simple mathematical expressions and data types, with minimal control logic via \u003ccode\u003eif\u003c/code\u003e, \u003ccode\u003efor\u003c/code\u003e statements, and only using the subset of Go that is consistent with C. Here are specific restrictions:\u003c/p\u003e\u003cul id=\"frame-62\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Can only use \u003ccode\u003efloat32\u003c/code\u003e, \u003ccode\u003e[u]int32\u003c/code\u003e for basic types (\u003ccode\u003eint\u003c/code\u003e is converted to \u003ccode\u003eint32\u003c/code\u003e automatically), and \u003ccode\u003estruct\u003c/code\u003e types composed of these same types – no other Go types (i.e., \u003ccode\u003emap\u003c/code\u003e, slices, \u003ccode\u003estring\u003c/code\u003e, etc) are compatible. There are strict alignment restrictions on 16 byte (e.g., 4 \u003ccode\u003efloat32\u003c/code\u003e’s) intervals that are enforced via the \u003ccode\u003ealignsl\u003c/code\u003e sub-package.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• WGSL does \u003cem\u003enot\u003c/em\u003e support 64 bit float or int.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Use \u003ccode\u003eslbool.Bool\u003c/code\u003e instead of \u003ccode\u003ebool\u003c/code\u003e – it defines a Go-friendly interface based on a \u003ccode\u003eint32\u003c/code\u003e basic type.\u003c/p\u003e\u003cp id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Alignment and padding of \u003ccode\u003estruct\u003c/code\u003e fields is key – this is automatically checked by \u003ccode\u003egosl\u003c/code\u003e.\u003c/p\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• WGSL does not support enum types, but standard go \u003ccode\u003econst\u003c/code\u003e declarations will be converted. Use an \u003ccode\u003eint32\u003c/code\u003e or \u003ccode\u003euint32\u003c/code\u003e data type. It will automatically deal with the simple incrementing \u003ccode\u003eiota\u003c/code\u003e values, but not more complex cases. Also, for bitflags, define explicitly, not using \u003ccode\u003ebitflags\u003c/code\u003e package, and use \u003ccode\u003e0x01\u003c/code\u003e, \u003ccode\u003e0x02\u003c/code\u003e, \u003ccode\u003e0x04\u003c/code\u003e etc instead of \u003ccode\u003e1\u003c\u003c2\u003c/code\u003e – in theory the latter should be ok but in practice it complains.\u003c/p\u003e\u003cp id=\"text-5\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Cannot use multiple return values, or multiple assignment of variables in a single \u003ccode\u003e=\u003c/code\u003e expression.\u003c/p\u003e\u003cp id=\"text-6\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003cem\u003eCan\u003c/em\u003e use multiple variable names with the same type (e.g., \u003ccode\u003emin, max float32\u003c/code\u003e) – this will be properly converted to the more redundant form with the type repeated, for WGSL.\u003c/p\u003e\u003cp id=\"text-7\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eswitch\u003c/code\u003e \u003ccode\u003ecase\u003c/code\u003e statements are \u003cem\u003epurely\u003c/em\u003e self-contained – no \u003ccode\u003efallthrough\u003c/code\u003e allowed! does support multiple items per \u003ccode\u003ecase\u003c/code\u003e however. Every \u003ccode\u003eswitch\u003c/code\u003e \u003cem\u003emust\u003c/em\u003e have a \u003ccode\u003edefault\u003c/code\u003e case.\u003c/p\u003e\u003cp id=\"text-8\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• WGSL does specify that new variables are initialized to 0, like Go, but also somehow discourages that use-case. It is safer to initialize directly:\u003c/p\u003e\u003c/ul\u003e\u003ctextarea id=\"editor-63\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e val := float32(0) // guaranteed 0 value\n var val float32 // ok but generally avoid\n\n\u003c/textarea\u003e\u003cul id=\"frame-64\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Use the automatically-generated \u003ccode\u003eGetX\u003c/code\u003e methods to get a local variable to a slice of structs:\u003c/li\u003e\u003c/ul\u003e\u003ctextarea id=\"editor-65\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e ctx := GetCtx(0)\n\n\u003c/textarea\u003e\u003cp id=\"text-66\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThis automatically does the right thing on GPU while returning a pointer to the indexed struct on CPU.\u003c/p\u003e\u003cul id=\"frame-67\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• tensor variables can only be used in \u003ccode\u003estorage\u003c/code\u003e (not \u003ccode\u003euniform\u003c/code\u003e) memory, due to restrictions on dynamic sizing and alignment. Aside from this constraint, it is possible to designate a group of variables to use uniform memory, with the \u003ccode\u003e-uniform\u003c/code\u003e argument as the first item in the \u003ccode\u003e//gosl:group\u003c/code\u003e comment directive.\u003c/li\u003e\u003c/ul\u003e\u003ch2 id=\"other-language-features\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eOther language features\u003c/h2\u003e\u003cul id=\"frame-69\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"https://google.github.io/tour-of-wgsl/types/pointers/passing_pointers/\" target=\"_blank\"\u003etour-of-wgsl\u003c/a\u003e is a good reference to explain things more directly than the spec.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eptr\u003cfunction,MyStruct\u003e\u003c/code\u003e provides a pointer arg\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eprivate\u003c/code\u003e scope = within the shader code “module”, i.e., one thread.\u003c/p\u003e\u003cp id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003efunction\u003c/code\u003e = within the function, not outside it.\u003c/p\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eworkgroup\u003c/code\u003e = shared across workgroup – coudl be powerful (but slow!) – need to learn more.\u003c/p\u003e\u003c/ul\u003e\u003ch2 id=\"atomic-access\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eAtomic access\u003c/h2\u003e\u003cp id=\"text-71\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWGSL adopts the Metal (lowest common denominator) strong constraint of imposing a \u003cem\u003etype\u003c/em\u003e level restriction on atomic operations: you can only do atomic operations on variables that have been declared atomic, as in:\u003c/p\u003e\u003ctextarea id=\"editor-72\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003evar\u003cstorage, read_write\u003e PathGBuf: array\u003catomic\u003ci32\u003e\u003e;\n...\natomicAdd(\u0026PathGBuf[idx], val);\n\n\u003c/textarea\u003e\u003cp id=\"text-73\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThis also unfortunately has the side-effect that you cannot do \u003cem\u003enon-atomic\u003c/em\u003e operations on atomic variables, as discussed extensively here: \u003ca href=\"https://github.com/gpuweb/gpuweb/issues/2377\" target=\"_blank\"\u003ehttps://github.com/gpuweb/gpuweb/issues/2377\u003c/a\u003e Gosl automatically detects the use of atomic functions on GPU variables, and tags them as atomic.\u003c/p\u003e\u003ch2 id=\"random-numbers-slrand\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eRandom numbers: slrand\u003c/h2\u003e\u003cp id=\"text-75\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/gosl/slrand\" target=\"_blank\"\u003egosl/slrand\u003c/a\u003e for a shader-optimized random number generation package, which is supported by \u003ccode\u003egosl\u003c/code\u003e – it will convert \u003ccode\u003eslrand\u003c/code\u003e calls into appropriate WGSL named function calls. \u003ccode\u003egosl\u003c/code\u003e will also copy the \u003ccode\u003eslrand.wgsl\u003c/code\u003e file, which contains the full source code for the RNG, into the destination \u003ccode\u003eshaders\u003c/code\u003e directory, so it can be included with a simple local path:\u003c/p\u003e\u003ctextarea id=\"editor-76\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e//gosl:wgsl mycode\n// #include \"slrand.wgsl\"\n//gosl:end mycode\n\n\u003c/textarea\u003e\u003ch2 id=\"performance\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003ePerformance\u003c/h2\u003e\u003cp id=\"text-78\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWith sufficiently large N, and ignoring the data copying setup time, around ~80x speedup is typical on a Macbook Pro with M1 processor. The \u003ccode\u003erand\u003c/code\u003e example produces a 175x speedup!\u003c/p\u003e\u003ch2 id=\"gosl-pages\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eGosl pages\u003c/h2\u003e\u003cul id=\"frame-80\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"gpu\" target=\"_blank\"\u003eGPU\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"GPU","URL":"gpu","Title":"GPU","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Gosl"],"Specials":{},"Description":"The use of massively parallel \u003cem\u003eGraphical Processsing Unit\u003c/em\u003e (\u003cstrong\u003eGPU\u003c/strong\u003e) hardware has revolutionized machine learning and other fields, producing many factors of speedup relative to traditional \u003cem\u003eCPU\u003c/em\u003e (\u003cem\u003eCentral Processing Unit\u003c/em\u003e) computation. However, there are numerous challenges for supporting GPU-based computation, relative to the more flexible CPU coding.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eGPU\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-8\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe use of massively parallel \u003cem\u003eGraphical Processsing Unit\u003c/em\u003e (\u003cstrong\u003eGPU\u003c/strong\u003e) hardware has revolutionized machine learning and other fields, producing many factors of speedup relative to traditional \u003cem\u003eCPU\u003c/em\u003e (\u003cem\u003eCentral Processing Unit\u003c/em\u003e) computation. However, there are numerous challenges for supporting GPU-based computation, relative to the more flexible CPU coding.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ca href=\"gosl\" target=\"_blank\"\u003eGosl\u003c/a\u003e Go shader language operating within the broader \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e augmented version of the Go lanuage provides a solution to these challenges that enables the same Go-based code to work efficiently and reasonably naturally on both the GPU and CPU (i.e., standard Go execution).\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eDebugging code on the GPU is notoriously difficult because the usual tools are not directly available (not even print statements), so the ability to run exactly the same code on the CPU and GPU is invaluable, in addition to the benefits in portability across platforms without GPU hardware.\u003c/p\u003e\u003cp id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee the \u003ca href=\"gosl\" target=\"_blank\"\u003egosl\u003c/a\u003e documentation for the details on how to write code that works on the GPU. The remainder of this document provides an overview of the overall approach in relation to other related tools.\u003c/p\u003e\u003ch2 id=\"challenges-for-gpu-computation\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eChallenges for GPU computation\u003c/h2\u003e\u003cp id=\"text-5\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe two most important challenges for GPU-based programs are:\u003c/p\u003e\u003cul id=\"frame-6\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• The GPU \u003cem\u003ehas its own separate memory space\u003c/em\u003e that needs to be synchronized explicitly and bidirectionally with the standard CPU memory (this is true programmatically even if at a hardware level there is shared memory).\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Computation must be organized into discrete chunks that can be computed efficiently in parallel, and each such chunk of computation lives in its own separate \u003cem\u003ekernel\u003c/em\u003e (\u003cem\u003ecompute shader\u003c/em\u003e) in the GPU, as an entirely separate, self-contained program, operating on \u003cem\u003eglobal variables\u003c/em\u003e that define the entire memory space of the computation.\u003c/p\u003e\u003c/ul\u003e\u003cp id=\"text-7\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo be maximally efficient, both of these factors must be optimized, such that:\u003c/p\u003e\u003cul id=\"frame-8\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• The bidirectional syncing of memory between CPU and GPU should be minimized, because such transfers incur a significant overhead.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• The overall computation should be broken down into the \u003cem\u003elargest possible chunks\u003c/em\u003e to minimize the number of discrete kernel runs, each of which incurs significant overhead.\u003c/p\u003e\u003c/ul\u003e\u003cp id=\"text-9\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThus, it is unfortunately \u003cem\u003ehighly inefficient\u003c/em\u003e to implement GPU-based computation by running each elemental vectorizable tensor operation (add, multiply, etc) as a separate GPU kernel, with its own separate bidirectional memory sync, even though that is a conceptually attractive and simple way to organize GPU computation, with minimal disruption relative to the CPU model.\u003c/p\u003e\u003cp id=\"text-10\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ca href=\"https://github.com/jax-ml/jax\" target=\"_blank\"\u003eJAX\u003c/a\u003e framework in Python provides one solution to this situation, optimized for neural network machine learning uses, by imposing strict \u003cem\u003efunctional programming\u003c/em\u003e constraints on the code you write (i.e., all functions must be \u003cem\u003eread-only\u003c/em\u003e), and leveraging those to automatically combine elemental computations into larger parallelizable chunks, using a “just in time” (\u003cem\u003ejit\u003c/em\u003e) compiler.\u003c/p\u003e\u003cp id=\"text-11\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe take a different approach, which is much simpler implementationally but requires a bit more work from the developer, which is to provide tools that allow \u003cem\u003eyou\u003c/em\u003e to organize your computation into kernel-sized chunks according to your knowledge of the problem, and transparently turn that code into the final CPU and GPU programs.\u003c/p\u003e\u003cp id=\"text-12\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn many cases, a human programmer can most likely out-perform the automatic compilation process, by knowing the full scope of what needs to be computed, and figuring out how to package it most efficiently per the above constraints. In the end, you get maximum efficiency and complete transparency about exactly what is being computed, perhaps with fewer “gotcha” bugs arising from all the magic happening under the hood, but it may take a bit more work to get there.\u003c/p\u003e\u003cp id=\"text-13\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe role of \u003ca href=\"gosl\" target=\"_blank\"\u003eGosl\u003c/a\u003e and \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e is to allow you to express the full computation in the clear, simple, Go language, using intuitive data structures that minimize the need for additional boilerplate to run efficiently on CPU and GPU. This ability to write a single codebase that runs efficiently on CPU and GPU is similar to the \u003ca href=\"https://en.wikipedia.org/wiki/SYCL\" target=\"_blank\"\u003eSYCL\u003c/a\u003e framework (and several others discussed on that wikipedia page), which builds on \u003ca href=\"https://en.wikipedia.org/wiki/OpenCL\" target=\"_blank\"\u003eOpenCL\u003c/a\u003e, both of which are based on the C / C++ programming language.\u003c/p\u003e\u003cp id=\"text-14\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn addition to the critical differences between Go and C++ as languages, Gosl targets only one hardware platform: WebGPU (via the \u003ca href=\"https://github.com/cogentcore/core/tree/main/gpu\" target=\"_blank\"\u003ecore gpu\u003c/a\u003e package), so it is more specifically optimized for this use-case. Furthermore, SYCL and other approaches require you to write GPU-like code that can also run on the CPU (with lots of explicit fine-grained memory and compute management), whereas Goal provides a more natural CPU-like programming model, while imposing some stronger constraints that encourage more efficient implementations.\u003c/p\u003e\u003cp id=\"text-15\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe bottom line is that the fantasy of being able to write CPU-native code and have it magically “just work” on the GPU with high levels of efficiency is just that: a fantasy. The reality is that code must be specifically structured and organized to work efficiently on the GPU. Goal just makes this process relatively clean and efficient and easy to read, with a minimum of extra boilerplate. The resulting code should be easily understood by anyone familiar with the Go language, even if that isn’t the way you would have written it in the first place. The reward is that you can get highly efficient results with significant GPU-accelerated speedups that works on \u003cem\u003eany platform\u003c/em\u003e, including the web and mobile phones, all with a single easy-to-read codebase.\u003c/p\u003e\u003ch2 id=\"kernel-functions\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eKernel functions\u003c/h2\u003e\u003cp id=\"text-17\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFirst, we assume the scope is a single Go package that implements a set of computations on some number of associated data representations. The package will likely contain a lot of CPU-only Go code that manages all the surrounding infrastructure for the computations, in terms of creating and configuring the data in memory, visualization, i/o, etc.\u003c/p\u003e\u003cp id=\"text-18\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe GPU-specific computation is organized into some (hopefully small) number of \u003cstrong\u003ekernel\u003c/strong\u003e functions, that are conceptually called using a \u003cstrong\u003eparallel for loop\u003c/strong\u003e, e.g., something like this:\u003c/p\u003e\u003ctextarea id=\"editor-19\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003efor i := range parallel(data) {\n Compute(i)\n}\n\n\u003c/textarea\u003e\u003cp id=\"text-20\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ccode\u003ei\u003c/code\u003e index effectively iterates over the range of the values of the \u003ccode\u003edata\u003c/code\u003e variable, with the GPU version launching kernels on the GPU for each different index value. The CPU version actually runs in parallel as well, using goroutines.\u003c/p\u003e\u003cp id=\"text-21\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWe assume that multiple kernels will in general be required, and that there is likely to be a significant amount of shared code infrastructure across these kernels. Thus, the kernel functions are typically relatively short, and call into a large body of code that is likely shared among the different kernel functions.\u003c/p\u003e\u003cp id=\"text-22\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eEven though the GPU kernels must each be compiled separately into a single distinct WGSL \u003cem\u003eshader\u003c/em\u003e file that is run under WebGPU, they can \u003ccode\u003eimport\u003c/code\u003e a shared codebase of files, and thus replicate the same overall shared code structure as the CPU versions.\u003c/p\u003e\u003cp id=\"text-23\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe GPU code can only handle a highly restricted \u003cem\u003esubset\u003c/em\u003e of Go code, with data structures having strict alignment requirements, and no \u003ccode\u003estring\u003c/code\u003e or other composite variable-length data structures (maps, slices etc). Thus, \u003ca href=\"gosl\" target=\"_blank\"\u003eGosl\u003c/a\u003e recognizes \u003ccode\u003e//gosl:start\u003c/code\u003e and \u003ccode\u003e//gosl:end\u003c/code\u003e comment directives surrounding the GPU-safe (and relevant) portions of the overall code. Any \u003ccode\u003e.go\u003c/code\u003e or \u003ccode\u003e.goal\u003c/code\u003e file can contribute GPU relevant code, including in other packages, and the gosl system automatically builds a shadow package-based set of \u003ccode\u003e.wgsl\u003c/code\u003e files accordingly.\u003c/p\u003e\u003cblockquote id=\"frame-24\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;margin:1em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eEach kernel function is marked with a \u003ccode\u003e//gosl:kernel\u003c/code\u003e directive, and the name of the function is used to create the name of the GPU shader file.\u003c/p\u003e\u003c/blockquote\u003e\u003ctextarea id=\"editor-25\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e// Compute does the main computation.\nfunc Compute(i uint32) { //gosl:kernel\n\tParams[0].IntegFromRaw(\u0026Data[i])\n}\n\n\u003c/textarea\u003e\u003ch2 id=\"memory-organization\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eMemory Organization\u003c/h2\u003e\u003cp id=\"text-27\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003ePerhaps the strongest constraints for GPU programming stem from the need to organize and synchronize all the memory buffers holding the data that the GPU kernel operates on. Furthermore, within a GPU kernel, the variables representing this data are \u003cem\u003eglobal variables\u003c/em\u003e, which is sensible given the standalone nature of each kernel.\u003c/p\u003e\u003cblockquote id=\"frame-28\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;margin:1em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo provide a common programming environment, all GPU-relevant variables must be Go global variables.\u003c/p\u003e\u003c/blockquote\u003e\u003cp id=\"text-29\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThus, names must be chosen appropriately for these variables, given their global scope within the Go package. The specific \u003cem\u003evalues\u003c/em\u003e for these variables can be dynamically set in an easy way, but the variables themselves are global.\u003c/p\u003e\u003cp id=\"text-30\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWithin the \u003ca href=\"https://github.com/cogentcore/core/tree/main/gpu\" target=\"_blank\"\u003ecore gpu\u003c/a\u003e framework, each \u003ccode\u003eComputeSystem\u003c/code\u003e defines a specific organization of such GPU buffer variables, and maximum efficiency is achieved by minimizing the number of such compute systems, and associated memory buffers. Each system also encapsulates the associated kernel shaders that operate on the associated memory data, so\u003c/p\u003e\u003cblockquote id=\"frame-31\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;margin:1em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eKernels and variables both must be defined within a specific system context.\u003c/p\u003e\u003c/blockquote\u003e\u003ch3 id=\"tensorfs-mapping\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003etensorfs mapping\u003c/h3\u003e\u003cp id=\"text-33\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/p\u003e\u003cp id=\"text-34\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe grouped global variables can be mapped directly to a corresponding \u003ca href=\"../tensor/tensorfs\"\u003etensorfs\u003c/a\u003e directory, which provides direct accessibility to this data within interactive Goal usage. Further, different sets of variable values can be easily managed by saving and loading different such directories.\u003c/p\u003e\u003ctextarea id=\"editor-35\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e\tgosl.ToDataFS(\"path/to/dir\" [, system]) // set tensorfs items in given path to current global vars\n\t\n\tgosl.FromDataFS(\"path/to/dir\" [,system]) // set global vars from given tensorfs path\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-36\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cp id=\"text-37\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThese and all such \u003ccode\u003egosl\u003c/code\u003e functions use the current system if none is explicitly specified, which is settable using the \u003ccode\u003egosl.SetSystem\u003c/code\u003e call. Any given variable can use the \u003ccode\u003eget\u003c/code\u003e or \u003ccode\u003eset\u003c/code\u003e Goal math mode functions directly.\u003c/p\u003e\u003ch2 id=\"memory-access\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eMemory access\u003c/h2\u003e\u003cp id=\"text-39\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn general, all global GPU variables will be arrays (slices) or tensors, which are exposed to the GPU as an array of floats.\u003c/p\u003e\u003cp id=\"text-40\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe tensor-based indexing syntax in Goal math mode transparently works across CPU and GPU modes, and is thus the preferred way to access tensor data.\u003c/p\u003e\u003cp id=\"text-41\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIt is critical to appreciate that none of the other convenient math-mode operations will work as you expect on the GPU, because:\u003c/p\u003e\u003cblockquote id=\"frame-42\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;margin:1em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThere is only one outer-loop, kernel-level parallel looping operation allowed at a time.\u003c/p\u003e\u003c/blockquote\u003e\u003cp id=\"text-43\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou cannot nest multiple such loops within each other. A kernel cannot launch another kernel. Therefore, as noted above, you must directly organize your computation to maximize the amount of parallel computation happening wthin each such kernel call.\u003c/p\u003e\u003cblockquote id=\"frame-44\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;margin:1em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTherefore, tensor indexing on the GPU only supports direct index values, not ranges.\u003c/p\u003e\u003c/blockquote\u003e\u003cp id=\"text-45\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFurthermore:\u003c/p\u003e\u003cblockquote id=\"frame-46\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;margin:1em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003ePointer-based access of global variables is not supported in GPU mode.\u003c/p\u003e\u003c/blockquote\u003e\u003cp id=\"text-47\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou have to use \u003cem\u003eindexes\u003c/em\u003e into arrays exclusively. Thus, some of the data structures you may need to copy up to the GPU include index variables that determine how to access other variables.\u003c/p\u003e\u003ch2 id=\"examples\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eExamples\u003c/h2\u003e\u003cp id=\"text-49\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eA large and complex biologically-based neural network simulation framework called \u003ca href=\"https://github.com/emer/axon\" target=\"_blank\"\u003eaxon\u003c/a\u003e has been implemented using \u003ccode\u003egosl\u003c/code\u003e, allowing 1000’s of lines of equations and data structures to run through standard Go on the CPU, and accelerated significantly on the GPU. This allows efficient debugging and unit testing of the code in Go, whereas debugging on the GPU is notoriously difficult.\u003c/p\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Histogram","URL":"histogram","Title":"Histogram","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Stats"],"Specials":{},"Description":"\u003cstrong\u003eHistogram\u003c/strong\u003e computes histograms. Go docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/stats/histogram\" target=\"_blank\"\u003estats/histogram\u003c/a\u003e","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eHistogram\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-9\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eHistogram\u003c/strong\u003e computes histograms. Go docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/stats/histogram\" target=\"_blank\"\u003estats/histogram\u003c/a\u003e\u003c/p\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ca id=\"content-buttons-go-123\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"glm\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"m274-450 248 248-42 42-320-320 320-320 42 42-248 248h526v60H274Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003ePrevious\u003c/p\u003e\u003c/a\u003e\u003cstretch id=\"content-buttons-go-131\" style=\"display:flex;flex-direction:row;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;font-weight:thin;text-align:start\"\u003e\u003c/stretch\u003e\u003ca id=\"content-buttons-go-132\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"metric\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"M686-450H160v-60h526L438-758l42-42 320 320-320 320-42-42 248-248Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003eNext\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Home","URL":"","Title":"Cogent Lab","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":null,"Specials":{},"Description":"\u003cstrong\u003eCogent Lab\u003c/strong\u003e is a free and open source data science and visualization framework for the Go language, built on top of the \u003ca href=\"https://cogentcore.org/core\" target=\"_blank\"\u003eCogent Core\u003c/a\u003e GUI framework, so that the same code runs on macOS, Windows, Linux, iOS, Android, and web.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eCogent Lab\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-10\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eCogent Lab\u003c/strong\u003e is a free and open source data science and visualization framework for the Go language, built on top of the \u003ca href=\"https://cogentcore.org/core\" target=\"_blank\"\u003eCogent Core\u003c/a\u003e GUI framework, so that the same code runs on macOS, Windows, Linux, iOS, Android, and web.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can interactively edit all of the examples and tutorials on this website and see the results immediately. See the \u003ca href=\"compression-tutorial\" target=\"_blank\"\u003ecompression tutorial\u003c/a\u003e for a good starting place.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eCogent Lab is still under development, but the basic API should be somewhat stable.\u003c/p\u003e\u003cp id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFeatures include:\u003c/p\u003e\u003cul id=\"frame-4\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• The \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e language transpiler (generates standard Go code) that supports more concise \u003ca href=\"math\" target=\"_blank\"\u003emath\u003c/a\u003e, \u003ca href=\"matrix\" target=\"_blank\"\u003ematrix\u003c/a\u003e, and \u003ca href=\"stats\" target=\"_blank\"\u003estats\u003c/a\u003e expressions that are largely compatible with the widely used \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e framework, in addition to \u003ca href=\"shell\" target=\"_blank\"\u003eshell\u003c/a\u003e command syntax, so it can be used as a replacement for a command-line shell.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• A \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e representation for n-dimensional data, which serves as the universal data type within the Lab framework. The \u003ca href=\"table\" target=\"_blank\"\u003etable\u003c/a\u003e uses tensors as columns for tabular, heterogenous data (similar to the widely-used \u003ca href=\"https://pandas.pydata.org/\" target=\"_blank\"\u003epandas\u003c/a\u003e data table), and the \u003ca href=\"tensorfs\" target=\"_blank\"\u003etensorfs\u003c/a\u003e is a hierarchical filesystem for tensor data that serves as the shared data workspace.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Interactive, full-featured \u003ca href=\"plot\" target=\"_blank\"\u003eplots\u003c/a\u003e and other GUI visualization tools.\u003c/p\u003e\u003cp id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• The \u003ca href=\"lab\" target=\"_blank\"\u003elab\u003c/a\u003e user interface API for flexibly connecting data and visualization components, providing the foundation for interactive data analysis applications integrating different Cogent Lab elements.\u003c/p\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Lab","URL":"lab","Title":"Lab","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":null,"Specials":{},"Description":"\u003cstrong\u003eLab\u003c/strong\u003e contains graphical interface elements for Cogent Lab (Go docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/lab\" target=\"_blank\"\u003elab\u003c/a\u003e), including:","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eLab\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-11\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eLab\u003c/strong\u003e contains graphical interface elements for Cogent Lab (Go docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/lab\" target=\"_blank\"\u003elab\u003c/a\u003e), including:\u003c/p\u003e\u003cul id=\"frame-1\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"browser\" target=\"_blank\"\u003eBrowser\u003c/a\u003e is a default combination of the following elements.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"tabs\" target=\"_blank\"\u003eTabs\u003c/a\u003e provides functions for creating tabs with data elements such as \u003ca href=\"plot\" target=\"_blank\"\u003eplots\u003c/a\u003e and views of \u003ca href=\"table\" target=\"_blank\"\u003etables\u003c/a\u003e.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"datatree\" target=\"_blank\"\u003eDataTree\u003c/a\u003e provides a tree-structured view of \u003ca href=\"tensorfs\" target=\"_blank\"\u003etensorfs\u003c/a\u003e and regular filesystem data.\u003c/p\u003e\u003c/ul\u003e\u003ch2 id=\"lab-pages\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eLab pages\u003c/h2\u003e\u003cul id=\"frame-3\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"browser\" target=\"_blank\"\u003eBrowser\u003c/a\u003e\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"datatree\" target=\"_blank\"\u003eDatatree\u003c/a\u003e\u003c/li\u003e\u003cli id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"tabs\" target=\"_blank\"\u003eTabs\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Math","URL":"math","Title":"Math","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Goal"],"Specials":{},"Description":"\u003cstrong\u003eMath\u003c/strong\u003e mode in \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e provides a \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e-like language for mathematical expressions involving \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e data elements (see \u003ca href=\"math#Reference tables\" target=\"_blank\"\u003eReference tables\u003c/a\u003e), which are transpiled into Go code for compilation or interactive interpretation. It is activated by a \u003ccode\u003e#\u003c/code\u003e character on a line, which is otherwise not a recognized symbol in Go, and \u003ccode\u003e##\u003c/code\u003e starts and stops multi-line blocks of math mode.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eMath\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-12\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eMath\u003c/strong\u003e mode in \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e provides a \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e-like language for mathematical expressions involving \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e data elements (see \u003ca href=\"math#Reference tables\" target=\"_blank\"\u003eReference tables\u003c/a\u003e), which are transpiled into Go code for compilation or interactive interpretation. It is activated by a \u003ccode\u003e#\u003c/code\u003e character on a line, which is otherwise not a recognized symbol in Go, and \u003ccode\u003e##\u003c/code\u003e starts and stops multi-line blocks of math mode.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe most important thing to remember about math mode is that everything must be a tensor! Any variables created in math mode are automatically tensors, but anything created outside of math mode must be converted to a tensor using the \u003ccode\u003earray\u003c/code\u003e function.\u003c/p\u003e\u003ctextarea id=\"editor-2\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003efv := 42.0 // this is a float64\n\n// now we enter math mode:\n##\ntv := 42.0 // this is a tensor.Float64\ntfv := array(fv) // as is this\n##\n\nfmt.Printf(\"fv: %v %T\\n\", fv, fv)\nfmt.Printf(\"tv: %v %T\\n\", tv, tv)\nfmt.Printf(\"tfv: %v %T\\n\", tfv, tfv)\n\u003c/textarea\u003e\u003cdiv id=\"frame-3\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch2 id=\"basics\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eBasics\u003c/h2\u003e\u003cp id=\"text-5\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eHere’s how you can create, inspect, and manipulate tensor data:\u003c/p\u003e\u003ctextarea id=\"editor-6\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\na := [[1., 2., 3.], [4., 5., 6.]] \naShape := a.shape // tensor of sizes of each dim\nb := zeros(aShape) // which can be used to make a new one\nc := a.reshape(3,2) // preserves data while reshaping\nd := arange(1, 11) // like a for loop from 1..11 (exclusive max)\ne := linspace(1., 3., 11, true) // floats over a range: final arg = inclusive\n##\n\nfmt.Println(\"a:\", a)\nfmt.Println(\"aShape:\", aShape)\nfmt.Println(\"b:\", b)\nfmt.Println(\"c:\", c)\nfmt.Println(\"d:\", d)\nfmt.Println(\"e:\", e)\n\u003c/textarea\u003e\u003cdiv id=\"frame-7\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-8\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e(go ahead and play around with any of the above expressions to explore the effects!)\u003c/p\u003e\u003cp id=\"text-9\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNote that, as in Python, you do need to add a decimal point to have a number treated as a floating point value in most cases – otherwise it will be an int.\u003c/p\u003e\u003cp id=\"text-10\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can perform math operations directly using standard operators:\u003c/p\u003e\u003ctextarea id=\"editor-11\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\na := [[1., 2., 3.], [4., 5., 6.]] \nb := a * a\nc := sin(a)\nd := a * [3., 2., 1.] // smaller dims apply repeatedly\n##\n\nfmt.Println(\"a:\", a)\nfmt.Println(\"b:\", b)\nfmt.Println(\"c:\", c)\nfmt.Println(\"d:\", d)\n\u003c/textarea\u003e\u003cdiv id=\"frame-12\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-13\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee \u003ca href=\"tensor-math#Alignment of shapes\" target=\"_blank\"\u003eAlignment of shapes\u003c/a\u003e for more details on \u003ca href=\"tensor-math\" target=\"_blank\"\u003etensor math\u003c/a\u003e operations, using the NumPy \u003ca href=\"https://numpy.org/doc/stable/user/basics.broadcasting.html\" target=\"_blank\"\u003ebroadcasting\u003c/a\u003e logic.\u003c/p\u003e\u003ch3 id=\"tensorfs\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eTensorfs\u003c/h3\u003e\u003cp id=\"text-15\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn an interactive Goal shell (which we simulate here in the docs), variables in math mode are automatically saved to the \u003ca href=\"tensorfs\" target=\"_blank\"\u003etensorfs\u003c/a\u003e virtual data filesystem:\u003c/p\u003e\u003ctextarea id=\"editor-16\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\n// make a new tensorfs directory for this example\nmkdir tfs\ncd tfs\na := [[1., 2., 3.], [4., 5., 6.]]\nsetcp(\"a_copy\", a) // this will preserve values\n\nb := a * a\na += a\n\n// list the current directory:\nls -l\n// go back to root (all vars from this page are there!)\ncd ..\n// (add another ls -l here to see them all..)\n##\n\nfmt.Println(\"a:\", a)\nfmt.Println(\"a get:\", # get(\"tfs/a\") #)\nfmt.Println(\"a copy:\", # get(\"tfs/a_copy\") #)\nfmt.Println(\"b:\", b)\n\u003c/textarea\u003e\u003cdiv id=\"frame-17\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-18\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNote that the filesystem variables are pointers to the live variables, so they always reflect the latest changes, so the \u003ccode\u003esetcp\u003c/code\u003e command is useful for saving a copy that does not get further updated.\u003c/p\u003e\u003ch2 id=\"slicing-and-indexing\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eSlicing and indexing\u003c/h2\u003e\u003cp id=\"text-20\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eMath mode provides NumPy-like ways of extracting data from a tensor (examples follow Go versions in \u003ca href=\"tensor#Views and values\" target=\"_blank\"\u003eViews and values\u003c/a\u003e).\u003c/p\u003e\u003ctextarea id=\"editor-21\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := linspace(0., 12., 12., false).reshape(3,4)\n\nrow1 := x[1]\ncol1 := x[:,1]\n##\n\nfmt.Println(\"x:\", x)\nfmt.Println(\"row1:\", row1)\nfmt.Println(\"col:\", col1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-22\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-23\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWhere \u003ccode\u003e:\u003c/code\u003e is an empty \u003ccode\u003eslice\u003c/code\u003e expression that indicates all values in that dimension.\u003c/p\u003e\u003cp id=\"text-24\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo get the column as a column vector, use \u003ccode\u003enewaxis\u003c/code\u003e:\u003c/p\u003e\u003ctextarea id=\"editor-25\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := linspace(0., 12., 12., false).reshape(3,4)\n\ncol1 := x[:, 1, newaxis]\n##\n\nfmt.Println(\"col1:\", col1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-26\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-27\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo get ranges within each dimension, or reorder, use \u003ccode\u003eslice\u003c/code\u003e expressions similar to those used in accessing Go slices, but with a 3rd \u003ccode\u003eStep\u003c/code\u003e value, as in a standard Go \u003ccode\u003efor\u003c/code\u003e loop:\u003c/p\u003e\u003ctextarea id=\"editor-28\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := linspace(0., 12., 12., false).reshape(3,4)\n\nrow1 := x[1, 1:3] // only a subset of columns\ncol1 := x[::-1, 1] // reverse order of rows dimension\n##\n\nfmt.Println(\"row1:\", row1)\nfmt.Println(\"col1:\", col1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-29\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-30\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eEllipsis (\u003ccode\u003e...\u003c/code\u003e) makes it easy to get the last dimension(s):\u003c/p\u003e\u003ctextarea id=\"editor-31\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := linspace(0., 12., 12., false).reshape(3,2,2)\n\nlast1 := x[..., 1]\n##\n\nfmt.Println(\"x\", x)\nfmt.Println(\"last1:\", last1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-32\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-33\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAs in \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e (and standard Go slices), indexed subsets of a tensor are \u003cem\u003eviews\u003c/em\u003e onto the original tensor, so that changes to the original values are immediately seen in these views. Use \u003ccode\u003ecopy\u003c/code\u003e to make a new separate copy of the values to break this connection.\u003c/p\u003e\u003ctextarea id=\"editor-34\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := linspace(0., 12., 12., false).reshape(3,2,2)\n\nlast1 := x[..., 1]\ncp1 := copy(last1)\n\nx[..., 1, 1] = 3.14 // note how we assign to all rows\n##\n\nfmt.Println(\"x\", x)\nfmt.Println(\"last1:\", last1)\nfmt.Println(\"cp1:\", cp1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-35\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch3 id=\"masked-by-booleans\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eMasked by booleans\u003c/h3\u003e\u003ctextarea id=\"editor-37\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := linspace(0., 12., 12., false).reshape(3,4)\n\nm := x[x\u003e=6]\nmi := x \u003e= 6\n##\n\nfmt.Println(\"m:\", m)\nfmt.Println(\"mi:\", mi)\n\u003c/textarea\u003e\u003cdiv id=\"frame-38\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch3 id=\"arbitrary-indexes\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eArbitrary indexes\u003c/h3\u003e\u003ctextarea id=\"editor-40\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := linspace(0., 12., 12., false).reshape(3,4)\n\nixs := [[0, 1], [0, 1], [0, 2], [0, 2], [1, 1], [1, 1], [2, 2], [2, 2]].reshape(2,4,2)\n\nix := x[ixs]\n##\n\nfmt.Println(\"ix:\", ix)\nfmt.Println(\"ixs:\", ixs)\n\u003c/textarea\u003e\u003cdiv id=\"frame-41\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch2 id=\"reference-tables\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eReference tables\u003c/h2\u003e\u003cp id=\"text-43\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe following tables summarize Goal math-mode syntax in terms of \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e and the underlying Go code generated. For MATLAB equivalents, see \u003ca href=\"https://numpy.org/doc/stable/user/numpy-for-matlab-users.html\" target=\"_blank\"\u003enumpy-for-matlab-users\u003c/a\u003e.\u003c/p\u003e\u003cul id=\"frame-44\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• The \u003cem\u003esame:\u003c/em\u003e in Goal means that the same NumPy syntax works in Goal, minus the \u003ccode\u003enp.\u003c/code\u003e prefix, and likewise for \u003cem\u003eor:\u003c/em\u003e (where Goal also has additional syntax).\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• In the \u003ccode\u003etensor.Go\u003c/code\u003e code, we sometimes just write a scalar number for simplicity, but these are actually \u003ccode\u003etensor.NewFloat64Scalar\u003c/code\u003e etc.\u003c/li\u003e\u003cli id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Goal also has support for \u003ccode\u003estring\u003c/code\u003e tensors, e.g., for labels, and operators such as addition that make sense for strings are supported. Otherwise, strings are automatically converted to numbers using the \u003ccode\u003etensor.Float\u003c/code\u003e interface. If you have any doubt about whether you’ve got a \u003ccode\u003etensor.Float64\u003c/code\u003e when you expect one, use \u003ccode\u003etensor.AsFloat64Tensor\u003c/code\u003e which makes sure.\u003c/li\u003e\u003c/ul\u003e\u003ch3 id=\"tensor-shape\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eTensor shape\u003c/h3\u003e\u003ctable id=\"frame-46\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.NumDim()\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003endim(a)\u003c/code\u003e or \u003ccode\u003ea.ndim\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.ndim(a)\u003c/code\u003e or \u003ccode\u003ea.ndim\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003enumber of dimensions of tensor \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.Len()\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003elen(a)\u003c/code\u003e or \u003ccode\u003ea.len\u003c/code\u003e or:\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.size(a)\u003c/code\u003e or \u003ccode\u003ea.size\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003enumber of elements of tensor \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.Shape().Sizes\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.shape(a)\u003c/code\u003e or \u003ccode\u003ea.shape\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e“size” of each dimension in a; \u003ccode\u003eshape\u003c/code\u003e returns a 1D \u003ccode\u003eint\u003c/code\u003e tensor\u003c/td\u003e\u003ctd id=\"text-16\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.Shape().Sizes[1]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-17\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-18\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.shape[1]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-19\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ethe number of elements of the 2nd dimension of tensor \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-20\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.Reshape(a, 10, 2)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-21\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame except no \u003ccode\u003ea.shape = (10,2)\u003c/code\u003e:\u003c/td\u003e\u003ctd id=\"text-22\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.reshape(10, 2)\u003c/code\u003e or \u003ccode\u003enp.reshape(a, 10, 2)\u003c/code\u003e or \u003ccode\u003ea.shape = (10,2)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-23\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eset the shape of \u003ccode\u003ea\u003c/code\u003e to a new shape that has the same total number of values (len or size); No option to change order in Goal: always row major; Goal does \u003cem\u003enot\u003c/em\u003e support direct shape assignment version.\u003c/td\u003e\u003ctd id=\"text-24\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.Reshape(a, tensor.AsIntSlice(sh)...)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-25\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-26\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.reshape(10, sh)\u003c/code\u003e or \u003ccode\u003enp.reshape(a, sh)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-27\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eset shape based on list of dimension sizes in tensor \u003ccode\u003esh\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-28\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.Reshape(a, -1)\u003c/code\u003e or \u003ccode\u003etensor.As1D(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-29\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-30\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.reshape(-1)\u003c/code\u003e or \u003ccode\u003enp.reshape(a, -1)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-31\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ea 1D vector view of \u003ccode\u003ea\u003c/code\u003e; Goal does not support \u003ccode\u003eravel\u003c/code\u003e, which is nearly identical.\u003c/td\u003e\u003ctd id=\"text-32\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.Flatten(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-33\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-34\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eb = a.flatten()\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-35\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ereturns a 1D copy of a\u003c/td\u003e\u003ctd id=\"text-36\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eb := tensor.Clone(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-37\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eb := copy(a)\u003c/code\u003e or:\u003c/td\u003e\u003ctd id=\"text-38\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eb = a.copy()\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-39\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003edirect assignment \u003ccode\u003eb = a\u003c/code\u003e in Goal or NumPy just makes variable b point to tensor a; \u003ccode\u003ecopy\u003c/code\u003e is needed to generate new underlying values (MATLAB always makes a copy)\u003c/td\u003e\u003ctd id=\"text-40\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.Squeeze(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-41\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-42\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.squeeze()\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-43\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eremove singleton dimensions of tensor \u003ccode\u003ea\u003c/code\u003e.\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"constructing\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eConstructing\u003c/h3\u003e\u003ctable id=\"frame-48\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.NewFloat64FromValues(\u003c/code\u003e \u003ccode\u003e1, 2, 3)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003e[1., 2., 3.]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.array([1., 2., 3.])\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003edefine a 1D tensor\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e(reshape)\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003e[[1., 2., 3.], [4., 5., 6.]]\u003c/code\u003e or:\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003e(np.array([[1., 2., 3.], [4., 5., 6.]])\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003edefine a 2x3 2D tensor\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e(reshape)\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003e[[a, b], [c, d]]\u003c/code\u003e or \u003ccode\u003eblock([[a, b], [c, d]])\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.block([[a, b], [c, d]])\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003econstruct a matrix from blocks \u003ccode\u003ea\u003c/code\u003e, \u003ccode\u003eb\u003c/code\u003e, \u003ccode\u003ec\u003c/code\u003e, and \u003ccode\u003ed\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-16\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.NewFloat64(3,4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-17\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ezeros(3,4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-18\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.zeros((3, 4))\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-19\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e3x4 2D tensor of float64 zeros; Goal does not use “tuple” so no double parens\u003c/td\u003e\u003ctd id=\"text-20\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.NewFloat64(3,4,5)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-21\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ezeros(3, 4, 5)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-22\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.zeros((3, 4, 5))\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-23\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e3x4x5 three-dimensional tensor of float64 zeros\u003c/td\u003e\u003ctd id=\"text-24\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.NewFloat64Ones(3,4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-25\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eones(3, 4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-26\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.ones((3, 4))\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-27\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e3x4 2D tensor of 64-bit floating point ones\u003c/td\u003e\u003ctd id=\"text-28\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.NewFloat64Full(5.5, 3,4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-29\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003efull(5.5, 3, 4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-30\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.full((3, 4), 5.5)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-31\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e3x4 2D tensor of 5.5; Goal variadic arg structure requires value to come first\u003c/td\u003e\u003ctd id=\"text-32\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.NewFloat64Rand(3,4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-33\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003erand(3, 4)\u003c/code\u003e or \u003ccode\u003eslrand(c, fi, 3, 4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-34\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003erng.random(3, 4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-35\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e3x4 2D float64 tensor with uniform random 0..1 elements; \u003ccode\u003erand\u003c/code\u003e uses current Go \u003ccode\u003erand\u003c/code\u003e source, while \u003ccode\u003eslrand\u003c/code\u003e uses \u003ca href=\"../gpu/gosl/slrand\"\u003egosl\u003c/a\u003e GPU-safe call with counter \u003ccode\u003ec\u003c/code\u003e and function index \u003ccode\u003efi\u003c/code\u003e and key = index of element\u003c/td\u003e\u003ctd id=\"text-36\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/td\u003e\u003ctd id=\"text-37\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/td\u003e\u003ctd id=\"text-38\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.concatenate((a,b),1)\u003c/code\u003e or \u003ccode\u003enp.hstack((a,b))\u003c/code\u003e or \u003ccode\u003enp.column_stack((a,b))\u003c/code\u003e or \u003ccode\u003enp.c_[a,b]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-39\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003econcatenate columns of a and b\u003c/td\u003e\u003ctd id=\"text-40\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/td\u003e\u003ctd id=\"text-41\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/td\u003e\u003ctd id=\"text-42\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.concatenate((a,b))\u003c/code\u003e or \u003ccode\u003enp.vstack((a,b))\u003c/code\u003e or \u003ccode\u003enp.r_[a,b]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-43\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003econcatenate rows of a and b\u003c/td\u003e\u003ctd id=\"text-44\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/td\u003e\u003ctd id=\"text-45\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/td\u003e\u003ctd id=\"text-46\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.tile(a, (m, n))\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-47\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ecreate m by n copies of a\u003c/td\u003e\u003ctd id=\"text-48\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/td\u003e\u003ctd id=\"text-49\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/td\u003e\u003ctd id=\"text-50\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[np.r_[:len(a),0]]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-51\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea\u003c/code\u003e with copy of the first row appended to the end\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"ranges-and-grids\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eRanges and grids\u003c/h3\u003e\u003cp id=\"text-50\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee \u003ca href=\"https://numpy.org/doc/stable/user/how-to-partition.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e docs for details.\u003c/p\u003e\u003ctable id=\"frame-51\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.NewIntRange(1, 11)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.arange(1., 11.)\u003c/code\u003e or \u003ccode\u003enp.r_[1.:11.]\u003c/code\u003e or \u003ccode\u003enp.r_[1:10:10j]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ecreate an increasing vector; \u003ccode\u003earange\u003c/code\u003e in goal is always ints; use \u003ccode\u003elinspace\u003c/code\u003e or \u003ccode\u003etensor.AsFloat64\u003c/code\u003e for floats\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.arange(10.)\u003c/code\u003e or \u003ccode\u003enp.r_[:10.]\u003c/code\u003e or \u003ccode\u003enp.r_[:9:10j]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ecreate an increasing vector; 1 arg is the stop value in a slice\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.arange(1.,11.)\u003c/code\u003e \u003ccode\u003e[:, np.newaxis]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ecreate a column vector\u003c/td\u003e\u003ctd id=\"text-16\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.NewFloat64\u003c/code\u003e \u003ccode\u003eSpacedLinear(\u003c/code\u003e \u003ccode\u003e1, 3, 4, true)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-17\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003elinspace(1,3,4,true)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-18\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.linspace(1,3,4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-19\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e4 equally spaced samples between 1 and 3, inclusive of end (use \u003ccode\u003efalse\u003c/code\u003e at end for exclusive)\u003c/td\u003e\u003ctd id=\"text-20\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-21\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-22\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.mgrid[0:9.,0:6.]\u003c/code\u003e or \u003ccode\u003enp.meshgrid(r_[0:9.],\u003c/code\u003e \u003ccode\u003er_[0:6.])\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-23\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003etwo 2D tensors: one of x values, the other of y values\u003c/td\u003e\u003ctd id=\"text-24\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-25\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-26\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eogrid[0:9.,0:6.]\u003c/code\u003e or \u003ccode\u003enp.ix_(np.r_[0:9.],\u003c/code\u003e \u003ccode\u003enp.r_[0:6.]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-27\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ethe best way to eval functions on a grid\u003c/td\u003e\u003ctd id=\"text-28\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-29\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-30\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.meshgrid([1,2,4],\u003c/code\u003e \u003ccode\u003e[2,4,5])\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-31\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-32\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-33\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-34\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.ix_([1,2,4],\u003c/code\u003e \u003ccode\u003e[2,4,5])\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-35\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ethe best way to eval functions on a grid\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"basic-indexing\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eBasic indexing\u003c/h3\u003e\u003cp id=\"text-53\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee \u003ca href=\"https://numpy.org/doc/stable/user/basics.indexing.html#basic-indexing\" target=\"_blank\"\u003eNumPy basic indexing\u003c/a\u003e. Tensor Go uses the \u003ccode\u003eReslice\u003c/code\u003e function for all cases (repeated \u003ccode\u003etensor.\u003c/code\u003e prefix replaced with \u003ccode\u003et.\u003c/code\u003e to take less space). Here you can clearly see the advantage of Goal in allowing significantly more succinct expressions to be written for accomplishing critical tensor functionality.\u003c/p\u003e\u003ctable id=\"frame-54\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a, 1, 4)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[1, 4]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eaccess element in second row, fifth column in 2D tensor \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a, -1)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[-1]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eaccess last element\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a,\u003c/code\u003e \u003ccode\u003e1, t.FullAxis)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[1]\u003c/code\u003e or \u003ccode\u003ea[1, :]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eentire second row of 2D tensor \u003ccode\u003ea\u003c/code\u003e; unspecified dimensions are equivalent to \u003ccode\u003e:\u003c/code\u003e (could omit second arg in Reslice too)\u003c/td\u003e\u003ctd id=\"text-16\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a,\u003c/code\u003e \u003ccode\u003eSlice{Stop:5})\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-17\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-18\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[0:5]\u003c/code\u003e or \u003ccode\u003ea[:5]\u003c/code\u003e or \u003ccode\u003ea[0:5, :]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-19\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e0..4 rows of \u003ccode\u003ea\u003c/code\u003e; uses same Go slice ranging here: (start:stop) where stop is \u003cem\u003eexclusive\u003c/em\u003e\u003c/td\u003e\u003ctd id=\"text-20\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a,\u003c/code\u003e \u003ccode\u003eSlice{Start:-5})\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-21\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-22\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[-5:]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-23\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003elast 5 rows of 2D tensor \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-24\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a,\u003c/code\u003e \u003ccode\u003et.NewAxis,\u003c/code\u003e \u003ccode\u003eSlice{Start:-5})\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-25\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-26\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[newaxis, -5:]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-27\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003elast 5 rows of 2D tensor \u003ccode\u003ea\u003c/code\u003e, as a column vector\u003c/td\u003e\u003ctd id=\"text-28\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a,\u003c/code\u003e \u003ccode\u003eSlice{Stop:3},\u003c/code\u003e \u003ccode\u003eSlice{Start:4, Stop:9})\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-29\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-30\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[0:3, 4:9]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-31\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe first through third rows and fifth through ninth columns of a 2D tensor, \u003ccode\u003ea\u003c/code\u003e.\u003c/td\u003e\u003ctd id=\"text-32\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a,\u003c/code\u003e \u003ccode\u003eSlice{Start:2,\u003c/code\u003e \u003ccode\u003eStop:25,\u003c/code\u003e \u003ccode\u003eStep:2}, t.FullAxis)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-33\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-34\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[2:21:2,:]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-35\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eevery other row of \u003ccode\u003ea\u003c/code\u003e, starting with the third and going to the twenty-first\u003c/td\u003e\u003ctd id=\"text-36\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a,\u003c/code\u003e \u003ccode\u003eSlice{Step:2},\u003c/code\u003e \u003ccode\u003et.FullAxis)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-37\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-38\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[::2, :]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-39\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eevery other row of \u003ccode\u003ea\u003c/code\u003e, starting with the first\u003c/td\u003e\u003ctd id=\"text-40\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Reslice(a,\u003c/code\u003e, \u003ccode\u003eSlice{Step:-1},\u003c/code\u003e \u003ccode\u003et.FullAxis)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-41\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-42\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[::-1,:]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-43\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea\u003c/code\u003e with rows in reverse order\u003c/td\u003e\u003ctd id=\"text-44\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003et.Clone(t.Reslice(a,\u003c/code\u003e \u003ccode\u003e1, t.FullAxis))\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-45\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eb = copy(a[1, :])\u003c/code\u003e or:\u003c/td\u003e\u003ctd id=\"text-46\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eb = a[1, :].copy()`\u003c/td\u003e\u003ctd id=\"text-47\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ewithout the copy, \u003ccode\u003ey\u003c/code\u003e would point to a view of values in \u003ccode\u003ex\u003c/code\u003e; \u003ccode\u003ecopy\u003c/code\u003e creates distinct values, in this case of \u003cem\u003eonly\u003c/em\u003e the 2nd row of \u003ccode\u003ex\u003c/code\u003e – i.e., it “concretizes” a given view into a literal, memory-continuous set of values for that view.\u003c/td\u003e\u003ctd id=\"text-48\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Assign(\u003c/code\u003e \u003ccode\u003et.Reslice(a,\u003c/code\u003e \u003ccode\u003eSlice{Stop:5}),\u003c/code\u003e \u003ccode\u003et.NewIntScalar(2))\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-49\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-50\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[:5] = 2\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-51\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eassign the value 2 to 0..4 rows of \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-52\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e(you get the idea)\u003c/td\u003e\u003ctd id=\"text-53\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-54\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[:5] = b[:, :5]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-55\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eassign the values in the first 5 columns of \u003ccode\u003eb\u003c/code\u003e to the first 5 rows of \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"boolean-tensors-and-indexing\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eBoolean tensors and indexing\u003c/h3\u003e\u003cp id=\"text-56\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee \u003ca href=\"https://numpy.org/doc/stable/user/basics.indexing.html#boolean-array-indexing\" target=\"_blank\"\u003eNumPy boolean indexing\u003c/a\u003e.\u003c/p\u003e\u003cp id=\"text-57\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNote that Goal only supports boolean logical operators (\u003ccode\u003e\u0026\u0026\u003c/code\u003e and \u003ccode\u003e||\u003c/code\u003e) on boolean tensors, not the single bitwise operators \u003ccode\u003e\u0026\u003c/code\u003e and \u003ccode\u003e|\u003c/code\u003e.\u003c/p\u003e\u003ctable id=\"frame-58\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Greater(a, 0.5)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003e(a \u003e 0.5)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ebool\u003c/code\u003e tensor of shape \u003ccode\u003ea\u003c/code\u003e with elements \u003ccode\u003e(v \u003e 0.5)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.And(a, b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea \u0026\u0026 b\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003elogical_and(a,b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eelement-wise AND operator on \u003ccode\u003ebool\u003c/code\u003e tensors\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Or(a, b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea \\|\\| b\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.logical_or(a,b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eelement-wise OR operator on \u003ccode\u003ebool\u003c/code\u003e tensors\u003c/td\u003e\u003ctd id=\"text-16\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Negate(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-17\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003e!a\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-18\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e?\u003c/td\u003e\u003ctd id=\"text-19\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eelement-wise negation on \u003ccode\u003ebool\u003c/code\u003e tensors\u003c/td\u003e\u003ctd id=\"text-20\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Assign(\u003c/code\u003e \u003ccode\u003etensor.Mask(a,\u003c/code\u003e \u003ccode\u003etmath.Less(a, 0.5),\u003c/code\u003e \u003ccode\u003e0)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-21\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-22\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[a \u003c 0.5]=0\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-23\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea\u003c/code\u003e with elements less than 0.5 zeroed out\u003c/td\u003e\u003ctd id=\"text-24\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.Flatten(\u003c/code\u003e \u003ccode\u003etensor.Mask(a,\u003c/code\u003e \u003ccode\u003etmath.Less(a, 0.5)))\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-25\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-26\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[a \u003c 0.5].flatten()\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-27\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ea 1D list of the elements of \u003ccode\u003ea\u003c/code\u003e \u003c 0.5 (as a copy, not a view)\u003c/td\u003e\u003ctd id=\"text-28\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.Mul(a,\u003c/code\u003e \u003ccode\u003etmath.Greater(a, 0.5))\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-29\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-30\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea * (a \u003e 0.5)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-31\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea\u003c/code\u003e with elements less than 0.5 zeroed out\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"advanced-index-based-indexing\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eAdvanced index-based indexing\u003c/h3\u003e\u003cp id=\"text-60\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee \u003ca href=\"https://numpy.org/doc/stable/user/basics.indexing.html#integer-array-indexing\" target=\"_blank\"\u003eNumPy integer indexing\u003c/a\u003e. Note that the current NumPy version of indexed is rather complex and difficult for many people to understand, as articulated in this \u003ca href=\"https://numpy.org/neps/nep-0021-advanced-indexing.html\" target=\"_blank\"\u003eNEP 21 proposal\u003c/a\u003e.\u003c/p\u003e\u003cp id=\"text-61\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eTODO:\u003c/strong\u003e not yet implemented:\u003c/p\u003e\u003ctable id=\"frame-62\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[np.ix_([1, 3, 4], [0, 2])]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003erows 2,4 and 5 and columns 1 and 3.\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.nonzero(a \u003e 0.5)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003efind the indices where (a \u003e 0.5)\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[:, v.T \u003e 0.5]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eextract the columns of \u003ccode\u003ea\u003c/code\u003e where column vector \u003ccode\u003ev\u003c/code\u003e \u003e 0.5\u003c/td\u003e\u003ctd id=\"text-16\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-17\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-18\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[:,np.nonzero(v \u003e 0.5)[0]]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-19\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eextract the columns of \u003ccode\u003ea\u003c/code\u003e where vector \u003ccode\u003ev\u003c/code\u003e \u003e 0.5\u003c/td\u003e\u003ctd id=\"text-20\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-21\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-22\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea[:] = 3\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-23\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eset all values to the same scalar value\u003c/td\u003e\u003ctd id=\"text-24\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-25\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-26\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.sort(a)\u003c/code\u003e or \u003ccode\u003ea.sort(axis=0)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-27\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esort each column of a 2D tensor, \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-28\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-29\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-30\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.sort(a, axis=1)\u003c/code\u003e or \u003ccode\u003ea.sort(axis=1)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-31\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esort the each row of 2D tensor, \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-32\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-33\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-34\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eI = np.argsort(a[:, 0]); b = a[I,:]\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-35\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esave the tensor \u003ccode\u003ea\u003c/code\u003e as tensor \u003ccode\u003eb\u003c/code\u003e with rows sorted by the first column\u003c/td\u003e\u003ctd id=\"text-36\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-37\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-38\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.unique(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-39\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ea vector of unique values in tensor \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"basic-math-operations-add-multiply-etc\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eBasic math operations (add, multiply, etc)\u003c/h3\u003e\u003cp id=\"text-64\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn Goal and NumPy, the standard \u003ccode\u003e+, -, *, /\u003c/code\u003e operators perform \u003cem\u003eelement-wise\u003c/em\u003e operations because those are well-defined for all dimensionalities and are consistent across the different operators, whereas matrix multiplication is specifically used in a 2D linear algebra context, and is not well defined for the other operators.\u003c/p\u003e\u003ctable id=\"frame-65\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Add(a,b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea + b\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eelement-wise addition; Goal does this string-wise for string tensors\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Mul(a,b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea * b\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eelement-wise multiply\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Div(a,b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea/b\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eelement-wise divide. \u003cem\u003eimportant:\u003c/em\u003e this always produces a floating point result.\u003c/td\u003e\u003ctd id=\"text-16\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Mod(a,b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-17\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-18\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea%b\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-19\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eelement-wise modulous (works for float and int)\u003c/td\u003e\u003ctd id=\"text-20\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Pow(a,3)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-21\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-22\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea**3\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-23\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eelement-wise exponentiation\u003c/td\u003e\u003ctd id=\"text-24\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etmath.Cos(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-25\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-26\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ecos(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-27\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eelement-wise function application\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"2d-matrix-linear-algebra\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003e2D Matrix Linear Algebra\u003c/h3\u003e\u003ctable id=\"frame-67\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ematrix.Mul(a,b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esame:\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea @ b\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ematrix multiply\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor.Transpose(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eor \u003ccode\u003ea.T\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.transpose()\u003c/code\u003e or \u003ccode\u003ea.T\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003etranspose of \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO:\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.conj().transpose() or a.conj().T\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003econjugate transpose of \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-16\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ematrix.Det(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-17\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ematrix.Det(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-18\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.linalg.det(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-19\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003edeterminant of \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-20\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ematrix.Identity(3)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-21\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-22\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.eye(3)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-23\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e3x3 identity matrix\u003c/td\u003e\u003ctd id=\"text-24\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ematrix.Diagonal(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-25\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-26\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.diag(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-27\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ereturns a vector of the diagonal elements of 2D tensor, \u003ccode\u003ea\u003c/code\u003e. Goal returns a read / write view.\u003c/td\u003e\u003ctd id=\"text-28\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-29\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-30\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.diag(v, 0)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-31\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ereturns a square diagonal matrix whose nonzero values are the elements of vector, v\u003c/td\u003e\u003ctd id=\"text-32\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ematrix.Trace(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-33\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-34\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.trace(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-35\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ereturns the sum of the elements along the diagonal of \u003ccode\u003ea\u003c/code\u003e.\u003c/td\u003e\u003ctd id=\"text-36\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ematrix.Tri()\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-37\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-38\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.tri()\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-39\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ereturns a new 2D Float64 matrix with 1s in the lower triangular region (including the diagonal) and the remaining upper triangular elements zero\u003c/td\u003e\u003ctd id=\"text-40\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ematrix.TriL(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-41\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-42\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.tril(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-43\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ereturns a copy of \u003ccode\u003ea\u003c/code\u003e with the lower triangular elements (including the diagonal) from \u003ccode\u003ea\u003c/code\u003e and the remaining upper triangular elements zeroed out\u003c/td\u003e\u003ctd id=\"text-44\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ematrix.TriU(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-45\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-46\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.triu(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-47\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ereturns a copy of \u003ccode\u003ea\u003c/code\u003e with the upper triangular elements (including the diagonal) from \u003ccode\u003ea\u003c/code\u003e and the remaining lower triangular elements zeroed out\u003c/td\u003e\u003ctd id=\"text-48\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-49\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-50\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003elinalg.inv(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-51\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003einverse of square 2D tensor a\u003c/td\u003e\u003ctd id=\"text-52\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-53\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-54\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003elinalg.pinv(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-55\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003epseudo-inverse of 2D tensor a\u003c/td\u003e\u003ctd id=\"text-56\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-57\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-58\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.linalg.matrix_rank(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-59\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ematrix rank of a 2D tensor a\u003c/td\u003e\u003ctd id=\"text-60\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-61\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-62\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003elinalg.solve(a, b)\u003c/code\u003e if \u003ccode\u003ea\u003c/code\u003e is square; \u003ccode\u003elinalg.lstsq(a, b)\u003c/code\u003e otherwise\u003c/td\u003e\u003ctd id=\"text-63\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esolution of \u003ccode\u003ea x = b\u003c/code\u003e for x\u003c/td\u003e\u003ctd id=\"text-64\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-65\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-66\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eSolve \u003ccode\u003ea.T x.T = b.T\u003c/code\u003e instead\u003c/td\u003e\u003ctd id=\"text-67\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esolution of x a = b for x\u003c/td\u003e\u003ctd id=\"text-68\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-69\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-70\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eU, S, Vh = linalg.svd(a); V = Vh.T\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-71\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003esingular value decomposition of a\u003c/td\u003e\u003ctd id=\"text-72\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-73\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-74\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003elinalg.cholesky(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-75\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eCholesky factorization of a 2D tensor\u003c/td\u003e\u003ctd id=\"text-76\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-77\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-78\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eD,V = linalg.eig(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-79\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eeigenvalues and eigenvectors of \u003ccode\u003ea\u003c/code\u003e, where \u003ccode\u003e[V,D]=eig(a,b)\u003c/code\u003e eigenvalues and eigenvectors of \u003ccode\u003ea, b\u003c/code\u003e where\u003c/td\u003e\u003ctd id=\"text-80\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-81\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-82\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eD,V = eigs(a, k=3)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-83\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eD,V = linalg.eig(a, b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-84\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-85\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-86\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eQ,R = linalg.qr(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-87\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eQR decomposition\u003c/td\u003e\u003ctd id=\"text-88\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-89\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-90\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eP,L,U = linalg.lu(a)\u003c/code\u003e where \u003ccode\u003ea == P@L@U\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-91\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eLU decomposition with partial pivoting (note: P(MATLAB) == transpose(P(NumPy)))\u003c/td\u003e\u003ctd id=\"text-92\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-93\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-94\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ex = linalg.lstsq(Z, y)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-95\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eperform a linear regression of the form\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"statistics\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eStatistics\u003c/h3\u003e\u003ctable id=\"frame-69\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.max()\u003c/code\u003e or \u003ccode\u003emax(a)\u003c/code\u003e or \u003ccode\u003estats.Max(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.max()\u003c/code\u003e or \u003ccode\u003enp.nanmax(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003emaximum element of \u003ccode\u003ea\u003c/code\u003e, Goal always ignores \u003ccode\u003eNaN\u003c/code\u003e as missing data\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.max(0)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003emaximum element of each column of tensor \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ea.max(1)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003emaximum element of each row of tensor \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-16\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-17\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-18\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.maximum(a, b)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-19\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003ecompares a and b element-wise, and returns the maximum value from each pair\u003c/td\u003e\u003ctd id=\"text-20\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003estats.L2Norm(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-21\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-22\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.sqrt(v @ v)\u003c/code\u003e or \u003ccode\u003enp.linalg.norm(v)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-23\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eL2 norm of vector v\u003c/td\u003e\u003ctd id=\"text-24\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-25\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-26\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ecg\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-27\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003econjugate gradients solver\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"fft-and-complex-numbers\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eFFT and complex numbers\u003c/h3\u003e\u003cp id=\"text-71\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003etodo: huge amount of work needed to support complex numbers throughout!\u003c/p\u003e\u003ctable id=\"frame-72\" style=\"display:grid;flex-direction:row;flex-grow:1;justify-content:center;align-items:start;columns:4;gap:6px;font-weight:thin;text-align:start\"\u003e\u003cth id=\"text-0\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensor\u003c/code\u003e Go\u003c/th\u003e\u003cth id=\"text-1\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eGoal\u003c/th\u003e\u003cth id=\"text-2\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNumPy\u003c/th\u003e\u003cth id=\"text-3\" style=\"margin:6px;font-weight:bold;line-height:1.5;text-align:start\"\u003eNotes\u003c/th\u003e\u003ctd id=\"text-4\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-5\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-6\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.fft.fft(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-7\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003eFourier transform of \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-8\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-9\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-10\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003enp.fft.ifft(a)\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-11\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003einverse Fourier transform of \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-12\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-13\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e.\u003c/td\u003e\u003ctd id=\"text-14\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003esignal.resample(x, np.ceil(len(x)/q))\u003c/code\u003e\u003c/td\u003e\u003ctd id=\"text-15\" style=\"margin:6px;font-weight:normal;line-height:1.5;text-align:start\"\u003edownsample with low-pass filtering\u003c/td\u003e\u003c/table\u003e\u003ch3 id=\"tensorfs-1\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eTensorfs\u003c/h3\u003e\u003cp id=\"text-74\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ca href=\"tensorfs\" target=\"_blank\"\u003etensorfs\u003c/a\u003e data filesystem provides a global filesystem-like workspace for storing tensor data, and \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e has special commands and functions to facilitate interacting with it.\u003c/p\u003e\u003cp id=\"text-75\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn an interactive \u003ccode\u003egoal\u003c/code\u003e shell, when you do \u003ccode\u003e##\u003c/code\u003e to switch into math mode, the prompt changes to show your current directory in the tensorfs, not the regular OS filesystem, and the final prompt character turns into a \u003ccode\u003e#\u003c/code\u003e.\u003c/p\u003e\u003cp id=\"text-76\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eUse \u003ccode\u003eget\u003c/code\u003e and \u003ccode\u003eset\u003c/code\u003e (aliases for \u003ccode\u003etensorfs.Get\u003c/code\u003e and \u003ccode\u003etensorfs.Set\u003c/code\u003e) to retrieve and store data in the tensorfs:\u003c/p\u003e\u003cul id=\"frame-77\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003ex := get(\"path/to/item\")\u003c/code\u003e retrieves the tensor data value at given path, which can then be used directly in an expression or saved to a new variable as in this example.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eset(\"path/to/item\", x)\u003c/code\u003e saves tensor data to given path, overwriting any existing value for that item if it already exists, and creating a new one if not. \u003ccode\u003ex\u003c/code\u003e can be any data expression.\u003c/p\u003e\u003c/ul\u003e\u003cp id=\"text-78\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can use the standard shell commands to navigate around the data filesystem:\u003c/p\u003e\u003cul id=\"frame-79\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003ecd \u003cdir\u003e\u003c/code\u003e to change the current working directory. By default, new variables created in the shell are also recorded into the current working directory for later access.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003els [-l,r] [dir]\u003c/code\u003e list the contents of a directory; without arguments, it shows the current directory. The \u003ccode\u003e-l\u003c/code\u003e option shows each element on a separate line with its shape. \u003ccode\u003e-r\u003c/code\u003e does a recursive list through subdirectories.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003emkdir \u003cdir\u003e\u003c/code\u003e makes a new subdirectory.\u003c/p\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cstretch id=\"content-buttons-go-131\" style=\"display:flex;flex-direction:row;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;font-weight:thin;text-align:start\"\u003e\u003c/stretch\u003e\u003ca id=\"content-buttons-go-132\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"shell\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"M686-450H160v-60h526L438-758l42-42 320 320-320 320-42-42 248-248Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003eNext\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Matrix","URL":"matrix","Title":"Matrix","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Tensor"],"Specials":{},"Description":"\u003cstrong\u003eMatrix\u003c/strong\u003e provides standard 2D linear algebra functions on \u003ca href=\"tensor\" target=\"_blank\"\u003etensors\u003c/a\u003e, using \u003ca href=\"https://github.com/gonum/gonum\" target=\"_blank\"\u003egonum\u003c/a\u003e functions for the implementations.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eMatrix\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-13\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eMatrix\u003c/strong\u003e provides standard 2D linear algebra functions on \u003ca href=\"tensor\" target=\"_blank\"\u003etensors\u003c/a\u003e, using \u003ca href=\"https://github.com/gonum/gonum\" target=\"_blank\"\u003egonum\u003c/a\u003e functions for the implementations.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eBasic matrix multiplication:\u003c/p\u003e\u003ctextarea id=\"editor-2\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\na := linspace(1., 4., 4., true).reshape(2, 2)\nv := [2., 3.]\n\nb := matrix.Mul(a, a)\nc := matrix.Mul(a, v)\nd := matrix.Mul(v, a)\n##\n\nfmt.Println(\"a:\", a)\nfmt.Println(\"b:\", b)\nfmt.Println(\"c:\", c)\nfmt.Println(\"d:\", d)\n\u003c/textarea\u003e\u003cdiv id=\"frame-3\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAnd other standard matrix operations:\u003c/p\u003e\u003ctextarea id=\"editor-5\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\na := linspace(1., 4., 4., true).reshape(2, 2)\n\nt := tensor.Transpose(a)\nd := matrix.Det(a)\ni := matrix.Inverse(a)\n##\n\nfmt.Println(\"t:\", t)\nfmt.Println(\"d:\", d)\nfmt.Println(\"i:\", i)\n\u003c/textarea\u003e\u003cdiv id=\"frame-6\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-7\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIncluding eigenvector functions:\u003c/p\u003e\u003ctextarea id=\"editor-8\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\na := [[2., 1.], [1., 2.]]\n\nv := matrix.EigSym(a)\n##\n\nfmt.Println(\"a:\", a)\nfmt.Println(\"v:\", v)\n\u003c/textarea\u003e\u003cdiv id=\"frame-9\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cstretch id=\"content-buttons-go-131\" style=\"display:flex;flex-direction:row;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;font-weight:thin;text-align:start\"\u003e\u003c/stretch\u003e\u003ca id=\"content-buttons-go-132\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"tensor-math\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"M686-450H160v-60h526L438-758l42-42 320 320-320 320-42-42 248-248Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003eNext\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Metric","URL":"metric","Title":"Metric","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Stats"],"Specials":{},"Description":"\u003cstrong\u003eMetric\u003c/strong\u003e computes distance metrics for comparing \u003ca href=\"tensor\" target=\"_blank\"\u003etensors\u003c/a\u003e. The different metrics supported are: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/stats/metric#Metrics\" target=\"_blank\"\u003estats/metric.Metrics\u003c/a\u003e.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eMetric\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-14\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eMetric\u003c/strong\u003e computes distance metrics for comparing \u003ca href=\"tensor\" target=\"_blank\"\u003etensors\u003c/a\u003e. The different metrics supported are: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/stats/metric#Metrics\" target=\"_blank\"\u003estats/metric.Metrics\u003c/a\u003e.\u003c/p\u003e\u003ctextarea id=\"editor-1\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := rand(12)\ny := rand(12)\n\nl2 := metric.L2Norm(x, y)\nr := metric.Correlation(x, y)\n##\n\nfmt.Println(\"x:\", x)\nfmt.Println(\"y:\", y)\nfmt.Println(\"l2:\", l2)\nfmt.Println(\"r:\", r)\n\u003c/textarea\u003e\u003cdiv id=\"frame-2\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAs with statistics, n-dimensional data is treated in a row-based manner, computing a metric value over the data across rows:\u003c/p\u003e\u003ctextarea id=\"editor-4\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := rand(12).reshape(3,4)\ny := rand(12).reshape(3,4)\n\nl2 := metric.L2Norm(x, y)\nr := metric.Correlation(x, y)\n##\n\nfmt.Println(\"x:\", x)\nfmt.Println(\"y:\", y)\nfmt.Println(\"l2:\", l2)\nfmt.Println(\"r:\", r)\n\u003c/textarea\u003e\u003cdiv id=\"frame-5\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-6\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo get a single value for each row representing the metric computed on the elements within that row, you need to iterate and slice:\u003c/p\u003e\u003ctextarea id=\"editor-7\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := rand(12).reshape(3,4)\ny := rand(12).reshape(3,4)\nl2 := zeros(3)\n## \n\nfor i := range 3 {\n\t##\n\tl2[i] = metric.L2Norm(x[i], y[i])\n\t##\n}\n\nfmt.Println(\"x:\", x)\nfmt.Println(\"y:\", y)\nfmt.Println(\"l2:\", l2)\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-8\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ca id=\"content-buttons-go-123\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"histogram\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"m274-450 248 248-42 42-320-320 320-320 42 42-248 248h526v60H274Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003ePrevious\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Plot editor","URL":"plot-editor","Title":"Plot editor","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Plot"],"Specials":{},"Description":"A \u003cstrong\u003eplot editor\u003c/strong\u003e allows you to create data plots that users can customize interactively.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003ePlot editor\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-15\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eA \u003cstrong\u003eplot editor\u003c/strong\u003e allows you to create data plots that users can customize interactively.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eHere is a simple plot editor:\u003c/p\u003e\u003ctextarea id=\"editor-2\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003edt := table.New(\"Data\")\nvalues := tensor.NewFloat32FromValues(1, 2.5, 7)\nplot.SetStyler(values, func(s *plot.Style) {\n\ts.On = true\n})\nerrors.Log(dt.AddColumn(\"Values\", values.AsValues()))\nmoreValues := tensor.NewFloat32FromValues(5, 3, 2)\nerrors.Log(dt.AddColumn(\"More values\", moreValues.AsValues()))\nplotcore.NewEditor(b).SetTable(dt)\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-3\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Plot","URL":"plot","Title":"Plot","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":null,"Specials":{},"Description":"You can graphically \u003cstrong\u003ePlot\u003c/strong\u003e data using the \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/plots\" target=\"_blank\"\u003eplots\u003c/a\u003e package. See \u003ca href=\"plot-editor\" target=\"_blank\"\u003eplot editor\u003c/a\u003e for interactive customization of plots.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003ePlot\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-16\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can graphically \u003cstrong\u003ePlot\u003c/strong\u003e data using the \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/plots\" target=\"_blank\"\u003eplots\u003c/a\u003e package. See \u003ca href=\"plot-editor\" target=\"_blank\"\u003eplot editor\u003c/a\u003e for interactive customization of plots.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can plot a vector:\u003c/p\u003e\u003ctextarea id=\"editor-2\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003eplt := lab.NewPlot(b)\nplots.NewLine(plt, #rand(10)#)\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-3\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can plot multiple vectors:\u003c/p\u003e\u003ctextarea id=\"editor-5\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003eplt := lab.NewPlot(b)\nplots.NewLine(plt, #rand(10)#)\nplots.NewLine(plt, #-rand(10)#)\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-6\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003ch2 id=\"styles\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eStyles\u003c/h2\u003e\u003cp id=\"text-8\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can style a plot line:\u003c/p\u003e\u003ctextarea id=\"editor-9\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003eplt := lab.NewPlot(b)\n# x := rand(10)\nplot.Styler(x, func(s *plot.Style) {\n\ts.Line.Color = colors.Scheme.Success.Base\n})\nplots.NewLine(plt, x)\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-10\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003ch3 id=\"tensor-metadata\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eTensor metadata\u003c/h3\u003e\u003cp id=\"text-12\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eStyler functions can be attached directly to a \u003ccode\u003etensor.Tensor\u003c/code\u003e via its metadata, and the \u003ccode\u003ePlotter\u003c/code\u003e elements will automatically grab these functions from any data source that has such metadata set. This allows the data generator to directly set default styling parameters, which can always be overridden later by adding more styler functions. Tying the plot styling directly to the source data allows all of the relevant logic to be put in one place, instead of spreading this logic across different places in the code.\u003c/p\u003e\u003cp id=\"text-13\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eHere is an example of how this works:\u003c/p\u003e\u003ctextarea id=\"editor-14\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003etx, ty := tensor.NewFloat64(21), tensor.NewFloat64(21)\nfor i := range 21 {\n\ttx.SetFloat1D(float64(i*5), i)\n\tty.SetFloat1D(50.0+40*math.Sin((float64(i)/8)*math.Pi), i)\n}\n// attach stylers to the Y axis data: that is where plotter looks for it\nplot.SetStyler(ty, func(s *plot.Style) {\n\ts.Plot.Title = \"Test Line\"\n\ts.Plot.XAxis.Label = \"X Axis\"\n\ts.Plot.YAxisLabel = \"Y Axis\"\n\ts.Plot.Scale = 2\n\ts.Plot.XAxis.Range.SetMax(105)\n\ts.Plot.SetLinesOn(plot.On).SetPointsOn(plot.On)\n\ts.Line.Color = colors.Uniform(colors.Red)\n\ts.Point.Color = colors.Uniform(colors.Blue)\n\ts.Range.SetMin(0).SetMax(100)\n})\n\n// somewhere else in the code:\n\nplt := lab.NewPlot(b)\n// NewLine automatically gets stylers from ty tensor metadata\nplots.NewLine(plt, plot.Data{plot.X: tx, plot.Y: ty})\n\u003c/textarea\u003e\u003cdiv id=\"frame-15\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003ch2 id=\"plot-types\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003ePlot Types\u003c/h2\u003e\u003cp id=\"text-17\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe following are the builtin standard plot types, in the \u003ccode\u003eplots\u003c/code\u003e package:\u003c/p\u003e\u003ch2 id=\"1d-and-2d-xy-data\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003e1D and 2D XY Data\u003c/h2\u003e\u003ch3 id=\"xy\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eXY\u003c/h3\u003e\u003cp id=\"text-20\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eXY\u003c/code\u003e is the workhorse standard Plotter, taking at least \u003ccode\u003eX\u003c/code\u003e and \u003ccode\u003eY\u003c/code\u003e inputs, and plotting lines and / or points at each X, Y point.\u003c/p\u003e\u003cp id=\"text-21\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eOptionally \u003ccode\u003eSize\u003c/code\u003e and / or \u003ccode\u003eColor\u003c/code\u003e inputs can be provided, which apply to the points. Thus, by using a \u003ccode\u003ePoint.Shape\u003c/code\u003e of \u003ccode\u003eRing\u003c/code\u003e or \u003ccode\u003eCircle\u003c/code\u003e, you can create a bubble plot by providing Size and Color data.\u003c/p\u003e\u003ch3 id=\"bar\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eBar\u003c/h3\u003e\u003cp id=\"text-23\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eBar\u003c/code\u003e takes \u003ccode\u003eY\u003c/code\u003e inputs, and draws bars of corresponding height.\u003c/p\u003e\u003cp id=\"text-24\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAn optional \u003ccode\u003eHigh\u003c/code\u003e input can be provided to also plot error bars above each bar.\u003c/p\u003e\u003cp id=\"text-25\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo create a plot with multiple error bars, multiple Bar Plotters are created, with \u003ccode\u003eStyle.Width\u003c/code\u003e parameters that have a shared \u003ccode\u003eStride = 1 / number of bars\u003c/code\u003e and \u003ccode\u003eOffset\u003c/code\u003e that increments for each bar added. The \u003ccode\u003eplots.NewBars\u003c/code\u003e function handles this directly.\u003c/p\u003e\u003ch3 id=\"errorbar\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eErrorBar\u003c/h3\u003e\u003cp id=\"text-27\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eXErrorBar\u003c/code\u003e and \u003ccode\u003eYErrorBar\u003c/code\u003e take \u003ccode\u003eX\u003c/code\u003e, \u003ccode\u003eY\u003c/code\u003e, \u003ccode\u003eLow\u003c/code\u003e, and \u003ccode\u003eHigh\u003c/code\u003e inputs, and draws an \u003ccode\u003eI\u003c/code\u003e shaped error bar at the X, Y coordinate with the error “handles” around it.\u003c/p\u003e\u003ch3 id=\"labels\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eLabels\u003c/h3\u003e\u003cp id=\"text-29\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eLabels\u003c/code\u003e takes \u003ccode\u003eX\u003c/code\u003e, \u003ccode\u003eY\u003c/code\u003e and \u003ccode\u003eLabels\u003c/code\u003e string inputs and plots labels at the given coordinates.\u003c/p\u003e\u003ch3 id=\"box\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eBox\u003c/h3\u003e\u003cp id=\"text-31\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eBox\u003c/code\u003e takes \u003ccode\u003eX\u003c/code\u003e, \u003ccode\u003eY\u003c/code\u003e (median line), \u003ccode\u003eU\u003c/code\u003e, \u003ccode\u003eV\u003c/code\u003e (box first and 3rd quartile values), and \u003ccode\u003eLow\u003c/code\u003e, \u003ccode\u003eHigh\u003c/code\u003e (Min, Max) inputs, and renders a box plot with error bars.\u003c/p\u003e\u003ch3 id=\"xfill-yfill\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eXFill, YFill\u003c/h3\u003e\u003cp id=\"text-33\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003eXFill\u003c/code\u003e and \u003ccode\u003eYFill\u003c/code\u003e are used to draw filled regions between pairs of X or Y points, using the \u003ccode\u003eX\u003c/code\u003e, \u003ccode\u003eY\u003c/code\u003e, and \u003ccode\u003eLow\u003c/code\u003e, \u003ccode\u003eHigh\u003c/code\u003e values to specify the center point (X, Y) and the region below / left and above / right to fill around that central point.\u003c/p\u003e\u003cp id=\"text-34\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eXFill along with an XY line can be used to draw the equivalent of the \u003ca href=\"https://matplotlib.org/stable/plot_types/basic/fill_between.html#sphx-glr-plot-types-basic-fill-between-py\" target=\"_blank\"\u003ematplotlib fill_between\u003c/a\u003e plot.\u003c/p\u003e\u003cp id=\"text-35\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYFill can be used to draw the equivalent of the \u003ca href=\"https://matplotlib.org/stable/plot_types/stats/violin.html#sphx-glr-plot-types-stats-violin-py\" target=\"_blank\"\u003ematplotlib violin plot\u003c/a\u003e.\u003c/p\u003e\u003ch3 id=\"pie\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003ePie\u003c/h3\u003e\u003cp id=\"text-37\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003ePie\u003c/code\u003e takes a list of \u003ccode\u003eY\u003c/code\u003e values that are plotted as the size of segments of a circular pie plot. Y values are automatically normalized for plotting.\u003c/p\u003e\u003cp id=\"text-38\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO: implement, details on mapping,\u003c/p\u003e\u003ch2 id=\"2d-grid-based\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003e2D Grid-based\u003c/h2\u003e\u003ch3 id=\"colorgrid\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eColorGrid\u003c/h3\u003e\u003cp id=\"text-41\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eInput = Values and X, Y size\u003c/p\u003e\u003ch3 id=\"contour\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eContour\u003c/h3\u003e\u003cp id=\"text-43\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e??\u003c/p\u003e\u003ch3 id=\"vector\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eVector\u003c/h3\u003e\u003cp id=\"text-45\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eX,Y,U,V\u003c/p\u003e\u003cp id=\"text-46\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eQuiver?\u003c/p\u003e\u003ch2 id=\"3d\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003e3D\u003c/h2\u003e\u003cp id=\"text-48\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO: use math32 3D projection math and you can just take each 3d point and reduce to 2D. For stuff you want to actually be able to use in SVG, it needs to ultimately be 2D, so it makes sense to support basic versions here, including XYZ (points, lines), Bar3D, wireframe.\u003c/p\u003e\u003cp id=\"text-49\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eCould also have a separate plot3d package based on \u003ccode\u003exyz\u003c/code\u003e that is true 3D for interactive 3D plots of surfaces or things that don’t make sense in this more limited 2D world.\u003c/p\u003e\u003ch1 id=\"statistical-plots\" style=\"margin:0.25em;font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eStatistical plots\u003c/h1\u003e\u003cp id=\"text-51\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ccode\u003estatplot\u003c/code\u003e package provides functions taking \u003ccode\u003etensor\u003c/code\u003e data that produce statistical plots of the data, including Quartiles (Box with Median, Quartile, Min, Max), Histogram (Bar), Violin (YFill), Range (XFill), Cluster…\u003c/p\u003e\u003cp id=\"text-52\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO: add a Data scatter that plots points to overlay on top of Violin or Box.\u003c/p\u003e\u003ch2 id=\"legendgroups\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eLegendGroups\u003c/h2\u003e\u003cul id=\"frame-54\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• implements current legend grouping logic – ends up being a multi-table output – not sure how to interface.\u003c/li\u003e\u003c/ul\u003e\u003ch2 id=\"histogram\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eHistogram\u003c/h2\u003e\u003ch2 id=\"quartiles\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eQuartiles\u003c/h2\u003e\u003ch2 id=\"violin\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eViolin\u003c/h2\u003e\u003ch2 id=\"range\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eRange\u003c/h2\u003e\u003ch2 id=\"cluster\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eCluster\u003c/h2\u003e\u003ch2 id=\"plot-pages\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003ePlot pages\u003c/h2\u003e\u003cul id=\"frame-61\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"plot-editor\" target=\"_blank\"\u003ePlot editor\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Shell","URL":"shell","Title":"Shell","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Goal"],"Specials":{},"Description":"In general, the \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e shell mode behavior mimics that of \u003ccode\u003ebash\u003c/code\u003e.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eShell\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-17\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn general, the \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e shell mode behavior mimics that of \u003ccode\u003ebash\u003c/code\u003e.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe following documentation describes specific use-cases.\u003c/p\u003e\u003ch2 id=\"environment-variables\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eEnvironment variables\u003c/h2\u003e\u003cul id=\"frame-3\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eset \u003cvar\u003e \u003cvalue\u003e\u003c/code\u003e (space delimited as in all shell mode, no equals)\u003c/li\u003e\u003c/ul\u003e\u003ch2 id=\"output-redirction\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eOutput redirction\u003c/h2\u003e\u003cul id=\"frame-5\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Standard output redirect: \u003ccode\u003e\u003e\u003c/code\u003e and \u003ccode\u003e\u003e\u0026\u003c/code\u003e (and \u003ccode\u003e|\u003c/code\u003e, \u003ccode\u003e|\u0026\u003c/code\u003e if needed)\u003c/li\u003e\u003c/ul\u003e\u003ch2 id=\"control-flow\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eControl flow\u003c/h2\u003e\u003cul id=\"frame-7\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Any error stops the script execution, except for statements wrapped in \u003ccode\u003e[ ]\u003c/code\u003e, indicating an “optional” statement, e.g.:\u003c/li\u003e\u003c/ul\u003e\u003ctextarea id=\"editor-8\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ecd some; [mkdir sub]; cd sub\n\n\u003c/textarea\u003e\u003cul id=\"frame-9\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003e\u0026\u003c/code\u003e at the end of a statement runs in the background (as in bash) – otherwise it waits until it completes before it continues.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003ejobs\u003c/code\u003e, \u003ccode\u003efg\u003c/code\u003e, \u003ccode\u003ebg\u003c/code\u003e, and \u003ccode\u003ekill\u003c/code\u003e builtin commands function as in usual bash.\u003c/p\u003e\u003c/ul\u003e\u003ch2 id=\"shell-functions-aliases\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eShell functions (aliases)\u003c/h2\u003e\u003cp id=\"text-11\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eUse the \u003ccode\u003ecommand\u003c/code\u003e keyword to define new functions for Shell mode execution, which can then be used like any other command, for example:\u003c/p\u003e\u003ctextarea id=\"editor-12\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ecommand list {\n\tls -la args...\n}\n\n\u003c/textarea\u003e\u003ctextarea id=\"editor-13\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ecd data\nlist *.tsv\n\n\u003c/textarea\u003e\u003cp id=\"text-14\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ccode\u003ecommand\u003c/code\u003e is transpiled into a Go function that takes \u003ccode\u003eargs ...string\u003c/code\u003e. In the command function body, you can use the \u003ccode\u003eargs...\u003c/code\u003e expression to pass all of the args, or \u003ccode\u003eargs[1]\u003c/code\u003e etc to refer to specific positional indexes, as usual.\u003c/p\u003e\u003cp id=\"text-15\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe command function name is registered so that the standard shell execution code can run the function, passing the args. You can also call it directly from Go code using the standard parentheses expression.\u003c/p\u003e\u003ch2 id=\"script-files-and-makefile-like-functionality\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eScript Files and Makefile-like functionality\u003c/h2\u003e\u003cp id=\"text-17\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAs with most scripting languages, a file of goal code can be made directly executable by appending a “shebang” expression at the start of the file:\u003c/p\u003e\u003ctextarea id=\"editor-18\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e#!/usr/bin/env goal\n\n\u003c/textarea\u003e\u003cp id=\"text-19\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWhen executed this way, any additional args are available via an \u003ccode\u003eargs []any\u003c/code\u003e variable, which can be passed to a command as follows:\u003c/p\u003e\u003ctextarea id=\"editor-20\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003einstall {args...}\n\n\u003c/textarea\u003e\u003cp id=\"text-21\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eor by referring to specific arg indexes etc.\u003c/p\u003e\u003cp id=\"text-22\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo make a script behave like a standard Makefile, you can define different \u003ccode\u003ecommand\u003c/code\u003es for each of the make commands, and then add the following at the end of the file to use the args to run commands:\u003c/p\u003e\u003ctextarea id=\"editor-23\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003egoal.RunCommands(args)\n\n\u003c/textarea\u003e\u003cp id=\"text-24\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee \u003ca href=\"cmd/goal/testdata/make\" target=\"_blank\"\u003emake\u003c/a\u003e for an example, in \u003ccode\u003ecmd/goal/testdata/make\u003c/code\u003e, which can be run for example using:\u003c/p\u003e\u003ctextarea id=\"editor-25\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e./make build\n\n\u003c/textarea\u003e\u003cp id=\"text-26\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNote that there is nothing special about the name \u003ccode\u003emake\u003c/code\u003e here, so this can be done with any file.\u003c/p\u003e\u003cp id=\"text-27\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ccode\u003emake\u003c/code\u003e package defines a number of useful utility functions that accomplish the standard dependency and file timestamp checking functionality from the standard \u003ccode\u003emake\u003c/code\u003e command, as in the \u003ca href=\"https://magefile.org/dependencies/\" target=\"_blank\"\u003emagefile\u003c/a\u003e system. Note that the goal direct shell command syntax makes the resulting make files much closer to a standard bash-like Makefile, while still having all the benefits of Go control and expressions, compared to magefile.\u003c/p\u003e\u003cp id=\"text-28\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO: implement and document above.\u003c/p\u003e\u003ch2 id=\"ssh-connections-to-remote-hosts\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eSSH connections to remote hosts\u003c/h2\u003e\u003cp id=\"text-30\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAny number of active SSH connections can be maintained and used dynamically within a script, including simple ways of copying data among the different hosts (including the local host). The Go mode execution is always on the local host in one running process, and only the shell commands are executed remotely, enabling a unique ability to easily coordinate and distribute processing and data across various hosts.\u003c/p\u003e\u003cp id=\"text-31\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eEach host maintains its own working directory and environment variables, which can be configured and re-used by default whenever using a given host.\u003c/p\u003e\u003cul id=\"frame-32\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003egossh hostname.org [name]\u003c/code\u003e establishes a connection, using given optional name to refer to this connection. If the name is not provided, a sequential number will be used, starting with 1, with 0 referring always to the local host.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003e@name\u003c/code\u003e then refers to the given host in all subsequent commands, with \u003ccode\u003e@0\u003c/code\u003e referring to the local host where the goal script is running.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• You can use a variable name for the server, like this (the explicit \u003ccode\u003e$ $\u003c/code\u003e shell mode is required because a line starting with \u003ccode\u003e{\u003c/code\u003e is not recognized as shell code):\u003c/p\u003e\u003c/ul\u003e\u003ctextarea id=\"editor-33\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003eserver := \"@myserver\"\n${server} ls$\n\n\u003c/textarea\u003e\u003cdiv id=\"frame-34\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003ch3 id=\"explicit-per-command-specification-of-host\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eExplicit per-command specification of host\u003c/h3\u003e\u003ctextarea id=\"editor-36\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e@name cd subdir; ls\n\n\u003c/textarea\u003e\u003ch3 id=\"default-host\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eDefault host\u003c/h3\u003e\u003ctextarea id=\"editor-38\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e@name // or:\ngossh @name\n\n\u003c/textarea\u003e\u003cp id=\"text-39\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003euses the given host for all subsequent commands (unless explicitly specified), until the default is changed. Use \u003ccode\u003egossh @0\u003c/code\u003e to return to localhost.\u003c/p\u003e\u003ch3 id=\"redirect-input-output-among-hosts\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eRedirect input / output among hosts\u003c/h3\u003e\u003cp id=\"text-41\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe output of a remote host command can be sent to a file on the local host:\u003c/p\u003e\u003ctextarea id=\"editor-42\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e@name cat hostfile.tsv \u003e @0:localfile.tsv\n\n\u003c/textarea\u003e\u003cp id=\"text-43\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNote the use of the \u003ccode\u003e:\u003c/code\u003e colon delimiter after the host name here. TODO: You cannot send output to a remote host file (e.g., \u003ccode\u003e\u003e @host:remotefile.tsv\u003c/code\u003e) – maybe with sftp?\u003c/p\u003e\u003cp id=\"text-44\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe output of any command can also be piped to a remote host as its standard input:\u003c/p\u003e\u003ctextarea id=\"editor-45\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003els *.tsv | @host cat \u003e files.txt\n\n\u003c/textarea\u003e\u003ch3 id=\"scp-to-copy-files-easily\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003escp to copy files easily\u003c/h3\u003e\u003cp id=\"text-47\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe builtin \u003ccode\u003escp\u003c/code\u003e function allows easy copying of files across hosts, using the persistent connections established with \u003ccode\u003egossh\u003c/code\u003e instead of creating new connections as in the standard scp command.\u003c/p\u003e\u003cp id=\"text-48\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003escp\u003c/code\u003e is \u003cem\u003ealways\u003c/em\u003e run from the local host, with the remote host filename specified as \u003ccode\u003e@name:remotefile\u003c/code\u003e\u003c/p\u003e\u003ctextarea id=\"editor-49\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003escp @name:hostfile.tsv localfile.tsv\n\n\u003c/textarea\u003e\u003cp id=\"text-50\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eImportantly, file wildcard globbing works as expected:\u003c/p\u003e\u003ctextarea id=\"editor-51\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003escp @name:*.tsv @0:data/\n\n\u003c/textarea\u003e\u003cp id=\"text-52\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eand entire directories can be copied, as in \u003ccode\u003ecp -a\u003c/code\u003e or \u003ccode\u003ecp -r\u003c/code\u003e (this behavior is automatic and does not require a flag).\u003c/p\u003e\u003ch3 id=\"close-connections\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eClose connections\u003c/h3\u003e\u003ctextarea id=\"editor-54\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003egossh close\n\n\u003c/textarea\u003e\u003cp id=\"text-55\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWill close all active connections and return the default host to @0. All active connections are also automatically closed when the shell terminates.\u003c/p\u003e\u003ch2 id=\"other-utilties\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eOther Utilties\u003c/h2\u003e\u003cp id=\"text-57\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e** TODO: need a replacement for findnm – very powerful but garbage..\u003c/p\u003e\u003ch2 id=\"rules-for-go-vs-shell-determination\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eRules for Go vs. Shell determination\u003c/h2\u003e\u003cp id=\"text-59\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThese are the rules used to determine whether a line is Go vs. Shell (word = IDENT token):\u003c/p\u003e\u003cul id=\"frame-60\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003e$\u003c/code\u003e at the start: Shell.\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Within Shell, \u003ccode\u003e{}\u003c/code\u003e: Go\u003c/li\u003e\u003cli id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Within Go, \u003ccode\u003e$ $\u003c/code\u003e: Shell\u003c/li\u003e\u003cli id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Line starts with \u003ccode\u003ego\u003c/code\u003e keyword: if no \u003ccode\u003e( )\u003c/code\u003e then Shell, else Go\u003c/li\u003e\u003cli id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Line is one word: Shell\u003c/li\u003e\u003cli id=\"text-5\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Line starts with \u003ccode\u003epath\u003c/code\u003e expression (e.g., \u003ccode\u003e./myexec\u003c/code\u003e) : Shell\u003c/li\u003e\u003cli id=\"text-6\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Line starts with \u003ccode\u003e\"string\"\u003c/code\u003e: Shell\u003c/li\u003e\u003cli id=\"text-7\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Line starts with \u003ccode\u003eword word\u003c/code\u003e: Shell\u003c/li\u003e\u003cli id=\"text-8\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Line starts with \u003ccode\u003eword {\u003c/code\u003e: Shell\u003c/li\u003e\u003cli id=\"text-9\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Otherwise: Go\u003c/li\u003e\u003c/ul\u003e\u003cp id=\"text-61\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTODO: update above\u003c/p\u003e\u003ch2 id=\"multiple-statements-per-line\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eMultiple statements per line\u003c/h2\u003e\u003cul id=\"frame-63\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• Multiple statements can be combined on one line, separated by \u003ccode\u003e;\u003c/code\u003e as in regular Go and shell languages. Critically, the language determination for the first statement determines the language for the remaining statements; you cannot intermix the two on one line, when using \u003ccode\u003e;\u003c/code\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ca id=\"content-buttons-go-123\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"math\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"m274-450 248 248-42 42-320-320 320-320 42 42-248 248h526v60H274Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003ePrevious\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Stats","URL":"stats","Title":"Stats","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":null,"Specials":{},"Description":"In addition to the basic statistics functions described below, there are several packages for computing \u003cstrong\u003estatistics\u003c/strong\u003e on \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e and \u003ca href=\"table\" target=\"_blank\"\u003etable\u003c/a\u003e data:","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eStats\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-18\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn addition to the basic statistics functions described below, there are several packages for computing \u003cstrong\u003estatistics\u003c/strong\u003e on \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e and \u003ca href=\"table\" target=\"_blank\"\u003etable\u003c/a\u003e data:\u003c/p\u003e\u003cul id=\"frame-1\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"metric\" target=\"_blank\"\u003emetric\u003c/a\u003e computes similarity / distance metrics for comparing two tensors, and associated distance / similarity matrix functions.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"cluster\" target=\"_blank\"\u003ecluster\u003c/a\u003e implements agglomerative clustering of items based on metric distance / similarity matrix data.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• convolve convolves data (e.g., for smoothing).\u003c/p\u003e\u003cp id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"glm\" target=\"_blank\"\u003eglm\u003c/a\u003e fits a general linear model for one or more dependent variables as a function of one or more independent variables. This encompasses all forms of regression.\u003c/p\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"histogram\" target=\"_blank\"\u003ehistogram\u003c/a\u003e bins data into groups and reports the frequency of elements in the bins.\u003c/p\u003e\u003c/ul\u003e\u003ch2 id=\"stats\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eStats\u003c/h2\u003e\u003cp id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe standard statistics functions supported are enumerated in \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/stats/stats#Stats\" target=\"_blank\"\u003estats/stats.Stats\u003c/a\u003e, and include things like \u003ccode\u003eMean\u003c/code\u003e, \u003ccode\u003eVar\u003c/code\u003eiance, etc.\u003c/p\u003e\u003ctextarea id=\"editor-4\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e##\nx := linspace(0., 12., 12., false)\nd := x.reshape(3,2,2) // n-dimensional data is handled \n\nmean := stats.Mean(x)\nmeand := stats.Mean(d)\n##\n\nfmt.Println(\"x:\", x)\nfmt.Println(\"mean:\", mean)\nfmt.Println(\"d:\", d)\nfmt.Println(\"mean d:\", meand)\n\u003c/textarea\u003e\u003cdiv id=\"frame-5\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-6\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can see that the stats on n-dimensional data are automatically computed across the \u003cem\u003erow\u003c/em\u003e (outer-most) dimension. You can reshape your data and the results as needed to get the statistics you want.\u003c/p\u003e\u003ch2 id=\"grouping-and-stats\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eGrouping and stats\u003c/h2\u003e\u003cp id=\"text-8\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ccode\u003estats\u003c/code\u003e package has functions that group values in a \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e or a \u003ca href=\"table\" target=\"_blank\"\u003etable\u003c/a\u003e so that statistics can be computed across the groups. The grouping uses \u003ca href=\"tensorfs\" target=\"_blank\"\u003etensorfs\u003c/a\u003e to organize the groups and statistics, as in the following example:\u003c/p\u003e\u003ctextarea id=\"editor-9\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003edt := table.New().SetNumRows(4)\ndt.AddStringColumn(\"Name\")\ndt.AddFloat32Column(\"Value\")\nfor i := range 4 {\n\tgp := \"A\"\n\tif i \u003e= 2 {\n\t\tgp = \"B\"\n\t}\n\tdt.Column(\"Name\").SetStringRow(gp, i, 0)\n\tdt.Column(\"Value\").SetFloatRow(float64(i), i, 0)\n}\ndir, _ := tensorfs.NewDir(\"Group\")\nstats.TableGroups(dir, dt, \"Name\")\nstats.TableGroupStats(dir, stats.StatMean, dt, \"Value\")\ngdt := stats.GroupStatsAsTableNoStatName(dir)\n\nfmt.Println(\"dt:\", dt)\nfmt.Println(\"tensorfs listing:\")\nfmt.Println(dir.ListLong(true, 2))\n\nfmt.Println(\"gdt:\", gdt)\n\u003c/textarea\u003e\u003cdiv id=\"frame-10\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch2 id=\"stats-pages\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eStats pages\u003c/h2\u003e\u003cul id=\"frame-12\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"cluster\" target=\"_blank\"\u003eCluster\u003c/a\u003e\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"glm\" target=\"_blank\"\u003eGlm\u003c/a\u003e\u003c/li\u003e\u003cli id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"histogram\" target=\"_blank\"\u003eHistogram\u003c/a\u003e\u003c/li\u003e\u003cli id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"metric\" target=\"_blank\"\u003eMetric\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Table","URL":"table","Title":"Table","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":null,"Specials":{},"Description":"\u003cstrong\u003etable\u003c/strong\u003e provides a DataTable / DataFrame structure similar to \u003ca href=\"https://pandas.pydata.org/\" target=\"_blank\"\u003epandas\u003c/a\u003e and \u003ca href=\"http://xarray.pydata.org/en/stable/\" target=\"_blank\"\u003exarray\u003c/a\u003e in Python, and \u003ca href=\"https://github.com/apache/arrow/tree/master/go/arrow/array/table.go\" target=\"_blank\"\u003eApache Arrow Table\u003c/a\u003e, using \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e n-dimensional columns aligned by common outermost row dimension.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eTable\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-19\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003etable\u003c/strong\u003e provides a DataTable / DataFrame structure similar to \u003ca href=\"https://pandas.pydata.org/\" target=\"_blank\"\u003epandas\u003c/a\u003e and \u003ca href=\"http://xarray.pydata.org/en/stable/\" target=\"_blank\"\u003exarray\u003c/a\u003e in Python, and \u003ca href=\"https://github.com/apache/arrow/tree/master/go/arrow/array/table.go\" target=\"_blank\"\u003eApache Arrow Table\u003c/a\u003e, using \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e n-dimensional columns aligned by common outermost row dimension.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eData in the table is accessed by first getting the \u003ccode\u003eColumn\u003c/code\u003e tensor (typically by name), and then using the \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#RowMajor\" target=\"_blank\"\u003etensor.RowMajor\u003c/a\u003e methods to access data within that tensor in a row-wise manner:\u003c/p\u003e\u003ctextarea id=\"editor-2\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003edt := table.New()\ndt.AddStringColumn(\"Name\")\ndt.AddFloat64Column(\"Data\", 2, 2)\ndt.SetNumRows(3)\n\ndt.Column(\"Name\").SetStringRow(\"item0\", 0, 0)\ndt.Column(\"Name\").SetStringRow(\"item1\", 1, 0)\ndt.Column(\"Name\").SetStringRow(\"item2\", 2, 0)\n\ndt.Column(\"Data\").SetFloatRow(55, 0, 0)\ndt.Column(\"Data\").SetFloatRow(102, 1, 1) // note: last arg is 1D \"cell\" index\ndt.Column(\"Data\").SetFloatRow(37, 2, 3)\n\nval := dt.Column(\"Data\").FloatRow(2, 3)\n\nfmt.Println(dt)\nfmt.Printf(\"val: %v\\n\", val)\n\u003c/textarea\u003e\u003cdiv id=\"frame-3\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch2 id=\"sorting-and-filtering\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eSorting and filtering\u003c/h2\u003e\u003cp id=\"text-5\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ccode\u003eColumn\u003c/code\u003e method creates a \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Rows\" target=\"_blank\"\u003etensor.Rows\u003c/a\u003e for the underlying column values, with a list of indexes used for the row-level access, which enables efficient sorting and filtering by row, as only these indexes need to be updated, not the underlying data values. The indexes are maintained on the table, which provides an indexed view onto the underlying data values that are stored in a separate \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/table#Columns\" target=\"_blank\"\u003etable.Columns\u003c/a\u003e structure. Thus, there can be multiple different such table views onto the same underlying columns data.\u003c/p\u003e\u003ctextarea id=\"editor-6\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003edt := table.New()\ndt.AddStringColumn(\"Name\")\ndt.AddFloat64Column(\"Data\")\ndt.SetNumRows(3)\n\nfruits := []string{\"peach\", \"apple\", \"orange\"}\n\nfor i := range 3 {\n\tdt.Column(\"Name\").SetStringRow(fruits[i], i, 0)\n\tdt.Column(\"Data\").SetFloatRow(float64(i+1), i, 0)\n}\n\ndt.Sequential()\ndt.SortColumn(\"Data\", tensor.Descending)\nfmt.Println(dt)\n\ndt.Sequential()\ndt.Filter(func(dt *table.Table, row int) bool {\n\treturn dt.Column(\"Data\").FloatRow(row, 0) \u003e 1\n})\nfmt.Println(dt)\n\u003c/textarea\u003e\u003cdiv id=\"frame-7\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch2 id=\"csv-tsv-file-format\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eCSV / TSV file format\u003c/h2\u003e\u003cp id=\"text-9\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTables can be saved and loaded from CSV (comma separated values) or TSV (tab separated values) files. See the next section for special formatting of header strings in these files to record the type and tensor cell shapes.\u003c/p\u003e\u003ch3 id=\"type-and-tensor-headers\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eType and Tensor Headers\u003c/h3\u003e\u003cp id=\"text-11\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo capture the type and shape of the columns, we support the following header formatting. We weren’t able to find any other widely supported standard (please let us know if there is one that we’ve missed!)\u003c/p\u003e\u003cp id=\"text-12\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eHere is the mapping of special header prefix characters to standard types:\u003c/p\u003e\u003ctextarea id=\"editor-13\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e'$': etensor.STRING,\n'%': etensor.FLOAT32,\n'#': etensor.FLOAT64,\n'|': etensor.INT64,\n'@': etensor.UINT8,\n'^': etensor.BOOL,\n\n\u003c/textarea\u003e\u003cp id=\"text-14\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eColumns that have tensor cell shapes (not just scalars) are marked as such with the \u003cem\u003efirst\u003c/em\u003e such column having a \u003ccode\u003e\u003cndim:dim,dim..\u003e\u003c/code\u003e suffix indicating the shape of the \u003cem\u003ecells\u003c/em\u003e in this column, e.g., \u003ccode\u003e\u003c2:5,4\u003e\u003c/code\u003e indicates a 2D cell Y=5,X=4. Each individual column is then indexed as \u003ccode\u003e[ndims:x,y..]\u003c/code\u003e e.g., the first would be \u003ccode\u003e[2:0,0]\u003c/code\u003e, then \u003ccode\u003e[2:0,1]\u003c/code\u003e etc.\u003c/p\u003e\u003ch3 id=\"example\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eExample\u003c/h3\u003e\u003cp id=\"text-16\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eHere’s a TSV file for a scalar String column (\u003ccode\u003eName\u003c/code\u003e), a 2D 1x4 tensor float32 column (\u003ccode\u003eInput\u003c/code\u003e), and a 2D 1x2 float32 \u003ccode\u003eOutput\u003c/code\u003e column.\u003c/p\u003e\u003ctextarea id=\"editor-17\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003e_H:\t$Name\t%Input[2:0,0]\u003c2:1,4\u003e\t%Input[2:0,1]\t%Input[2:0,2]\t%Input[2:0,3]\t%Output[2:0,0]\u003c2:1,2\u003e\t%Output[2:0,1]\n_D:\tEvent_0\t1\t0\t0\t0\t1\t0\n_D:\tEvent_1\t0\t1\t0\t0\t1\t0\n_D:\tEvent_2\t0\t0\t1\t0\t0\t1\n_D:\tEvent_3\t0\t0\t0\t1\t0\t1\n\n\u003c/textarea\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Tabs","URL":"tabs","Title":"Tabs","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Lab"],"Specials":{},"Description":"\u003cstrong\u003eTabs\u003c/strong\u003e makes it easy to add various graphical views of data elements in a tabbed \u003ca href=\"browser\" target=\"_blank\"\u003eBrowser\u003c/a\u003e view. Go API docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/lab#Tabs\" target=\"_blank\"\u003elab.Tabs\u003c/a\u003e.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eTabs\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-20\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003eTabs\u003c/strong\u003e makes it easy to add various graphical views of data elements in a tabbed \u003ca href=\"browser\" target=\"_blank\"\u003eBrowser\u003c/a\u003e view. Go API docs: \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/lab#Tabs\" target=\"_blank\"\u003elab.Tabs\u003c/a\u003e.\u003c/p\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ca id=\"content-buttons-go-123\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"datatree\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"m274-450 248 248-42 42-320-320 320-320 42 42-248 248h526v60H274Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003ePrevious\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Tensor math","URL":"tensor-math","Title":"Tensor math","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":["Tensor"],"Specials":{},"Description":"The \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor/tmath\" target=\"_blank\"\u003etensor/tmath\u003c/a\u003e package implements most of the standard library \u003ca href=\"https://pkg.go.dev/math\" target=\"_blank\"\u003emath\u003c/a\u003e functions, including basic arithmetic operations, for \u003ca href=\"tensor\" target=\"_blank\"\u003etensors\u003c/a\u003e.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eTensor math\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-21\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor/tmath\" target=\"_blank\"\u003etensor/tmath\u003c/a\u003e package implements most of the standard library \u003ca href=\"https://pkg.go.dev/math\" target=\"_blank\"\u003emath\u003c/a\u003e functions, including basic arithmetic operations, for \u003ca href=\"tensor\" target=\"_blank\"\u003etensors\u003c/a\u003e.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFor example:\u003c/p\u003e\u003ctextarea id=\"editor-2\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFromValues(0., 1., 2., 3.)\nadd := tmath.Add(x, x)\nsub := tmath.Sub(x, x)\nmul := tmath.Mul(x, x)\ndiv := tmath.Div(x, x)\n\nfmt.Println(\"add:\", add)\nfmt.Println(\"sub:\", sub)\nfmt.Println(\"mul:\", mul)\nfmt.Println(\"div:\", div)\n\u003c/textarea\u003e\u003cdiv id=\"frame-3\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAs you can see, the operations are performed element-wise; see the \u003ca href=\"matrix\" target=\"_blank\"\u003ematrix\u003c/a\u003e package for 2D matrix multiplication and related operations.\u003c/p\u003e\u003cp id=\"text-5\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eMath functions can be performed:\u003c/p\u003e\u003ctextarea id=\"editor-6\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFromValues(0., 1., 2., 3.)\nsin := tmath.Sin(x)\natan := tmath.Atan2(x, tensor.NewFromValues(3.0))\npow := tmath.Pow(x, tensor.NewFromValues(2.0))\n\nfmt.Println(\"sin:\", sin)\nfmt.Println(\"atan:\", atan)\nfmt.Println(\"pow:\", pow)\n\u003c/textarea\u003e\u003cdiv id=\"frame-7\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-8\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eSee the info below on \u003ca href=\"tensor-math#Alignment of shapes\" target=\"_blank\"\u003eAlignment of shapes\u003c/a\u003e for the rules governing the way that different-shaped tensors are aligned for these computations.\u003c/p\u003e\u003cp id=\"text-9\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eParallel goroutines will be used for implementing these computations if the tensors are sufficiently large to make it generally beneficial to do so.\u003c/p\u003e\u003cp id=\"text-10\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThere are also \u003ccode\u003e*Out\u003c/code\u003e versions of each function, which take an additional output tensor to store the results into, instead of creating a new one. For computationally-intensive pipelines, it can be significantly more efficient to re-use pre-allocated outputs (which are automatically and efficiently resized to the proper capacity if not already).\u003c/p\u003e\u003ch2 id=\"alignment-of-shapes\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eAlignment of shapes\u003c/h2\u003e\u003cp id=\"text-12\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe NumPy concept of \u003ca href=\"https://numpy.org/doc/stable/user/basics.broadcasting.html\" target=\"_blank\"\u003ebroadcasting\u003c/a\u003e is critical for flexibly defining the semantics for how functions taking two n-dimensional Tensor arguments behave when they have different shapes. Ultimately, the computation operates by iterating over the length of the longest tensor, and the question is how to \u003cem\u003ealign\u003c/em\u003e the shapes so that a meaningful computation results from this.\u003c/p\u003e\u003cp id=\"text-13\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIf both tensors are 1D and the same length, then a simple matched iteration over both can take place. However, the broadcasting logic defines what happens when there is a systematic relationship between the two, enabling powerful (but sometimes difficult to understand) computations to be specified.\u003c/p\u003e\u003cp id=\"text-14\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe following examples demonstrate the logic:\u003c/p\u003e\u003cp id=\"text-15\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eInnermost dimensions that match in dimension are iterated over as you’d expect:\u003c/p\u003e\u003ctextarea id=\"editor-16\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003eImage (3d array): 256 x 256 x 3\nScale (1d array): 3\nResult (3d array): 256 x 256 x 3\n\n\u003c/textarea\u003e\u003cp id=\"text-17\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAnything with a dimension size of 1 (a “singleton”) will match against any other sized dimension:\u003c/p\u003e\u003ctextarea id=\"editor-18\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003eA (4d array): 8 x 1 x 6 x 1\nB (3d array): 7 x 1 x 5\nResult (4d array): 8 x 7 x 6 x 5\n\n\u003c/textarea\u003e\u003cp id=\"text-19\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn the innermost dimension here, the single value in A acts like a “scalar” in relationship to the 5 values in B along that same dimension, operating on each one in turn. Likewise for the singleton second-to-last dimension in B.\u003c/p\u003e\u003cp id=\"text-20\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAny non-1 mismatch represents an error:\u003c/p\u003e\u003ctextarea id=\"editor-21\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003eA (2d array): 2 x 1\nB (3d array): 8 x 4 x 3 # second from last dimensions mismatched\n\n\u003c/textarea\u003e\u003cp id=\"text-22\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ccode\u003eAlignShapes\u003c/code\u003e function performs this shape alignment logic, and the \u003ccode\u003eWrapIndex1D\u003c/code\u003e function is used to compute a 1D index into a given shape, based on the total output shape sizes, wrapping any singleton dimensions around as needed. These are used in the \u003ca href=\"tmath\" target=\"_blank\"\u003etmath\u003c/a\u003e package for example to implement the basic binary math operators.\u003c/p\u003e\u003c/main\u003e\u003c/div\u003e\u003cdiv id=\"content-buttons-go-116\" style=\"display:flex;flex-direction:row;justify-content:start;align-items:center;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ca id=\"content-buttons-go-123\" style=\"color:var(--secondary-on-container-color);background:var(--secondary-container-color);display:flex;flex-direction:row;justify-content:center;align-items:center;padding-top:10px;padding-right:24px;padding-bottom:10px;padding-left:16px;font-size:14px;font-weight:thin;text-align:center;border-radius:1e+09px\" href=\"matrix\"\u003e\u003csvg id=\"icon\" style=\"color:var(--secondary-on-container-color);stroke:var(--secondary-on-container-color);fill:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1.2857143em;min-height:1.2857143em;width:1.2857143em;height:1.2857143em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"\u003e\u003cpath d=\"m274-450 248 248-42 42-320-320 320-320 42 42-248 248h526v60H274Z\"/\u003e\u003c/svg\u003e\u003c/svg\u003e\u003cdiv id=\"space\" style=\"color:var(--secondary-on-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:1ch;min-height:1em;width:1ch;height:1em;font-size:14px;font-weight:thin;text-align:center\"\u003e\u003c/div\u003e\u003cp id=\"text\" style=\"color:var(--secondary-on-container-color);font-size:14px;font-weight:500;line-height:1.4285715;text-align:center\"\u003ePrevious\u003c/p\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Tensor","URL":"tensor","Title":"Tensor","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":null,"Specials":{},"Description":"The \u003cstrong\u003etensor.Tensor\u003c/strong\u003e represents n-dimensional data of various types, providing similar functionality to the widely used \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e libraries in Python, and the commercial MATLAB framework.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eTensor\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-22\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003cstrong\u003etensor.Tensor\u003c/strong\u003e represents n-dimensional data of various types, providing similar functionality to the widely used \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e libraries in Python, and the commercial MATLAB framework.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e \u003ca href=\"math\" target=\"_blank\"\u003emath\u003c/a\u003e mode operates on tensor data exclusively: see documentation there for convenient shortcut expressions for common tensor operations. This page documents the underlying Go language implementation of tensors. See \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e for the Go API docs, \u003ca href=\"tensor-math\" target=\"_blank\"\u003etensor math\u003c/a\u003e for basic math operations that can be performed on tensors, and \u003ca href=\"stats\" target=\"_blank\"\u003estats\u003c/a\u003e for statistics functions operating on tensor data.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eA tensor can be constructed from a Go slice, and accessed using a 1D index into that slice:\u003c/p\u003e\u003ctextarea id=\"editor-3\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFromValues(0, 1, 2, 3)\nval := x.Float1D(2)\n\nfmt.Println(val)\n\u003c/textarea\u003e\u003cdiv id=\"frame-4\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-5\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNote that the type of the tensor is inferred from the values, using standard Go rules, so you would need to add a decimal to obtain floating-point numbers instead of \u003ccode\u003eint\u003c/code\u003es:\u003c/p\u003e\u003ctextarea id=\"editor-6\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFromValues(0., 1., 2., 3.)\nval := x.Float1D(2)\n\nfmt.Printf(\"value: %v %T\\n\", val, val)\n\u003c/textarea\u003e\u003cdiv id=\"frame-7\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-8\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can reshape the tensor by setting the number of values along any number of dimensions, preserving any values that are compatible with the new shape, and access values using n-dimensional indexes:\u003c/p\u003e\u003ctextarea id=\"editor-9\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFromValues(0, 1, 2, 3)\nx.SetShapeSizes(2, 2)\nval := x.Float(1, 0)\n\nfmt.Println(val)\n\u003c/textarea\u003e\u003cdiv id=\"frame-10\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-11\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe dimensions are organized in \u003cem\u003erow major\u003c/em\u003e format (same as \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e), so the number of rows comes first, then columns; the last dimension (i.e., columns in this case) is the \u003cem\u003einnermost\u003c/em\u003e dimension, so that each column represents a contiguous array of values in memory, while rows are \u003cem\u003enot\u003c/em\u003e contiguous.\u003c/p\u003e\u003cp id=\"text-12\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can create a tensor with a specified shape, and fill it with a single value:\u003c/p\u003e\u003ctextarea id=\"editor-13\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat32(2, 2)\ntensor.SetAllFloat64(x, 1)\n\nfmt.Println(x)\n\u003c/textarea\u003e\u003cdiv id=\"frame-14\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-15\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNote the detailed formatting available from the standard stringer \u003ccode\u003eString()\u003c/code\u003e method on any tensor, providing the shape sizes on the first line, with dimensional indexes for the values.\u003c/p\u003e\u003cp id=\"text-16\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eA given tensor can hold any standard Go value type, including \u003ccode\u003eint\u003c/code\u003e, \u003ccode\u003efloat32\u003c/code\u003e and \u003ccode\u003efloat64\u003c/code\u003e, and \u003ccode\u003estring\u003c/code\u003e values (using Go generics for the numerical types), and it provides accessor methods for the following “core” types:\u003c/p\u003e\u003cul id=\"frame-17\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eFloat\u003c/code\u003e methods set and return \u003ccode\u003efloat64\u003c/code\u003e values.\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eInt\u003c/code\u003e methods set and return \u003ccode\u003eint\u003c/code\u003e values.\u003c/li\u003e\u003cli id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eString\u003c/code\u003e methods set and return \u003ccode\u003estring\u003c/code\u003e values.\u003c/li\u003e\u003c/ul\u003e\u003cp id=\"text-18\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFor example, you can directly get a \u003ccode\u003estring\u003c/code\u003e representation of any value:\u003c/p\u003e\u003ctextarea id=\"editor-19\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFromValues(0, 1, 2, 3)\nval := x.String1D(2)\n\nfmt.Println(val)\n\u003c/textarea\u003e\u003cdiv id=\"frame-20\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch3 id=\"setting-values\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eSetting values\u003c/h3\u003e\u003cp id=\"text-22\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo set a value, you typically use a type-specific method most appropriate for the underlying data type:\u003c/p\u003e\u003ctextarea id=\"editor-23\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat32(2, 2)\ntensor.SetAllFloat64(x, 1)\n\nx.SetFloat(3.14, 0, 1) // value comes first, then the appropriate number of indexes as varargs...\n\nfmt.Println(x)\n\u003c/textarea\u003e\u003cdiv id=\"frame-24\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-25\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThere are also \u003ccode\u003eValue\u003c/code\u003e, \u003ccode\u003eValue1D\u003c/code\u003e, and \u003ccode\u003eSet\u003c/code\u003e, \u003ccode\u003eSet1D\u003c/code\u003e methods that use Generics to operate on the actual underlying data type:\u003c/p\u003e\u003ctextarea id=\"editor-26\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat32(2, 2)\ntensor.SetAllFloat64(x, 1)\n\nx.Set(3.1415, 0, 1)\n\nval := x.Value(0, 1)\nv1d := x.Value1D(1)\n\nfmt.Println(x)\nfmt.Printf(\"val: %v %T\\n\", val, val)\nfmt.Printf(\"v1d: %v\\n\", v1d)\n\u003c/textarea\u003e\u003cdiv id=\"frame-27\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch2 id=\"views-and-values\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eViews and values\u003c/h2\u003e\u003cp id=\"text-29\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe abstract \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Tensor\" target=\"_blank\"\u003etensor.Tensor\u003c/a\u003e interface is implemented (and extended) by the concrete \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Values\" target=\"_blank\"\u003etensor.Values\u003c/a\u003e types, which are what we’ve been getting in the above examples, and directly manage an underlying Go slice of values. These can be reshaped and appended to, like a Go slice.\u003c/p\u003e\u003cp id=\"text-30\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn addition, there are various \u003cem\u003eView\u003c/em\u003e types that wrap other tensors and provide more flexible ways of accessing the tensor values, and provide all of the same core functionality present in \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e.\u003c/p\u003e\u003ch3 id=\"sliced\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eSliced\u003c/h3\u003e\u003cp id=\"text-32\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFirst, this is the starting Values tensor, as a 3x4 matrix:\u003c/p\u003e\u003ctextarea id=\"editor-33\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 4)\nx.CopyFrom(tensor.NewIntRange(12))\n\nfmt.Println(x)\n\u003c/textarea\u003e\u003cdiv id=\"frame-34\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-35\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eUsing the \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Reslice\" target=\"_blank\"\u003etensor.Reslice\u003c/a\u003e function, you can extract any subset from this 2D matrix, for example the values in a given row or column:\u003c/p\u003e\u003ctextarea id=\"editor-36\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 4)\nx.CopyFrom(tensor.NewIntRange(12))\n\nrow1 := tensor.Reslice(x, 1) // row is first index; column index is unspecified = all\ncol1 := tensor.Reslice(x, tensor.FullAxis, 1) // explicitly request all rows\n\nfmt.Println(\"row1:\", row1)\nfmt.Println(\"col1:\", col1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-37\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-38\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNote that the column values got turned into a 1D tensor in this process – to keep it as a column vector (2D with 1 column and 3 rows), you need to add an extra “blank” dimension, which can be done using the \u003ccode\u003etensor.NewAxis\u003c/code\u003e value:\u003c/p\u003e\u003ctextarea id=\"editor-39\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 4)\nx.CopyFrom(tensor.NewIntRange(12))\n\ncol1 := tensor.Reslice(x, tensor.FullAxis, 1, tensor.NewAxis)\n\nfmt.Println(\"col1:\", col1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-40\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-41\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can also specify sub-ranges along each dimension, or even reorder the values, by using a \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Slice\" target=\"_blank\"\u003etensor.Slice\u003c/a\u003e element that has \u003ccode\u003eStart\u003c/code\u003e, \u003ccode\u003eStop\u003c/code\u003e and \u003ccode\u003eStep\u003c/code\u003e values, like those of a standard Go \u003ccode\u003efor\u003c/code\u003e loop expression, with sensible default behavior for zero values:\u003c/p\u003e\u003ctextarea id=\"editor-42\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 4)\nx.CopyFrom(tensor.NewIntRange(12))\n\ncol1 := tensor.Reslice(x, tensor.Slice{Step: -1}, 1)\n\nfmt.Println(\"col1:\", col1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-43\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-44\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can use \u003ccode\u003etensor.Ellipsis\u003c/code\u003e to specify \u003ccode\u003eFullAxis\u003c/code\u003e for all the dimensions up to those specified, to flexibly focus on the innermost dimensions:\u003c/p\u003e\u003ctextarea id=\"editor-45\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 2, 2)\nx.CopyFrom(tensor.NewIntRange(12))\n\nlast1 := tensor.Reslice(x, tensor.Ellipsis, 1)\n\nfmt.Println(\"x:\", x)\nfmt.Println(\"last1:\", last1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-46\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-47\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eAs in \u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e (and standard Go slices), the \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Sliced\" target=\"_blank\"\u003etensor.Sliced\u003c/a\u003e view wraps the original source tensor, so that if you change a value in that original source, \u003cem\u003ethe value automatically changes in the view\u003c/em\u003e as well. Use the \u003ccode\u003eAsValues()\u003c/code\u003e method on a view to get a new concrete \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Values\" target=\"_blank\"\u003etensor.Values\u003c/a\u003e representation of the view (equivalent to the NumPy \u003ccode\u003ecopy\u003c/code\u003e function).\u003c/p\u003e\u003ctextarea id=\"editor-48\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 2, 2)\nx.CopyFrom(tensor.NewIntRange(12))\n\nlast1 := tensor.Reslice(x, tensor.Ellipsis, 1)\n\nfmt.Println(\"values:\", x)\nfmt.Println(\"last1:\", last1)\n\nvalues := last1.AsValues()\nx.Set(3.14, 1, 0, 1)\n\nfmt.Println(\"values:\", x)\nfmt.Println(\"last1:\", last1)\nfmt.Println(\"values:\", values)\n\u003c/textarea\u003e\u003cdiv id=\"frame-49\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch3 id=\"masked-by-booleans\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eMasked by booleans\u003c/h3\u003e\u003cp id=\"text-51\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can apply a boolean mask to a tensor, to extract arbitrary values where the boolean value is true:\u003c/p\u003e\u003ctextarea id=\"editor-52\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 4)\nx.CopyFrom(tensor.NewIntRange(12))\n\nm := tensor.NewMasked(x).Filter(func(tsr tensor.Tensor, idx int) bool {\n\treturn tsr.Float1D(idx) \u003e= 6\n})\nvals := m.AsValues()\n\nfmt.Println(\"masked: \", m)\nfmt.Println(\"vals: \", vals)\n\u003c/textarea\u003e\u003cdiv id=\"frame-53\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-54\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eNote that missing values are encoded as \u003ccode\u003eNaN\u003c/code\u003e, which allows the resulting \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Masked\" target=\"_blank\"\u003etensor.Masked\u003c/a\u003e view to retain the shape of the original, and all of the other math functions operating on tensors properly treat \u003ccode\u003eNaN\u003c/code\u003e as a missing value that is ignored. You can also get the concrete values as shown, but this reduces the shape to 1D by default.\u003c/p\u003e\u003ch3 id=\"indexes\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eIndexes\u003c/h3\u003e\u003cp id=\"text-56\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can extract arbitrary values from a tensor using a list of indexes (as a tensor), where the shape of that list then determines the shape of the resulting view:\u003c/p\u003e\u003ctextarea id=\"editor-57\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 4)\nx.CopyFrom(tensor.NewIntRange(12))\n\nixs := tensor.NewIntFromValues(\n\t0, 1,\n\t0, 1,\n\t0, 2,\n\t0, 2,\n\t1, 1,\n\t1, 1,\n\t2, 2,\n\t2, 2)\nixs.SetShapeSizes(2,4,2) // note: last 2 is the number of indexes into source\n\nix := tensor.NewIndexed(x, ixs)\n\nfmt.Println(ix)\n\u003c/textarea\u003e\u003cdiv id=\"frame-58\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-59\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eYou can also feed Masked indexes into the \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Indexed\" target=\"_blank\"\u003etensor.Indexed\u003c/a\u003e view to get a reshaped view:\u003c/p\u003e\u003ctextarea id=\"editor-60\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 4)\nx.CopyFrom(tensor.NewIntRange(12))\n\nm := tensor.NewMasked(x).Filter(func(tsr tensor.Tensor, idx int) bool {\n\treturn tsr.Float1D(idx) \u003e= 6\n})\nixs := m.SourceIndexes(true)\nixs.SetShapeSizes(2,3,2)\nix := tensor.NewIndexed(x, ixs)\n\nfmt.Println(\"masked:\", ix)\n\u003c/textarea\u003e\u003cdiv id=\"frame-61\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch3 id=\"differences-from-numpy\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eDifferences from NumPy\u003c/h3\u003e\u003cp id=\"text-63\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ca href=\"https://numpy.org/doc/stable/index.html\" target=\"_blank\"\u003eNumPy\u003c/a\u003e is somewhat confusing with respect to the distinction between \u003cem\u003ebasic indexing\u003c/em\u003e (using a single index or sliced ranges of indexes along each dimension) versus \u003cem\u003eadvanced indexing\u003c/em\u003e (using an array of indexes or bools). Basic indexing returns a \u003cem\u003eview\u003c/em\u003e into the original data (where changes to the view directly affect the underlying type), while advanced indexing returns a \u003cem\u003ecopy\u003c/em\u003e.\u003c/p\u003e\u003cp id=\"text-64\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eHowever, rather confusingly (per this \u003ca href=\"https://stackoverflow.com/questions/15691740/does-assignment-with-advanced-indexing-copy-array-data\" target=\"_blank\"\u003estack overflow question\u003c/a\u003e), you can do direct assignment through advanced indexing (more on this below):\u003c/p\u003e\u003ctextarea id=\"editor-65\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ea[np.array([1,2])] = 5 # or:\na[a \u003e 0.5] = 1 # boolean advanced indexing\n\n\u003c/textarea\u003e\u003cp id=\"text-66\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIn the tensor package, all of the View types (\u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Sliced\" target=\"_blank\"\u003etensor.Sliced\u003c/a\u003e, \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Reshaped\" target=\"_blank\"\u003etensor.Reshaped\u003c/a\u003e, \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Masked\" target=\"_blank\"\u003etensor.Masked\u003c/a\u003e, and \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Indexed\" target=\"_blank\"\u003etensor.Indexed\u003c/a\u003e) are unambiguously wrappers around a source tensor, and their values change when the source changes. Use \u003ccode\u003e.AsValues()\u003c/code\u003e to break that connection and get the view as a new set of concrete values.\u003c/p\u003e\u003ch3 id=\"row-cell-access\" style=\"margin:0.25em;font-size:22px;font-weight:normal;line-height:1.2727273;text-align:start\"\u003eRow, Cell access\u003c/h3\u003e\u003cp id=\"text-68\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#RowMajor\" target=\"_blank\"\u003etensor.RowMajor\u003c/a\u003e interface provides a convenient set of methods to access tensors where the first, outermost dimension is a row, and there may be multiple remaining dimensions after that. All concrete \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensor#Values\" target=\"_blank\"\u003etensor.Values\u003c/a\u003e tensors implement this interface.\u003c/p\u003e\u003cp id=\"text-69\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFor example, you can easily get a \u003ccode\u003eSubSpace\u003c/code\u003e tensor that contains the values within a given row, and set values within a row tensor using a flat 1D “cell” index that applies to the values within a row:\u003c/p\u003e\u003ctextarea id=\"editor-70\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensor.NewFloat64(3, 2, 2)\nx.CopyFrom(tensor.NewIntRange(12))\n\nx.SetFloatRow(3.14, 1, 2) // set 1D cell 2 in row 1\nrow1 := x.RowTensor(1)\n\nfmt.Println(\"values:\", x)\nfmt.Println(\"row1:\", row1)\n\u003c/textarea\u003e\u003cdiv id=\"frame-71\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003ch2 id=\"tensor-pages\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eTensor pages\u003c/h2\u003e\u003cul id=\"frame-73\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"matrix\" target=\"_blank\"\u003eMatrix\u003c/a\u003e\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ca href=\"tensor-math\" target=\"_blank\"\u003eTensor math\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"},{"Name":"Tensorfs","URL":"tensorfs","Title":"Tensorfs","Date":"0001-01-01T00:00:00Z","Authors":null,"Draft":false,"Categories":null,"Specials":{},"Description":"\u003cstrong\u003etensorfs\u003c/strong\u003e provides a virtual filesystem for \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e data, which can be accessed for example in \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e \u003ca href=\"math\" target=\"_blank\"\u003emath\u003c/a\u003e mode expressions, like the variable storage system in \u003ca href=\"https://ipython.readthedocs.io/en/stable/interactive/tutorial.html\" target=\"_blank\"\u003eIPython / Jupyter\u003c/a\u003e, with the advantage that the hierarchical structure of a filesystem allows data to be organized in more intuitive and effective ways. For example, data at different time scales can be put into different directories, or multiple different statistics computed on a given set of data can be put into a subdirectory. \u003ca href=\"stats#Groups\" target=\"_blank\"\u003eGroups\u003c/a\u003e creates pivot-table style groups of values as directories, for example.","HTML":"\u003ccontent id=\"content-0\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;min-height:10em;font-weight:thin;text-align:start\"\u003e\u003cdiv id=\"content-content-go-188\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003c/div\u003e\u003cdiv id=\"content-content-go-191\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;padding-right:0.5em;padding-left:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"content-content-go-203\" style=\"font-size:36px;font-weight:normal;line-height:1.2222222;text-align:start\"\u003eTensorfs\u003c/p\u003e\u003cdiv id=\"content-content-go-226\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cmain id=\"frame-23\" style=\"display:flex;flex-direction:column;flex-grow:1;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003cp id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003cstrong\u003etensorfs\u003c/strong\u003e provides a virtual filesystem for \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e data, which can be accessed for example in \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e \u003ca href=\"math\" target=\"_blank\"\u003emath\u003c/a\u003e mode expressions, like the variable storage system in \u003ca href=\"https://ipython.readthedocs.io/en/stable/interactive/tutorial.html\" target=\"_blank\"\u003eIPython / Jupyter\u003c/a\u003e, with the advantage that the hierarchical structure of a filesystem allows data to be organized in more intuitive and effective ways. For example, data at different time scales can be put into different directories, or multiple different statistics computed on a given set of data can be put into a subdirectory. \u003ca href=\"stats#Groups\" target=\"_blank\"\u003eGroups\u003c/a\u003e creates pivot-table style groups of values as directories, for example.\u003c/p\u003e\u003cp id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensorfs\u003c/code\u003e implements the Go \u003ca href=\"https://pkg.go.dev/io/fs\" target=\"_blank\"\u003efs\u003c/a\u003e interface, and can be accessed using fs-general tools, including the cogent core \u003ccode\u003efiletree\u003c/code\u003e and the \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e shell.\u003c/p\u003e\u003cp id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThere are two main APIs, one for direct usage within Go, and another that is used by the \u003ca href=\"goal\" target=\"_blank\"\u003eGoal\u003c/a\u003e framework for interactive shell-based access, which always operates relative to a current working directory.\u003c/p\u003e\u003ch2 id=\"go-api\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eGo API\u003c/h2\u003e\u003cp id=\"text-4\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThere are type-specific accessor methods for the standard high-frequency data types: \u003ccode\u003eFloat64\u003c/code\u003e, \u003ccode\u003eFloat32\u003c/code\u003e, \u003ccode\u003eInt\u003c/code\u003e, and \u003ccode\u003eStringValue\u003c/code\u003e (\u003ccode\u003eString\u003c/code\u003e is taken by the stringer interface):\u003c/p\u003e\u003ctextarea id=\"editor-5\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003edir, _ := tensorfs.NewDir(\"root\")\nx := dir.Float64(\"data\", 3, 3)\n\nfmt.Println(dir.ListLong(true, 2))\nfmt.Println(x)\n\u003c/textarea\u003e\u003cdiv id=\"frame-6\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-7\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eWhich are wrappers around the underlying Generic \u003ccode\u003eValue\u003c/code\u003e method:\u003c/p\u003e\u003ctextarea id=\"editor-8\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003ex := tensorfs.Value[float64](dir, \"data\", 3, 3)\n\n\u003c/textarea\u003e\u003cp id=\"text-9\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThese methods create the given tensor if it does not yet exist, and otherwise return it, providing a robust order-independent way of accessing / constructing the relevant data.\u003c/p\u003e\u003cp id=\"text-10\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eFor efficiency, \u003cem\u003ethere are no checks\u003c/em\u003e on the existing value relative to the arguments passed, so if you end up using the same name for two different things, that will cause problems that will hopefully become evident. If you want to ensure that the size is correct, you should use an explicit \u003ccode\u003etensor.SetShapeSizes\u003c/code\u003e call, which is still quite efficient if the size is the same. You can also have an initial call to \u003ccode\u003eValue\u003c/code\u003e that has no size args, and then set the size later – that works fine.\u003c/p\u003e\u003cp id=\"text-11\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThere are also a few other variants of the \u003ccode\u003eValue\u003c/code\u003e functionality:\u003c/p\u003e\u003cul id=\"frame-12\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eScalar\u003c/code\u003e calls \u003ccode\u003eValue\u003c/code\u003e with a size of 1.\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eValues\u003c/code\u003e makes multiple tensor values of the same shape, with a final variadic list of names.\u003c/li\u003e\u003cli id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eValueType\u003c/code\u003e takes a \u003ccode\u003ereflect.Kind\u003c/code\u003e arg for the data type, which can then be a variable.\u003c/li\u003e\u003cli id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003eSetTensor\u003c/code\u003e sets a tensor to a node of given name, creating the node if needed. This is also available as the \u003ccode\u003eSet\u003c/code\u003e method on a directory node.\u003c/li\u003e\u003c/ul\u003e\u003cp id=\"text-13\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e\u003ccode\u003etensorfs.DirTable\u003c/code\u003e returns a \u003ca href=\"table\" target=\"_blank\"\u003etable\u003c/a\u003e with all the tensors under a given directory node, which can then be used for making plots or doing other forms of data analysis. This works best when each tensor has the same outer-most row dimension. The table is persistent and very efficient, using direct pointers to the underlying tensor values.\u003c/p\u003e\u003ch2 id=\"directories\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eDirectories\u003c/h2\u003e\u003cp id=\"text-15\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eA given \u003ca href=\"https://pkg.go.dev/cogentcore.org/lab/tensorfs#Node\" target=\"_blank\"\u003etensorfs.Node\u003c/a\u003e can either have a \u003ca href=\"tensor\" target=\"_blank\"\u003etensor\u003c/a\u003e value or be a \u003cem\u003esubdirectory\u003c/em\u003e containing a list of other node lements.\u003c/p\u003e\u003cp id=\"text-16\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eTo make a new subdirectory:\u003c/p\u003e\u003ctextarea id=\"editor-17\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003edir, _ := tensorfs.NewDir(\"root\")\nsubdir := dir.Dir(\"sub\")\nx := subdir.Float64(\"data\", 3, 3)\n\nfmt.Println(dir.ListLong(true, 2))\nfmt.Println(x)\n\u003c/textarea\u003e\u003cdiv id=\"frame-18\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-19\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eIf the subdirectory doesn’t exist yet, it will be made, and otherwise it is returned. Any errors will be logged and a nil returned, likely causing a panic unless you expect it to fail and check for that.\u003c/p\u003e\u003ch2 id=\"operating-over-values-across-directories\" style=\"margin:0.25em;font-size:28px;font-weight:normal;line-height:1.2857143;text-align:start\"\u003eOperating over values across directories\u003c/h2\u003e\u003cp id=\"text-21\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThe \u003ccode\u003eValuesFunc\u003c/code\u003e method on a directory node allows you to easily extract a list of values across any number of subdirectories (it only returns the final value “leaves” of the filetree):\u003c/p\u003e\u003ctextarea id=\"editor-22\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003edir, _ := tensorfs.NewDir(\"root\")\nsubdir := dir.Dir(\"sub\")\nx := subdir.Float64(\"x\", 3, 3)\nsubsub := subdir.Dir(\"stats\")\ny := subsub.Float64(\"y\", 1)\nz := subsub.Float64(\"z\", 1)\n\nfmt.Println(dir.ListLong(true, 2))\n\nvals := dir.ValuesFunc(nil) // nil = get everything\nfor _, v := range vals {\n\tfmt.Println(v)\n}\n\u003c/textarea\u003e\u003cdiv id=\"frame-23\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-24\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThus, even if you have statistics or other data nested down deep, this will “flatten” the hierarchy and allow you to process it. Here’s a version that actually filters the nodes:\u003c/p\u003e\u003ctextarea id=\"editor-25\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:95%;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\" rows=\"10\" cols=\"30\"\u003edir, _ := tensorfs.NewDir(\"root\")\nsubdir := dir.Dir(\"sub\")\nx := subdir.Float64(\"x\", 5, 5)\nsubsub := subdir.Dir(\"stats\")\ny := subsub.Float64(\"y\", 1)\nz := subsub.Float64(\"z\", 1)\n\nfmt.Println(dir.ListLong(true, 2))\n\nvals := dir.ValuesFunc(func(n *tensorfs.Node) bool {\n\tif n.IsDir() { // can filter by dirs here too (get to see everything)\n\t\treturn true\n\t}\n\treturn n.Tensor.NumDims() == 1\n})\nfor _, v := range vals {\n\tfmt.Println(v)\n}\n\u003c/textarea\u003e\u003cdiv id=\"frame-26\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;font-weight:thin;text-align:start\"\u003e\u003ceditor id=\"editor-0\" style=\"background:var(--surface-container-color);display:flex;flex-direction:row;justify-content:start;align-items:start;gap:0.5em;min-width:10em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;font-weight:thin;line-height:1.3;text-align:start;border-radius:16px\"\u003e\u003c/editor\u003e\u003c/div\u003e\u003cp id=\"text-27\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003eThere are parallel \u003ccode\u003eNode\u003c/code\u003e and \u003ccode\u003eValue\u003c/code\u003e access methods for directory nodes, with the Value ones being:\u003c/p\u003e\u003cul id=\"frame-28\" style=\"display:flex;flex-direction:column;justify-content:start;align-items:start;gap:0.5em;padding-left:4ch;font-weight:thin;text-align:start\"\u003e\u003cli id=\"text-0\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003etsr := dir.Value(\"name\")\u003c/code\u003e returns tensor directly, will panic if not valid\u003c/li\u003e\u003cli id=\"text-1\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003etsrs, err := dir.Values(\"name1\", \"name2\")\u003c/code\u003e returns a slice of tensor values within directory by name. a plain \u003ccode\u003e.Values()\u003c/code\u003e returns all values.\u003c/li\u003e\u003cli id=\"text-2\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003etsrs := dir.ValuesFunc(\u003cfilter func\u003e)\u003c/code\u003e walks down directories (unless filtered) and returns a flat list of all tensors found. Goes in “directory order” = order nodes were added.\u003c/li\u003e\u003cli id=\"text-3\" style=\"margin:0.25em;font-weight:normal;line-height:1.5;text-align:start\"\u003e• \u003ccode\u003etsrs := dir.ValuesAlphaFunc(\u003cfilter func\u003e)\u003c/code\u003e is like \u003ccode\u003eValuesFunc\u003c/code\u003e but traverses in alpha order at each node.\u003c/li\u003e\u003c/ul\u003e\u003c/main\u003e\u003c/div\u003e\u003c/div\u003e\u003c/content\u003e"}]