@Override
    public double apply(Variable v, Map<Object, Object> cache) {
      Double detJ = null;
      double[][] J = null;
      if (cache != null) {
        detJ = (Double) cache.get(1);
        J = (double[][]) cache.get(2);
      }
      if (detJ == null || J == null) {
        J = new double[3][3];
        J[0][0] = x_r.apply(v);
        J[0][1] = x_s.apply(v);
        J[0][2] = x_t.apply(v);
        J[1][0] = y_r.apply(v);
        J[1][1] = y_s.apply(v);
        J[1][2] = y_t.apply(v);
        J[2][0] = z_r.apply(v);
        J[2][1] = z_s.apply(v);
        J[2][2] = z_t.apply(v);
        // @see ./doc/invA33.png
        detJ = Utils.determinant(J);
        if (cache != null) {
          cache.put(1, detJ);
          cache.put(2, J);
        }
      }

      if ("r".equals(rst)) {
        if ("x".equals(xyz)) return (J[1][1] * J[2][2] - J[1][2] * J[2][1]) / detJ;
        else if ("y".equals(xyz)) return (J[0][2] * J[2][1] - J[0][1] * J[2][2]) / detJ;
        else if ("z".equals(xyz)) return (J[0][1] * J[1][2] - J[0][2] * J[1][1]) / detJ;
      } else if ("s".equals(rst)) {
        if ("x".equals(xyz)) return (J[1][2] * J[2][0] - J[1][0] * J[2][2]) / detJ;
        else if ("y".equals(xyz)) return (J[0][0] * J[2][2] - J[0][2] * J[2][0]) / detJ;
        else if ("z".equals(xyz)) return (J[0][2] * J[1][0] - J[0][0] * J[1][2]) / detJ;
      } else {
        if ("x".equals(xyz)) return (J[1][0] * J[2][1] - J[1][1] * J[2][0]) / detJ;
        else if ("y".equals(xyz)) return (J[0][1] * J[2][0] - J[0][0] * J[2][1]) / detJ;
        else if ("z".equals(xyz)) return (J[0][0] * J[1][1] - J[0][1] * J[1][0]) / detJ;
      }
      throw new FutureyeException("");
    }
    @Override
    public double[] applyAll(VariableArray valAry, Map<Object, Object> cache) {
      double[] detJ = null;
      double[][][] J = null;
      int len = valAry.length();
      double[] rlt = new double[len];
      if (cache != null) {
        detJ = (double[]) cache.get(1);
        J = (double[][][]) cache.get(2);
      }
      if (detJ == null || J == null) {
        J = new double[3][3][len];
        J[0][0] = x_r.applyAll(valAry, cache);
        J[0][1] = x_s.applyAll(valAry, cache);
        J[0][2] = x_t.applyAll(valAry, cache);
        J[1][0] = y_r.applyAll(valAry, cache);
        J[1][1] = y_s.applyAll(valAry, cache);
        J[1][2] = y_t.applyAll(valAry, cache);
        J[2][0] = z_r.applyAll(valAry, cache);
        J[2][1] = z_s.applyAll(valAry, cache);
        J[2][2] = z_t.applyAll(valAry, cache);
        // @see ./doc/invA33.png
        detJ = Utils.determinant(J);
        if (cache != null) {
          cache.put(1, detJ);
          cache.put(2, J);
        }
      }

      if ("r".equals(rst)) {
        if ("x".equals(xyz))
          for (int i = 0; i < len; i++)
            rlt[i] = (J[1][1][i] * J[2][2][i] - J[1][2][i] * J[2][1][i]) / detJ[i];
        else if ("y".equals(xyz))
          for (int i = 0; i < len; i++)
            rlt[i] = (J[0][2][i] * J[2][1][i] - J[0][1][i] * J[2][2][i]) / detJ[i];
        else if ("z".equals(xyz))
          for (int i = 0; i < len; i++)
            rlt[i] = (J[0][1][i] * J[1][2][i] - J[0][2][i] * J[1][1][i]) / detJ[i];
      } else if ("s".equals(rst)) {
        if ("x".equals(xyz))
          for (int i = 0; i < len; i++)
            rlt[i] = (J[1][2][i] * J[2][0][i] - J[1][0][i] * J[2][2][i]) / detJ[i];
        else if ("y".equals(xyz))
          for (int i = 0; i < len; i++)
            rlt[i] = (J[0][0][i] * J[2][2][i] - J[0][2][i] * J[2][0][i]) / detJ[i];
        else if ("z".equals(xyz))
          for (int i = 0; i < len; i++)
            rlt[i] = (J[0][2][i] * J[1][0][i] - J[0][0][i] * J[1][2][i]) / detJ[i];
      } else if ("t".equals(rst)) {
        if ("x".equals(xyz))
          for (int i = 0; i < len; i++)
            rlt[i] = (J[1][0][i] * J[2][1][i] - J[1][1][i] * J[2][0][i]) / detJ[i];
        else if ("y".equals(xyz))
          for (int i = 0; i < len; i++)
            rlt[i] = (J[0][1][i] * J[2][0][i] - J[0][0][i] * J[2][1][i]) / detJ[i];
        else if ("z".equals(xyz))
          for (int i = 0; i < len; i++)
            rlt[i] = (J[0][0][i] * J[1][1][i] - J[0][1][i] * J[1][0][i]) / detJ[i];
      } else {
        throw new FutureyeException();
      }
      return rlt;
    }
 public SF123() {
   super(SFLinearLocal2D.this.varNames);
   this.setArgIdx(Utils.getIndexMap(this.getVarNames()));
 }