2025-12-03 12:37.10: New job: test ahrefs/ocannl https://github.com/ahrefs/ocannl.git#refs/heads/master (8b77ba7394f4c89e3a83d77ec4c6ef5920b51476) (linux-x86_64:(lint-fmt)) Base: ocaml/opam:debian-13-ocaml-4.08@sha256:e3cc4e8fe5c00f48c72a719e3551b1d8a51c2862349a0f7507e8aa29fdf72321 ocamlformat version: version 0.28.1 (from opam) To reproduce locally: git clone --recursive "https://github.com/ahrefs/ocannl.git" -b "master" && cd "ocannl" && git reset --hard 8b77ba73 cat > Dockerfile <<'END-OF-DOCKERFILE' FROM ocaml/opam:debian-13-ocaml-4.08@sha256:e3cc4e8fe5c00f48c72a719e3551b1d8a51c2862349a0f7507e8aa29fdf72321 USER 1000:1000 RUN cd ~/opam-repository && (git cat-file -e 6c1b38620288b5bf349067f089a7b1fc91185d94 || git fetch origin master) && git reset -q --hard 6c1b38620288b5bf349067f089a7b1fc91185d94 && git log --no-decorate -n1 --oneline && opam update -u RUN opam depext -i dune WORKDIR /src RUN opam depext -i ocamlformat=0.28.1 COPY --chown=1000:1000 . /src/ RUN opam exec -- dune build @fmt --ignore-promoted-rules || (echo "dune build @fmt failed"; exit 2) END-OF-DOCKERFILE docker build . END-REPRO-BLOCK 2025-12-03 12:37.10: Using cache hint "ahrefs/ocannl-ocaml/opam:debian-13-ocaml-4.08@sha256:e3cc4e8fe5c00f48c72a719e3551b1d8a51c2862349a0f7507e8aa29fdf72321-debian-13-4.08_opam-2.4-ocamlformat-6c1b38620288b5bf349067f089a7b1fc91185d94" 2025-12-03 12:37.10: Using OBuilder spec: ((from ocaml/opam:debian-13-ocaml-4.08@sha256:e3cc4e8fe5c00f48c72a719e3551b1d8a51c2862349a0f7507e8aa29fdf72321) (user (uid 1000) (gid 1000)) (run (cache (opam-archives (target /home/opam/.opam/download-cache))) (network host) (shell "cd ~/opam-repository && (git cat-file -e 6c1b38620288b5bf349067f089a7b1fc91185d94 || git fetch origin master) && git reset -q --hard 6c1b38620288b5bf349067f089a7b1fc91185d94 && git log --no-decorate -n1 --oneline && opam update -u")) (run (cache (opam-archives (target /home/opam/.opam/download-cache))) (network host) (shell "opam depext -i dune")) (workdir /src) (run (cache (opam-archives (target /home/opam/.opam/download-cache))) (network host) (shell "opam depext -i ocamlformat=0.28.1")) (copy (src .) (dst /src/)) (run (shell "opam exec -- dune build @fmt --ignore-promoted-rules || (echo \"dune build @fmt failed\"; exit 2)")) ) 2025-12-03 12:37.10: Waiting for resource in pool OCluster 2025-12-03 12:37.10: Waiting for worker… 2025-12-03 12:37.11: Got resource from pool OCluster Building on bremusa.ocamllabs.io All commits already cached HEAD is now at 8b77ba73 Handle corner case in iterated variable processing (from ocaml/opam:debian-13-ocaml-4.08@sha256:e3cc4e8fe5c00f48c72a719e3551b1d8a51c2862349a0f7507e8aa29fdf72321) 2025-12-03 12:37.11 ---> using "d458486dd7823c592e7ea9c88366c5f90e1939c3b51f3abbd6760272096f8a3e" from cache /: (user (uid 1000) (gid 1000)) /: (run (cache (opam-archives (target /home/opam/.opam/download-cache))) (network host) (shell "cd ~/opam-repository && (git cat-file -e 6c1b38620288b5bf349067f089a7b1fc91185d94 || git fetch origin master) && git reset -q --hard 6c1b38620288b5bf349067f089a7b1fc91185d94 && git log --no-decorate -n1 --oneline && opam update -u")) 6c1b386202 Merge pull request #28774 from Julow/release-ocamlformat-0.28.1 <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [default] Initialised default (at git+file:///home/opam/opam-repository): [INFO] opam 2.1 and 2.2 include many performance and security improvements over 2.0; please consider upgrading (https://opam.ocaml.org/doc/Install.html) Everything as up-to-date as possible (run with --verbose to show unavailable upgrades). However, you may "opam upgrade" these packages explicitly, which will ask permission to downgrade or uninstall the conflicting packages. Nothing to do. # Run eval $(opam env) to update the current shell environment 2025-12-03 12:37.11 ---> using "a7d3c7d9f6aff7dc059c465a33e7ef3fda4b4a1ee9c79bef8645b5cd4da72b96" from cache /: (run (cache (opam-archives (target /home/opam/.opam/download-cache))) (network host) (shell "opam depext -i dune")) # Detecting depexts using vars: arch=x86_64, os=linux, os-distribution=debian, os-family=debian # No extra OS packages requirements found. # All required OS packages found. # Now letting opam install the packages The following actions will be performed: - install dune 3.20.2 <><> Gathering sources ><><><><><><><><><><><><><><><><><><><><><><><><><><><><> [dune.3.20.2] found in cache <><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> -> installed dune.3.20.2 Done. # Run eval $(opam env) to update the current shell environment 2025-12-03 12:37.11 ---> using "b8799a0f87a66bd49a9341889a0027044c03db80ad17a5edb3adaf72f166d8fd" from cache /: (workdir /src) /src: (run (cache (opam-archives (target /home/opam/.opam/download-cache))) (network host) (shell "opam depext -i ocamlformat=0.28.1")) # Detecting depexts using vars: arch=x86_64, os=linux, os-distribution=debian, os-family=debian # No extra OS packages requirements found. # All required OS packages found. # Now letting opam install the packages The following actions will be performed: - install sexplib0 v0.14.0 [required by base] - install ocamlbuild 0.16.1 [required by fpath, astring, uuseg] - install either 1.0.0 [required by ocamlformat-lib] - install menhirLib 20250912 [required by ocamlformat-lib] - install csexp 1.5.2 [required by ocamlformat] - install camlp-streams 5.0.1 [required by ocamlformat-lib] - install seq base [required by re] - install menhirSdk 20250912 [required by ocamlformat-lib] - install fix 20250919 [required by ocamlformat-lib] - install menhirCST 20250912 [required by menhir] - install ocamlfind 1.9.8 [required by ocp-indent, astring, fpath, uuseg] - install dune-build-info 3.20.2 [required by ocamlformat-lib] - install cmdliner 2.0.0 [required by ocamlformat] - install ocaml-version 4.0.3 [required by ocamlformat-lib] - install dune-configurator 3.20.2 [required by base] - install re 1.11.0 [required by ocamlformat] - install menhir 20250912 [required by ocamlformat-lib] - install topkg 1.1.1 [required by fpath, astring, uuseg] - install ocp-indent 1.9.0 [required by ocamlformat-lib] - install base v0.14.3 [required by ocamlformat-lib] - install uutf 1.0.4 [required by ocamlformat-lib] - install astring 0.8.5 [required by ocamlformat-lib] - install stdio v0.14.0 [required by ocamlformat-lib] - install uucp 15.0.0 [required by uuseg] - install fpath 0.7.3 [required by ocamlformat-lib] - install uuseg 15.0.0 [required by ocamlformat-lib] - install ocamlformat-lib 0.28.1 [required by ocamlformat] - install ocamlformat 0.28.1 ===== 28 to install ===== <><> Gathering sources ><><><><><><><><><><><><><><><><><><><><><><><><><><><><> [astring.0.8.5] found in cache [base.v0.14.3] found in cache [camlp-streams.5.0.1] found in cache [cmdliner.2.0.0] found in cache [csexp.1.5.2] found in cache [dune-build-info.3.20.2] found in cache [dune-configurator.3.20.2] found in cache [either.1.0.0] found in cache [fix.20250919] found in cache [fpath.0.7.3] found in cache [menhir.20250912] found in cache [menhirCST.20250912] found in cache [menhirLib.20250912] found in cache [menhirSdk.20250912] found in cache [ocaml-version.4.0.3] found in cache [ocamlbuild.0.16.1] found in cache [ocamlfind.1.9.8] found in cache [ocamlformat.0.28.1] found in cache [ocamlformat-lib.0.28.1] found in cache [ocp-indent.1.9.0] found in cache [re.1.11.0] found in cache [sexplib0.v0.14.0] found in cache [stdio.v0.14.0] found in cache [topkg.1.1.1] found in cache [uucp.15.0.0] found in cache [uuseg.15.0.0] found in cache [uutf.1.0.4] found in cache <><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> -> installed seq.base -> installed camlp-streams.5.0.1 -> installed csexp.1.5.2 -> installed either.1.0.0 -> installed fix.20250919 -> installed cmdliner.2.0.0 -> installed menhirCST.20250912 -> installed menhirLib.20250912 -> installed menhirSdk.20250912 -> installed ocaml-version.4.0.3 -> installed re.1.11.0 -> installed sexplib0.v0.14.0 -> installed dune-build-info.3.20.2 -> installed dune-configurator.3.20.2 -> installed ocamlfind.1.9.8 -> installed ocp-indent.1.9.0 -> installed ocamlbuild.0.16.1 -> installed base.v0.14.3 -> installed topkg.1.1.1 -> installed stdio.v0.14.0 -> installed uutf.1.0.4 -> installed astring.0.8.5 -> installed fpath.0.7.3 -> installed menhir.20250912 -> installed uucp.15.0.0 -> installed uuseg.15.0.0 -> installed ocamlformat-lib.0.28.1 -> installed ocamlformat.0.28.1 Done. <><> ocp-indent.1.9.0 installed successfully ><><><><><><><><><><><><><><><><><> => This package requires additional configuration for use in editors. Install package 'user-setup', or manually: * for Emacs, add these lines to ~/.emacs: (add-to-list 'load-path "/home/opam/.opam/4.08/share/emacs/site-lisp") (require 'ocp-indent) * for Vim, add this line to ~/.vimrc: set rtp^="/home/opam/.opam/4.08/share/ocp-indent/vim" # Run eval $(opam env) to update the current shell environment 2025-12-03 12:37.11 ---> using "7b71439e6ac9917292b28dc59ecc075d01d03dd2ef11c372809a6cf99e594a22" from cache /src: (copy (src .) (dst /src/)) 2025-12-03 12:37.12 ---> saved as "8ae9766adfd67c7f074947d88ddfb01aff1d679545bca97fcec8969d69b50f98" /src: (run (shell "opam exec -- dune build @fmt --ignore-promoted-rules || (echo \"dune build @fmt failed\"; exit 2)")) Warning: Invalid documentation comment: File "tensor/einsum_types.ml", line 38, characters 0-0: End of text is not allowed in '[...]' (code). File "tensor/einsum_types.ml", line 1, characters 0-0: diff --git a/_build/default/tensor/einsum_types.ml b/_build/default/tensor/.formatted/einsum_types.ml index 084d9ac..e357e66 100644 --- a/_build/default/tensor/einsum_types.ml +++ b/_build/default/tensor/.formatted/einsum_types.ml @@ -4,18 +4,16 @@ open Base -(** Use_padding specification for convolutions. *) type use_padding_spec = [ `True | `False | `Unspecified ] [@@deriving compare, sexp] +(** Use_padding specification for convolutions. *) -(** Convolution component for affine axis specifications. - Note: [dilation] is a string because it can be an identifier at parse time, - and is resolved to an int at runtime. *) type conv_spec = { dilation : string; kernel_label : string; use_padding : use_padding_spec } [@@deriving compare, sexp] +(** Convolution component for affine axis specifications. Note: [dilation] is a string because it + can be an identifier at parse time, and is resolved to an int at runtime. *) -(** Specification for individual axes in the einsum notation. - Note: [stride] is a string because it can be an identifier at parse time, - and is resolved to an int at runtime. *) +(** Specification for individual axes in the einsum notation. Note: [stride] is a string because it + can be an identifier at parse time, and is resolved to an int at runtime. *) type axis_spec = | Label of string (** A variable axis label. *) | Fixed_index of int (** A fixed index, used for projection. *) @@ -25,8 +23,8 @@ type axis_spec = conv : conv_spec option; (** Optional convolution: dilation*kernel. *) stride_offset : int; (** Constant offset added after stride*over. *) } - (** Affine axis specification: stride*over + stride_offset [+ dilation*kernel]. - Corresponds to [Row.Affine] in shape inference. *) + (** Affine axis specification: stride*over + stride_offset [+ dilation*kernel]. Corresponds to + [Row.Affine] in shape inference. *) [@@deriving compare, sexp] (** An index pointing to any of a shape's axes, including the kind of the axis ([Batch, Input, @@ -75,8 +73,8 @@ type parsed_axis_labels = { (** The labels are strings assigned to [AxisKey] axes. Moreover the [bcast_] fields represent whether additional leading/middle axes are allowed (corresponding to the dot-ellipsis syntax for broadcasting). The string can be used to identify a row variable, and defaults to ["batch"], - ["input"], ["output"] respectively when parsing ["..."]. The [given_] fields are lists of - axis specs of the corresponding kind in [labels] where [from_end=true], [given_beg_] where + ["input"], ["output"] respectively when parsing ["..."]. The [given_] fields are lists of axis + specs of the corresponding kind in [labels] where [from_end=true], [given_beg_] where [from_end=false]. *) let axis_labels parsed = parsed.labels File "tensor/shape.mli", line 1, characters 0-0: diff --git a/_build/default/tensor/shape.mli b/_build/default/tensor/.formatted/shape.mli index 5226630..55a8977 100644 --- a/_build/default/tensor/shape.mli +++ b/_build/default/tensor/.formatted/shape.mli @@ -239,5 +239,5 @@ val to_labels : t -> string array (** Uses the matrix convention of putting the input axes last. *) val parse_n5_layout : string -> int array -(** Parse a N5_layout priority string (e.g., "0,1,2") into display indices. - Only supports integer labels (Fixed_index). *) +(** Parse a N5_layout priority string (e.g., "0,1,2") into display indices. Only supports integer + labels (Fixed_index). *) File "test/einsum/test_conv_padding.ml", line 1, characters 0-0: diff --git a/_build/default/test/einsum/test_conv_padding.ml b/_build/default/test/einsum/.formatted/test_conv_padding.ml index da313d4..5cade6f 100644 --- a/_build/default/test/einsum/test_conv_padding.ml +++ b/_build/default/test/einsum/.formatted/test_conv_padding.ml @@ -7,8 +7,8 @@ let conv2d = Nn_blocks.conv2d (** Test that conv2d with use_padding=true preserves spatial dimensions. - With use_padding=true, the output spatial dimensions should match input/stride. - For stride=1 and any kernel_size, output should have the same spatial dims as input. *) + With use_padding=true, the output spatial dimensions should match input/stride. For stride=1 and + any kernel_size, output should have the same spatial dims as input. *) let test_conv2d_padding_preserves_dims () = printf "Testing conv2d with use_padding=true preserves dimensions...\n%!"; Tensor.unsafe_reinitialize (); @@ -17,7 +17,9 @@ let test_conv2d_padding_preserves_dims () = let input = TDSL.range_of_shape ~output_dims:[ 5; 5; 1 ] () in (* Apply conv2d with kernel_size=3, stride=1, use_padding=true *) - let%op output = conv2d ~label:["test_conv"] ~kernel_size:3 ~stride:1 ~use_padding:true () input in + let%op output = + conv2d ~label:[ "test_conv" ] ~kernel_size:3 ~stride:1 ~use_padding:true () input + in let ctx = Context.auto () in Train.set_hosted output.value; @@ -43,7 +45,9 @@ let test_conv2d_no_padding_reduces_dims () = let input = TDSL.range_of_shape ~output_dims:[ 5; 5; 1 ] () in (* Apply conv2d with kernel_size=3, stride=1, use_padding=false *) - let%op output = conv2d ~label:["test_conv"] ~kernel_size:3 ~stride:1 ~use_padding:false () input in + let%op output = + conv2d ~label:[ "test_conv" ] ~kernel_size:3 ~stride:1 ~use_padding:false () input + in let ctx = Context.auto () in Train.set_hosted output.value; @@ -59,8 +63,8 @@ let test_conv2d_no_padding_reduces_dims () = (** Test conv2d with stride=2 and use_padding=true. - With stride=2 and use_padding=true, output dims should be ceil(input/stride). - For 6x6 input, stride=2: output should be 3x3. *) + With stride=2 and use_padding=true, output dims should be ceil(input/stride). For 6x6 input, + stride=2: output should be 3x3. *) let test_conv2d_stride_with_padding () = printf "Testing conv2d with stride=2 and use_padding=true...\n%!"; Tensor.unsafe_reinitialize (); @@ -69,7 +73,9 @@ let test_conv2d_stride_with_padding () = let input = TDSL.range_of_shape ~output_dims:[ 6; 6; 1 ] () in (* Apply conv2d with kernel_size=3, stride=2, use_padding=true *) - let%op output = conv2d ~label:["test_conv"] ~kernel_size:3 ~stride:2 ~use_padding:true () input in + let%op output = + conv2d ~label:[ "test_conv" ] ~kernel_size:3 ~stride:2 ~use_padding:true () input + in let ctx = Context.auto () in Train.set_hosted output.value; @@ -95,7 +101,9 @@ let test_conv2d_stride_without_padding () = let input = TDSL.range_of_shape ~output_dims:[ 6; 6; 1 ] () in (* Apply conv2d with kernel_size=3, stride=2, use_padding=false *) - let%op output = conv2d ~label:["test_conv"] ~kernel_size:3 ~stride:2 ~use_padding:false () input in + let%op output = + conv2d ~label:[ "test_conv" ] ~kernel_size:3 ~stride:2 ~use_padding:false () input + in let ctx = Context.auto () in Train.set_hosted output.value; File "test/einsum/test_einsum_parser.ml", line 1, characters 0-0: diff --git a/_build/default/test/einsum/test_einsum_parser.ml b/_build/default/test/einsum/.formatted/test_einsum_parser.ml index c305169..ac88c8a 100644 --- a/_build/default/test/einsum/test_einsum_parser.ml +++ b/_build/default/test/einsum/.formatted/test_einsum_parser.ml @@ -12,8 +12,7 @@ let test_single_char () = (* Test 2: With batch and input *) let spec2 = "b|i->o" in let labels2 = Einsum_parser.axis_labels_of_spec spec2 in - printf " 'b|i->o' -> batch:%d input:%d output:%d\n" - (List.length labels2.given_batch) + printf " 'b|i->o' -> batch:%d input:%d output:%d\n" (List.length labels2.given_batch) (List.length labels2.given_input) (List.length labels2.given_output); @@ -21,13 +20,9 @@ let test_single_char () = let spec3 = "ij;jk=>ik" in let l1, l2_opt, l3 = Einsum_parser.einsum_of_spec spec3 in let l2 = Option.value_exn l2_opt in - printf " 'ij;jk=>ik' -> (%d,%d);(%d,%d)=>(%d,%d)\n" - (List.length l1.given_input) - (List.length l1.given_output) - (List.length l2.given_input) - (List.length l2.given_output) - (List.length l3.given_input) - (List.length l3.given_output); + printf " 'ij;jk=>ik' -> (%d,%d);(%d,%d)=>(%d,%d)\n" (List.length l1.given_input) + (List.length l1.given_output) (List.length l2.given_input) (List.length l2.given_output) + (List.length l3.given_input) (List.length l3.given_output); printf "\n" File "test/einsum/test_conv_syntax.ml", line 1, characters 0-0: diff --git a/_build/default/test/einsum/test_conv_syntax.ml b/_build/default/test/einsum/.formatted/test_conv_syntax.ml index bb97681..028dbb4 100644 --- a/_build/default/test/einsum/test_conv_syntax.ml +++ b/_build/default/test/einsum/.formatted/test_conv_syntax.ml @@ -8,43 +8,50 @@ let test_conv_parsing () = let spec1 = "2*o+3*k" in let labels1 = Einsum_parser.axis_labels_of_spec spec1 in printf "Test 1: Parsed '%s' successfully\n%!" spec1; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels1)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels1)); (* Test 2: Simple conv expression without coefficients (multichar - requires commas) *) let spec2 = "o+k" in let labels2 = Einsum_parser.axis_labels_of_spec spec2 in printf "Test 2: Parsed '%s' successfully\n%!" spec2; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels2)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels2)); (* Test 3: Mixed spec with comma (multichar mode) *) let spec3 = "a, 2*b+c" in let labels3 = Einsum_parser.axis_labels_of_spec spec3 in printf "Test 3: Parsed '%s' successfully\n%!" spec3; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels3)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels3)); (* Test 4: Conv expression with multiple identifiers (multichar - requires commas) *) let spec4 = "i, o+k, j" in let labels4 = Einsum_parser.axis_labels_of_spec spec4 in printf "Test 4: Parsed '%s' successfully (multichar mode)\n%!" spec4; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels4)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels4)); (* Test 5: Conv expression with multi-char identifiers (multichar) *) let spec5 = "a+bc" in let labels5 = Einsum_parser.axis_labels_of_spec spec5 in printf "Test 5: Parsed '%s' successfully (multichar mode)\n%!" spec5; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels5)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels5)); (* Test 6: Test in einsum notation with multichar conv *) let spec6 = "i, j -> 2*i+j" in let labels6 = Einsum_parser.axis_labels_of_spec spec6 in printf "Test 6: Parsed '%s' successfully\n%!" spec6; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels6)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels6)); (* Test 7: Complex batch-input-output spec with conv *) let spec7 = "batch|input->3*output+1*kernel," in let labels7 = Einsum_parser.axis_labels_of_spec spec7 in printf "Test 7: Parsed '%s' successfully\n%!" spec7; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels7)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels7)); printf "All conv syntax parsing tests passed!\n%!" @@ -55,25 +62,29 @@ let test_strided_iteration_parsing () = let spec1 = "2*output" in let labels1 = Einsum_parser.axis_labels_of_spec spec1 in printf "Test 1: Parsed strided iteration '%s' successfully\n%!" spec1; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels1)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels1)); (* Test 2: Strided iteration with single-char identifier (multichar mode) *) let spec2 = "3*i" in let labels2 = Einsum_parser.axis_labels_of_spec spec2 in printf "Test 2: Parsed strided iteration '%s' successfully\n%!" spec2; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels2)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels2)); (* Test 3: Strided iteration in einsum context (multichar due to multiplication) *) let spec3 = "input -> 2*output" in let labels3 = Einsum_parser.axis_labels_of_spec spec3 in printf "Test 3: Parsed einsum with strided iteration '%s' successfully\n%!" spec3; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels3)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels3)); (* Test 4: Mixed regular labels and strided iteration (multichar due to comma) *) let spec4 = "regular, 3*strided" in let labels4 = Einsum_parser.axis_labels_of_spec spec4 in printf "Test 4: Parsed mixed labels with strided iteration '%s' successfully\n%!" spec4; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels4)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels4)); printf "\nAll strided iteration parsing tests completed!\n%!" @@ -138,37 +149,43 @@ let test_use_padding_syntax () = let spec1 = "o=+k" in let labels1 = Einsum_parser.axis_labels_of_spec spec1 in printf "Test 1: Parsed '%s' (use_padding=true)\n%!" spec1; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels1)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels1)); (* Test 2: use_padding=false with < syntax *) let spec2 = "o<+k" in let labels2 = Einsum_parser.axis_labels_of_spec spec2 in printf "Test 2: Parsed '%s' (use_padding=false)\n%!" spec2; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels2)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels2)); (* Test 3: use_padding with stride *) let spec3 = "2*o=+k" in let labels3 = Einsum_parser.axis_labels_of_spec spec3 in printf "Test 3: Parsed '%s' (stride with use_padding=true)\n%!" spec3; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels3)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels3)); (* Test 4: use_padding with dilation *) let spec4 = "o<+3*k" in let labels4 = Einsum_parser.axis_labels_of_spec spec4 in printf "Test 4: Parsed '%s' (dilation with use_padding=false)\n%!" spec4; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels4)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels4)); (* Test 5: use_padding with stride and dilation *) let spec5 = "2*o=+3*k" in let labels5 = Einsum_parser.axis_labels_of_spec spec5 in printf "Test 5: Parsed '%s' (stride, dilation, use_padding=true)\n%!" spec5; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels5)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels5)); (* Test 6: unspecified use_padding (legacy syntax) *) let spec6 = "o+k" in let labels6 = Einsum_parser.axis_labels_of_spec spec6 in printf "Test 6: Parsed '%s' (unspecified use_padding)\n%!" spec6; - printf " Structure: %s\n\n%!" (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels6)); + printf " Structure: %s\n\n%!" + (Sexp.to_string_hum (Einsum_parser.sexp_of_parsed_axis_labels labels6)); printf "All use_padding syntax tests completed!\n%!" File "arrayjit/lib/indexing.ml", line 1, characters 0-0: diff --git a/_build/default/arrayjit/lib/indexing.ml b/_build/default/arrayjit/lib/.formatted/indexing.ml index 018c9e9..0d03161 100644 --- a/_build/default/arrayjit/lib/indexing.ml +++ b/_build/default/arrayjit/lib/.formatted/indexing.ml @@ -139,8 +139,8 @@ type projections = { *) product_iterators : symbol array; (** The product space iterators (concatentation of the relevant batch, output, input axes) for - iterating over the [product_space] axes, where same axes are at same array indices. - These may be shared; lowering creates fresh symbols for loop indices. *) + iterating over the [product_space] axes, where same axes are at same array indices. These + may be shared; lowering creates fresh symbols for loop indices. *) project_lhs : axis_index array; (** A projection that takes an [product_space]-bound index and produces an index into the result of an operation. *) File "lib/nn_blocks.ml", line 1, characters 0-0: diff --git a/_build/default/lib/nn_blocks.ml b/_build/default/lib/.formatted/nn_blocks.ml index 562b267..8558d01 100644 --- a/_build/default/lib/nn_blocks.ml +++ b/_build/default/lib/.formatted/nn_blocks.ml @@ -216,7 +216,8 @@ let%op conv2d ~label ?(kernel_size = 3) ?(stride = 1) ?(use_padding = true) () x (** Depthwise separable convolution - more efficient for mobile/edge devices. Consists of depthwise conv (spatial filtering per channel) followed by pointwise conv (1x1 conv for channel mixing) *) -let%op depthwise_separable_conv2d ~label ?(kernel_size = 3) ?(stride = 1) ?(use_padding = true) () x = +let%op depthwise_separable_conv2d ~label ?(kernel_size = 3) ?(stride = 1) ?(use_padding = true) () x + = (* Depthwise: each input channel is convolved with its own filter *) Shape.set_dim kh kernel_size; Shape.set_dim kw kernel_size; @@ -250,8 +251,8 @@ let%op avg_pool2d ?(stride = 2) ?(window_size = 2) () x = Shape.set_dim ww window_size; let sum = x - +++ "... | stride*oh< + wh, stride*ow< + ww, ..c..; wh, ww => ... | oh, ow, ..c.." [ "wh"; "ww" ] - (0.5 + 0.5) + +++ "... | stride*oh< + wh, stride*ow< + ww, ..c..; wh, ww => ... | oh, ow, ..c.." + [ "wh"; "ww" ] (0.5 + 0.5) in sum /. (dim wh *. dim ww) File "arrayjit/lib/assignments.ml", line 1, characters 0-0: diff --git a/_build/default/arrayjit/lib/assignments.ml b/_build/default/arrayjit/lib/.formatted/assignments.ml index 2c5a13e..0940272 100644 --- a/_build/default/arrayjit/lib/assignments.ml +++ b/_build/default/arrayjit/lib/.formatted/assignments.ml @@ -192,10 +192,10 @@ let%track4_sexp to_low_level code = = let projections : Indexing.projections = Lazy.force projections in let basecase rev_iters = - (* Create a substitution from product iterators to loop iterators. - Fresh loop symbols are needed because product_iterators may be shared across - different operations/tensors, but each lowered operation needs private loop symbols - to avoid conflicts in low_level.ml's symbol-to-tensor tracking. *) + (* Create a substitution from product iterators to loop iterators. Fresh loop symbols are + needed because product_iterators may be shared across different operations/tensors, but + each lowered operation needs private loop symbols to avoid conflicts in low_level.ml's + symbol-to-tensor tracking. *) let subst_map = let loop_iters = Array.of_list_rev rev_iters in Array.mapi projections.product_iterators ~f:(fun i prod_iter -> File "tensor/ppx_shared.ml", line 1, characters 0-0: diff --git a/_build/default/tensor/ppx_shared.ml b/_build/default/tensor/.formatted/ppx_shared.ml index 5bf48c7..2d5d0db 100644 --- a/_build/default/tensor/ppx_shared.ml +++ b/_build/default/tensor/.formatted/ppx_shared.ml @@ -115,12 +115,12 @@ let ndarray_constant expr = (** Convert an einsum spec string to an OCaml expression that constructs the runtime string. - This function parses the einsum spec using the Einsum_parser, then reconstructs a runtime - string expression, handling: - - stride and dilation values: if they look like integer literals, emit them directly; - otherwise emit [Int.to_string identifier] to convert at runtime - - use_padding: if unspecified (legacy syntax), emit [if use_padding then "=" else "<"] - to read the value from [Row.use_padding] at runtime + This function parses the einsum spec using the Einsum_parser, then reconstructs a runtime string + expression, handling: + - stride and dilation values: if they look like integer literals, emit them directly; otherwise + emit [Int.to_string identifier] to convert at runtime + - use_padding: if unspecified (legacy syntax), emit [if use_padding then "=" else "<"] to read + the value from [Row.use_padding] at runtime Example: ["stride*x=+k; y => z"] where [stride] is a variable, generates an expression that evaluates to e.g. ["2*x=+k; y => z"] if [stride = 2]. *) @@ -216,11 +216,12 @@ let substitute_identifiers_in_einsum_spec ~loc str_input = let output_segments = row_to_segments ~kind:"output" parsed.bcast_output parsed.given_beg_output parsed.given_output in - let has_batch = not (List.is_empty batch_segments) || Option.is_some parsed.bcast_batch in - let has_input = not (List.is_empty input_segments) || Option.is_some parsed.bcast_input in + let has_batch = (not (List.is_empty batch_segments)) || Option.is_some parsed.bcast_batch in + let has_input = (not (List.is_empty input_segments)) || Option.is_some parsed.bcast_input in let segments = if has_batch then - batch_segments @ [ estring ~loc "|" ] + batch_segments + @ [ estring ~loc "|" ] @ (if has_input then input_segments @ [ estring ~loc "->" ] else []) @ output_segments else if has_input then input_segments @ [ estring ~loc "->" ] @ output_segments @@ -248,33 +249,34 @@ let substitute_identifiers_in_einsum_spec ~loc str_input = let combined = String.concat (List.filter_map all_segments ~f:(fun e -> - match e.pexp_desc with Pexp_constant (Pconst_string (s, _, _)) -> Some s | _ -> None)) + match e.pexp_desc with + | Pexp_constant (Pconst_string (s, _, _)) -> Some s + | _ -> None)) in estring ~loc combined else [%expr String.concat ~sep:"" [%e elist ~loc all_segments]] - with Parse_error _ -> + with Parse_error _ -> ( (* If parsing fails, try as axis_labels_spec *) - (try - let parsed = axis_labels_of_spec str_input in - let segments = parsed_to_segments parsed in - let all_literals = - List.for_all segments ~f:(fun e -> - match e.pexp_desc with Pexp_constant (Pconst_string _) -> true | _ -> false) - in - if all_literals then - let combined = - String.concat - (List.filter_map segments ~f:(fun e -> - match e.pexp_desc with - | Pexp_constant (Pconst_string (s, _, _)) -> Some s - | _ -> None)) - in - estring ~loc combined - else [%expr String.concat ~sep:"" [%e elist ~loc segments]] - with Parse_error msg -> - (* Fall back to returning the original string with an error note *) - pexp_extension ~loc - @@ Location.error_extensionf ~loc "Failed to parse einsum spec: %s" msg) + try + let parsed = axis_labels_of_spec str_input in + let segments = parsed_to_segments parsed in + let all_literals = + List.for_all segments ~f:(fun e -> + match e.pexp_desc with Pexp_constant (Pconst_string _) -> true | _ -> false) + in + if all_literals then + let combined = + String.concat + (List.filter_map segments ~f:(fun e -> + match e.pexp_desc with + | Pexp_constant (Pconst_string (s, _, _)) -> Some s + | _ -> None)) + in + estring ~loc combined + else [%expr String.concat ~sep:"" [%e elist ~loc segments]] + with Parse_error msg -> + (* Fall back to returning the original string with an error note *) + pexp_extension ~loc @@ Location.error_extensionf ~loc "Failed to parse einsum spec: %s" msg) let string_expr ~loc s = Ast_helper.Exp.constant @@ Pconst_string (s, loc, None) File "tensor/row.ml", line 1, characters 0-0: diff --git a/_build/default/tensor/row.ml b/_build/default/tensor/.formatted/row.ml index 3e4a138..6dd88c3 100644 --- a/_build/default/tensor/row.ml +++ b/_build/default/tensor/.formatted/row.ml @@ -3648,8 +3648,13 @@ let%track7_sexp get_proj_index (proj_env : proj_env) (proj : proj) : Idx.axis_in | [ (1, s) ] when !offset = 0 -> Idx.Iterator s | _ -> Idx.Affine { symbols; offset = !offset }) | Conv_input - { stride; over; conv = Some { dilation; kernel; kernel_size; use_padding }; stride_offset; target_id } - -> ( + { + stride; + over; + conv = Some { dilation; kernel; kernel_size; use_padding }; + stride_offset; + target_id; + } -> ( let over_idx = loop over in let kernel_idx = loop kernel in let symbols = ref [] in @@ -3890,13 +3895,13 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list) @@ Shape_error ("Multiple constraints on the same projection", [ Index_mismatch [ idx; idx2 ] ]))); let product_dim = ref @@ Map.empty (module Proj_id) in - (* Collect projection IDs that will get their index from Conv_input (target_id projections). - These should NOT get fresh iterators from product_dim processing. *) + (* Collect projection IDs that will get their index from Conv_input (target_id projections). These + should NOT get fresh iterators from product_dim processing. *) let conv_input_targets = Set.of_list (module Proj_id) @@ List.filter_map !p_conv_input ~f:(fun (p, _) -> - let repr, _ = Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:p ~rank:0 in - Some repr) + let repr, _ = Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:p ~rank:0 in + Some repr) in List.iter !p_dims ~f:(fun (p, d) -> let repr, _ = Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:p ~rank:0 in @@ -3910,8 +3915,8 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list) "Conflicting dimensions for the same projection: %{p#Proj_id} %{d#Int} \ %{d2#Int}"], [] ))); - (* Create fresh iterators for product dimensions, EXCEPT for those that will get - their index from Conv_input (they will be processed later). *) + (* Create fresh iterators for product dimensions, EXCEPT for those that will get their index from + Conv_input (they will be processed later). *) Map.iteri !product_dim ~f:(fun ~key:p ~data:_ -> let repr, _ = Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:p ~rank:0 in if not (Set.mem conv_input_targets repr) then @@ -3971,8 +3976,8 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list) ("Cannot unify two Conv_input projections", [ Index_mismatch [ idx1; idx2 ] ]) with _ -> () (* Ignore errors for now *)); - (* Now create fresh iterators for product dimensions that still don't have an index. - This is done after p_conv_input processing so Conv_input projections don't conflict. *) + (* Now create fresh iterators for product dimensions that still don't have an index. This is done + after p_conv_input processing so Conv_input projections don't conflict. *) Map.iteri !product_dim ~f:(fun ~key:p ~data:_ -> let repr, _ = Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:p ~rank:0 in Utils.mref_add_missing projs repr ~f:(fun () -> Idx.(Iterator (get_symbol ())))); dune build @fmt failed "/usr/bin/env" "bash" "-c" "opam exec -- dune build @fmt --ignore-promoted-rules || (echo "dune build @fmt failed"; exit 2)" failed with exit status 2 2025-12-03 12:37.14: Job failed: Failed: Build failed