Skip to content

Commit 458901b

Browse files
committed
Fix map function + add common variables
should have added them from beginning instead of giving custom names to them. Will not be deleting that.
1 parent e44fd92 commit 458901b

18 files changed

+836
-719
lines changed

README.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ You can also get the node from comfy manager under the name of More math.
2222
- Math: `+`, `-`, `*`, `/`, `%`, `^`, `||`
2323
- Boolean: `<`, `<=`, `>`, `>=`, `==`, `!=`
2424
(`false = 0.0`, `true = 1.0`)
25+
- Lists: `[v1, v2, ...]` (Vector math supported, only usefull in `conv`)
2526

2627
## Functions
2728

@@ -69,12 +70,22 @@ You can also get the node from comfy manager under the name of More math.
6970

7071
- `tmin(x, y)`: Element-wise minimum of x and y.
7172
- `tmax(x, y)`: Element-wise maximum of x and y.
72-
- `smin(x, y, ...)`: **Scalar** minimum. Returns the single smallest value across all input tensors/values.
73-
- `smax(x, y, ...)`: **Scalar** maximum. Returns the single largest value across all input tensors/values.
73+
- `smin(x, ...)`: **Scalar** minimum. Returns the single smallest value across all input tensors/values.
74+
- `smax(x, ...)`: **Scalar** maximum. Returns the single largest value across all input tensors/values.
7475
- `tnorm(x)`: **Tensor** Normalizes x (L2 norm along last dimension).
7576
- `snorm(x)`: **Scalar** L2 norm of the entire tensor.
7677
- `swap(tensor, dim, index1, index2)`: Swaps two slices of a tensor along a specified dimension. (Tensor only)
7778

79+
### Advanced Tensor Operations (Tensor Only)
80+
81+
- `map(tensor, c1, ...)`: Remaps `tensor` using source coordinates.
82+
- Up to 3 coordinate mapping functions can be provided which map to the last (up to 3) dimensions of the tensor.
83+
- If less than 3 functions are provided and shape of tensor > 3, the remaining dimensions are assumed to be identity functions.
84+
- `conv(tensor, kw, [kh], [kd], k_expr)`: Applies a convolution to `tensor`.
85+
- `k_expr` can be a math expression (using `kX`, `kY`, `kZ`) or a list literal.
86+
87+
- `permute(tensor, [dims])`: Rearranges the dimensions of the tensor. (e.g., `permute(a, [2, 3, 0, 1])`)
88+
7889
### FFT (Tensor Only)
7990

8091
- `fft(x)`: Fast Fourier Transform (Time to Frequency).
@@ -84,9 +95,13 @@ You can also get the node from comfy manager under the name of More math.
8495
### Utility
8596

8697
- `print(x)`: Prints the value of x to the console and returns x.
98+
- `print_shape(x)` or `pshp`: Prints the shape of x to the console and returns x.
8799

88100
## Variables
89101

102+
- **Common variables (except FLOAT, MODEL, VAE and CLIP)**:
103+
- `D{N}` - position in n-th dimension of tensor (for example D0, D1, D2, ...)
104+
- `S{N}` - size of n-th dimension of tensor (for example S0, S1, S2, ...)
90105
- **common inputs** (matches node input type):
91106
- `a`, `b`, `c`, `d`
92107
- **Extra floats**:
@@ -103,8 +118,13 @@ You can also get the node from comfy manager under the name of More math.
103118
- `W` or `width` - width of image. y/width = 1
104119
- `H` or `height`- height of image. x/height = 1
105120
- `B` or 'batch' - position in batch
106-
- 'T' or 'batch_count` - number of batches
121+
- `T` or `batch_count` - number of batches
107122
- `N` or `channel_count` - count of channels
123+
- **IMAGE KERNEL**:
124+
- `kX`, `kY` - position in kernel. Centered at 0.0.
125+
- `kW`, `kernel_width` - width of kernel.
126+
- `kH`, `kernel_height` - height of kernel.
127+
- `kD`, `kernel_depth` - depth of kernel.
108128

109129
- **AUDIO**:
110130
- `B` or 'batch' - position in batch
@@ -124,6 +144,6 @@ You can also get the node from comfy manager under the name of More math.
124144
- no additional variables
125145
- `F` or `frequency_count` – frequency count (freq domain, iFFT only)
126146
- `K` or `frequency` – isotropic frequency (Euclidean norm of indices, iFFT only)
127-
- `Kx`, `Ky`, `K_dimN` - frequency index for specific dimension
128-
- `Fx`, `Fy`, `F_dimN` - frequency count for specific dimension
147+
- `Kx`, `Ky`, `Kz`, `Kw`,`Kv`, `Ku`, `K_dimN` - frequency index for specific dimension
148+
- `Fx`, `Fy`, `Fz`, `Fw`,`Fv`,`Fu`, `F_dimN` - frequency count for specific dimension
129149
- Constants: `e`, `pi`

more_math/AudioMathNode.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import torch
2-
from .helper_functions import getIndexTensorAlongDim, comonLazy, eval_tensor_expr, make_zero_like
2+
from .helper_functions import generate_dim_variables, getIndexTensorAlongDim, comonLazy, eval_tensor_expr, make_zero_like
33

44
from comfy_api.latest import io
55

@@ -9,12 +9,12 @@
99
class AudioMathNode(MathNodeBase):
1010
"""
1111
Enables math expressions on Audio tensors.
12-
12+
1313
Inputs:
1414
a, b, c, d: Audio inputs (b, c, d default to zero if not provided)
1515
w, x, y, z: Float variables for expressions
1616
AudioExpr: Expression to apply on audio tensors
17-
17+
1818
Outputs:
1919
AUDIO: Result of applying expression to input audio
2020
"""
@@ -42,31 +42,32 @@ def define_schema(cls) -> io.Schema:
4242
)
4343

4444
@classmethod
45-
def execute(cls, a, AudioExpr, b=None, c=None, d=None, w=0.0, x=0.0, y=0.0, z=0.0):
46-
waveform = a['waveform']
45+
def execute(cls, AudioExpr, a, b=None, c=None, d=None, w=0.0, x=0.0, y=0.0, z=0.0):
46+
av = a['waveform']
4747
sample_rate = a['sample_rate']
4848

4949
a, b, c, d = cls.prepare_inputs(a, b, c, d)
5050

5151
bv, cv, dv = b['waveform'], c['waveform'], d['waveform']
5252

5353
variables = {
54-
'a': waveform, 'b': bv, 'c': cv, 'd': dv,
54+
'a': av, 'b': bv, 'c': cv, 'd': dv,
5555
'w': w, 'x': x, 'y': y, 'z': z,
56-
'B': getIndexTensorAlongDim(waveform, 0),
57-
'C': getIndexTensorAlongDim(waveform, 1),
58-
'S': getIndexTensorAlongDim(waveform, 2),
59-
'R': torch.full_like(waveform, sample_rate, dtype=torch.float32),
60-
'T': torch.full_like(waveform, waveform.shape[2], dtype=torch.float32),
61-
'N': waveform.shape[1],
62-
'batch': getIndexTensorAlongDim(waveform, 0),
63-
'channel': getIndexTensorAlongDim(waveform, 1),
64-
'sample': getIndexTensorAlongDim(waveform, 2),
65-
'sample_rate': torch.full_like(waveform, sample_rate, dtype=torch.float32),
66-
'sample_count': torch.full_like(waveform, waveform.shape[2], dtype=torch.float32),
67-
'channel_count': waveform.shape[1],
68-
}
56+
'B': getIndexTensorAlongDim(av, 0),
57+
'C': getIndexTensorAlongDim(av, 1),
58+
'S': getIndexTensorAlongDim(av, 2),
59+
'R': torch.full_like(av, sample_rate, dtype=torch.float32),
60+
'T': torch.full_like(av, av.shape[2], dtype=torch.float32),
61+
'N': av.shape[1],
62+
'batch': getIndexTensorAlongDim(av, 0),
63+
'channel': getIndexTensorAlongDim(av, 1),
64+
'sample': getIndexTensorAlongDim(av, 2),
65+
'sample_rate': torch.full_like(av, sample_rate, dtype=torch.float32),
66+
'sample_count': torch.full_like(av, av.shape[2], dtype=torch.float32),
67+
'channel_count': av.shape[1],
68+
} | generate_dim_variables(av)
69+
6970

70-
result_tensor = eval_tensor_expr(AudioExpr, variables, waveform.shape)
71+
result_tensor = eval_tensor_expr(AudioExpr, variables, av.shape)
7172

7273
return ({'waveform': result_tensor, 'sample_rate': sample_rate},)

more_math/ConditioningMathNode.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from inspect import cleandoc
22
import torch
33

4-
from .helper_functions import comonLazy, eval_tensor_expr, make_zero_like
4+
from .helper_functions import comonLazy, eval_tensor_expr, generate_dim_variables, make_zero_like
55
from comfy_api.latest import io
66

77

@@ -11,17 +11,17 @@
1111
class ConditioningMathNode(MathNodeBase):
1212
"""
1313
Enables math operations on conditionings.
14-
14+
1515
Inputs:
1616
a, b, c, d: Conditioning inputs (b, c, d default to zero if not provided)
1717
w, x, y, z: Float variables for expressions
1818
Tensor: Expression for the tensor part (describes image composition)
1919
pooled_output: Expression for the pooled output (condensed representation)
20-
20+
2121
Outputs:
2222
CONDITIONING: Result of applying expressions to input conditionings
2323
"""
24-
24+
2525
@classmethod
2626
def define_schema(cls) -> io.Schema:
2727
return io.Schema(
@@ -60,9 +60,9 @@ def execute(cls, Tensor, pooled_output, a, b=None, c=None, d=None, w=0.0, x=0.0,
6060

6161
# Extract tensors
6262
ta, tb, tc, td = a[0][0], b[0][0], c[0][0], d[0][0]
63-
63+
6464
# Evaluate tensor expression
65-
variables = {'a': ta, 'b': tb, 'c': tc, 'd': td, 'w': w, 'x': x, 'y': y, 'z': z}
65+
variables = {'a': ta, 'b': tb, 'c': tc, 'd': td, 'w': w, 'x': x, 'y': y, 'z': z} | generate_dim_variables(ta)
6666
result_tensor = eval_tensor_expr(Tensor, variables, ta.shape)
6767

6868
# Evaluate pooled_output expression if available
@@ -71,7 +71,7 @@ def execute(cls, Tensor, pooled_output, a, b=None, c=None, d=None, w=0.0, x=0.0,
7171
pb = b[0][1].get("pooled_output")
7272
pc = c[0][1].get("pooled_output")
7373
pd = d[0][1].get("pooled_output")
74-
variables = {'a': pa, 'b': pb, 'c': pc, 'd': pd, 'w': w, 'x': x, 'y': y, 'z': z}
74+
variables = {'a': pa, 'b': pb, 'c': pc, 'd': pd, 'w': w, 'x': x, 'y': y, 'z': z} | generate_dim_variables(pa)
7575
result_pooled = eval_tensor_expr(pooled_output, variables, pa.shape)
7676
else:
7777
result_pooled = None

more_math/ImageMathNode.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import torch
2-
from .helper_functions import getIndexTensorAlongDim, comonLazy, eval_tensor_expr, make_zero_like
2+
from .helper_functions import generate_dim_variables, getIndexTensorAlongDim, comonLazy, eval_tensor_expr, make_zero_like
33

44
from comfy_api.latest import io
55

@@ -9,12 +9,12 @@
99
class ImageMathNode(MathNodeBase):
1010
"""
1111
Enables math expressions on Images.
12-
12+
1313
Inputs:
1414
a, b, c, d: Image inputs (b, c, d default to zero if not provided)
1515
w, x, y, z: Float variables for expressions
1616
Image: Expression to apply on input images
17-
17+
1818
Outputs:
1919
IMAGE: Result of applying expression to input images
2020
"""
@@ -45,11 +45,6 @@ def define_schema(cls) -> io.Schema:
4545
def execute(cls, Image, a, b=None, c=None, d=None, w=0.0, x=0.0, y=0.0, z=0.0):
4646
a, b, c, d = cls.prepare_inputs(a, b, c, d)
4747

48-
# Permute to B, C, H, W for processing
49-
a = a.permute(0, 3, 1, 2)
50-
b = b.permute(0, 3, 1, 2)
51-
c = c.permute(0, 3, 1, 2)
52-
d = d.permute(0, 3, 1, 2)
5348

5449
variables = {
5550
'a': a, 'b': b, 'c': c, 'd': d,
@@ -62,10 +57,8 @@ def execute(cls, Image, a, b=None, c=None, d=None, w=0.0, x=0.0, y=0.0, z=0.0):
6257
'H': a.shape[2], 'height': a.shape[2],
6358
'T': a.shape[0], 'batch_count': a.shape[0],
6459
'N': a.shape[1], 'channel_count': a.shape[1],
65-
}
60+
} | generate_dim_variables(a)
6661

6762
result = eval_tensor_expr(Image, variables, a.shape)
6863

69-
# Permute back to B, H, W, C
70-
result = result.permute(0, 2, 3, 1)
7164
return (result,)

more_math/LatentMathNode.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import torch
66

7-
from .helper_functions import getIndexTensorAlongDim, comonLazy, parse_expr, eval_tensor_expr_with_tree, make_zero_like
7+
from .helper_functions import generate_dim_variables, getIndexTensorAlongDim, comonLazy, parse_expr, eval_tensor_expr_with_tree, make_zero_like
88

99
from .MathNodeBase import MathNodeBase
1010

@@ -114,7 +114,7 @@ def eval_single_tensor(a_t, b_t, c_t, d_t):
114114
'H': height_val, 'height': height_val,
115115
'T': frame_count, 'batch_count': batch_count,
116116
'N': channel_count, 'channel_count': channel_count,
117-
}
117+
} | generate_dim_variables(a_t)
118118

119119
# expose time/frame if present
120120
if time_dim is not None:

more_math/NoiseMathNode.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import torch
44

5-
from .helper_functions import getIndexTensorAlongDim, comonLazy, parse_expr, eval_tensor_expr_with_tree, make_zero_like
5+
from .helper_functions import generate_dim_variables, getIndexTensorAlongDim, comonLazy, parse_expr, eval_tensor_expr_with_tree, make_zero_like
66

77
from comfy_api.latest import io
88

@@ -183,7 +183,7 @@ def merge_to_tensor(val, ref):
183183
'I': merged_samples, 'T': frame_count, 'N': merged_samples.shape[channel_dim],
184184
'batch': B, 'width': merged_samples.shape[width_dim], 'height': merged_samples.shape[height_dim], 'channel': C,
185185
'batch_count': merged_samples.shape[0], 'channel_count': merged_samples.shape[1], 'input_latent': merged_samples,
186-
}
186+
} | generate_dim_variables(merged_samples)
187187
if time_dim is not None:
188188
F = getIndexTensorAlongDim(merged_samples, time_dim)
189189
variables.update({'frame': F, 'frame_count': frame_count})

more_math/Parser/MathExpr.g4

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ func1
8989
| SOFTPLUS '(' expr ')' # SoftplusFunc
9090
| GELU '(' expr ')' # GeluFunc
9191
| SIGN '(' expr ')' # SignFunc
92+
| PRINT_SHAPE_L '(' expr ')' # PrintShapeFunc
93+
| PRINT_SHAPE '(' expr ')' # PrintShapeFunc
9294
;
9395

9496
// Two-argument functions
@@ -156,6 +158,8 @@ SFFT : 'fft';
156158
SIFFT : 'ifft';
157159
ANGL : 'angle';
158160
PRNT : 'print';
161+
PRINT_SHAPE_L : 'print_shape';
162+
PRINT_SHAPE : 'pshp';
159163
LERP : 'lerp';
160164
STEP : 'step';
161165
SMOOTHSTEP : 'smoothstep';

0 commit comments

Comments
 (0)