# SCAD → Cordial Translation Reference

Every SCAD operation has a Cordial equivalent. Where the operation can
be parallelized, the conditions and a Cordial example are shown.

---

## Primitives

### sphere

**SCAD**
```scad
sphere(r=5);
sphere(5);
```

**Cordial**
```rust
sphere(5.0)
```

Parallelism: n/a — leaf node; always evaluable at any point independently.

---

### cube

**SCAD**
```scad
cube([10, 20, 30]);
cube(5);
cube([10, 20, 30], center=true);
```

**Cordial**
```rust
box3(5.0, 10.0, 15.0)   // half-extents, always centered
cube(5.0)                // equal half-extents
```

Note: SCAD `cube()` uses full sizes and defaults to corner-aligned.
Cordial uses half-extents and is always centered. The lowerer handles
the translation offset automatically when ingesting SCAD.

---

### cylinder

**SCAD**
```scad
cylinder(h=10, r=3);
cylinder(h=10, r=3, center=true);
```

**Cordial**
```rust
cylinder(3.0, 10.0)   // always centered on Z
```

---

## Transforms

### translate

**SCAD**
```scad
translate([10, 0, 0]) sphere(1);
```

**Cordial**
```rust
sphere(1.0).translate(10.0, 0.0, 0.0)
```

Parallelism: a translation wraps its child — the child subtree is
independently evaluable. Multiple translates on independent shapes
are always parallel.

---

### rotate

**SCAD**
```scad
rotate([45, 0, 0]) cube(5);
rotate([0, 90, 0]) cube(5);
```

**Cordial**
```rust
cube(5.0).rotate_x(45.0)
cube(5.0).rotate_y(90.0)
```

SCAD `rotate([x,y,z])` decomposes into sequential X, Y, Z rotations.
Cordial exposes each axis independently.

---

### scale

**SCAD**
```scad
scale([2, 1, 1]) sphere(1);
scale(3) sphere(1);
```

**Cordial**
```rust
sphere(1.0).scale(2.0, 1.0, 1.0)
sphere(1.0).scale_uniform(3.0)
```

---

## Boolean Operations

### union

**SCAD**
```scad
union() {
    sphere(1);
    cube(2);
}
```

**Cordial**
```rust
sphere(1.0) | cube(2.0)

// or explicitly:
sphere(1.0).union(cube(2.0))

// or variadic:
Shape::union_all([sphere(1.0), cube(2.0), cylinder(1.0, 3.0)])
```

**Parallelism: always parallelizable.**

Condition: union children share no intermediate state. In an SDF,
every child is a separate distance field — `min(d_a, d_b)` evaluates
`d_a` and `d_b` independently.

```rust
// Parallel union — each branch evaluates on its own thread
par::branch()
    .add(sphere(1.0))
    .add(cube(2.0).translate(5.0, 0.0, 0.0))
    .add(cylinder(1.0, 3.0).rotate_x(90.0))
    .union()
```

---

### difference

**SCAD**
```scad
difference() {
    cube(10, center=true);
    sphere(5);
}
```

**Cordial**
```rust
cube(10.0) - sphere(5.0)

// or explicitly:
cube(10.0).difference(sphere(5.0))

// or multiple subtractions:
cube(10.0).difference_all([sphere(5.0), cylinder(2.0, 20.0)])
```

**Parallelism: parallelizable when operands are independent subtrees.**

Condition: the base shape and the subtracted shapes share no
intermediate nodes. The base evaluates independently from the
subtracted shapes. The subtracted shapes themselves are a union
of independent evaluations (each contributes to `max(base, -sub)`).

```rust
// The base and each subtracted shape are independent branches
par::branch()
    .add(cube(10.0))
    .add(sphere(5.0))
    .add(cylinder(2.0, 20.0))
    .intersection()  // difference = intersection with complement
```

---

### intersection

**SCAD**
```scad
intersection() {
    sphere(5);
    cube(4, center=true);
}
```

**Cordial**
```rust
sphere(5.0) & cube(4.0)
```

**Parallelism: parallelizable when operands are independent subtrees.**

Same condition as difference — `max(d_a, d_b)` evaluates both
sides independently.

```rust
par::branch()
    .add(sphere(5.0))
    .add(cube(4.0))
    .intersection()
```

---

## Control Flow

### for loop

**SCAD**
```scad
for (i = [0:5])
    translate([i*10, 0, 0]) sphere(1);

for (i = [0:2:10])
    translate([i, 0, 0]) sphere(1);

for (x = [1, 5, 10])
    translate([x, 0, 0]) cube(2);
```

**Cordial** (`.crd` source)
```
// Linear array — 6 spheres spaced 10 apart
map(i, 0..6) { translate(sphere(1), i * 10, 0, 0) }

// 8 bolts around a circle
map(i, 0..8) { rotate_z(translate(cylinder(0.5, 2), 5, 0, 0), i * pi/4) }
```

**Cordial** (Rust DSL)
```rust
pattern::linear_array(&sphere(1.0), 6, [10.0, 0.0, 0.0])

par::polar(&cylinder(0.5, 2.0).translate(5.0, 0.0, 0.0), 8)
```

**Parallelism: always parallelizable when bounds are constant.**

`map` unrolls at parse time into N independent branches joined by
union. Each iteration is independent — no iteration reads state
written by another. This is the fundamental serial-to-parallel
transformation: what looks like a sequential loop is actually N
independent geometric evaluations.

---

### if / else

**SCAD**
```scad
if (use_sphere)
    sphere(5);
else
    cube(5, center=true);

x = 10;
if (x > 5) sphere(x);
```

**Cordial** — direct conditional geometry isn't needed because Rust
has native `if`:
```rust
let shape = if use_sphere {
    sphere(5.0)
} else {
    cube(5.0)
};
```

**Parallelism: constant conditions → dead code elimination.**

Condition: if the condition evaluates to a constant at lowering
time, only the taken branch produces geometry. The other branch is
eliminated entirely — zero cost.

When the condition is variable (unknown at compile time), both
branches are included as a union. This is conservative but
correct — the SDF field is defined everywhere.

---

### Ternary

**SCAD**
```scad
r = big ? 10 : 1;
sphere(r);
```

**Cordial** — native Rust:
```rust
let r = if big { 10.0 } else { 1.0 };
sphere(r)
```

Evaluated at lowering time when all inputs are constant.

---

## Patterns (Cordial-only)

These have no direct SCAD equivalent — they're higher-level abstractions
that compile to parallel-friendly structures.

### linear_array

```rust
// 5 spheres along X, spaced 3 units apart
pattern::linear_array(&sphere(1.0), 5, [3.0, 0.0, 0.0])
```

Always parallel — each instance is independent.

### polar_array

```rust
// 12 bolts around Z
pattern::polar_array(&cylinder(0.3, 2.0).translate(5.0, 0.0, 0.0), 12)
```

Always parallel — equivalent to N rotations of the same shape.

### grid_array

```rust
// 4x6 grid of cylinders
pattern::grid_array(&cylinder(0.5, 1.0), 4, 6, 3.0, 3.0)
```

Always parallel — N×M independent instances.

### mirror

```rust
pattern::mirror_x(&sphere(1.0).translate(3.0, 0.0, 0.0))
// Original at (3,0,0) + mirror at (-3,0,0)
```

Always parallel — 2 branches, one original, one reflected.

---

## Parallel Composition (Cordial-only)

### par::branch — explicit parallel grouping

```rust
// N independent shapes, explicitly grouped for parallel evaluation
let part = par::branch()
    .add(sphere(2.0))
    .add(cylinder(1.0, 5.0).translate(0.0, 0.0, 1.0))
    .add(cube(1.5).rotate_z(45.0).translate(3.0, 0.0, 0.0))
    .union();
```

Each `.add()` is an independent branch. The join operation (`.union()`,
`.intersection()`, `.smooth_union(k)`) combines results after all
branches complete.

### par::map — multiplicative parallelism

```rust
// Same shape, N different transforms — all independent
par::map(&sphere(0.5), (0..20).map(|i| {
    let t = i as f64 / 20.0;
    let x = (t * std::f64::consts::TAU).cos() * 5.0;
    let y = (t * std::f64::consts::TAU).sin() * 5.0;
    let z = t * 10.0;
    move |s: Shape| s.translate(x, y, z)
}))
```

### par::symmetric — mirror parallelism

```rust
par::symmetric_x(&part)     // 2 branches
par::symmetric_xyz(&part)   // 8 branches (all octants)
```

### par::polar — rotational parallelism

```rust
par::polar(&fin, 6)   // 6 branches around Z
```

---

## Parallelism Summary

| Operation | Parallelizable? | Condition |
|-----------|----------------|-----------|
| Primitive (sphere, cube, etc.) | Always | Leaf node — independent by definition |
| Transform (translate, rotate, scale) | Always | Wraps child; child evaluates independently |
| Union | Always | `min(a, b)` — operands share no state |
| Difference | Yes | Operands are independent subtrees |
| Intersection | Yes | Operands are independent subtrees |
| For loop (constant bounds) | Always | Unrolls to N independent branches |
| For loop (variable bounds) | No | Cannot unroll at compile time |
| If/else (constant condition) | n/a | Dead code eliminated; only one branch exists |
| If/else (variable condition) | Yes | Both branches included as union |
| `par::branch` | Always | Explicit parallel grouping |
| `par::map` | Always | Same shape, N transforms |
| `par::polar` | Always | N rotations around axis |
| `pattern::*` | Always | Compile to union of independent instances |

The threshold: an operation becomes parallelizable when it crosses
into calculus — when accumulated structure becomes continuous and
differentiable, every point in the field is independently evaluable.
SDFs are inherently in this territory: the distance function is
defined at every point in space, and evaluating it at point A tells
you nothing about point B. Serial operations that build up an SDF
tree are just describing the function — once described, evaluation
is embarrassingly parallel.
