"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[72],{3905:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return u}});var a=n(67294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,a,i=function(e,t){if(null==e)return{};var n,a,i={},r=Object.keys(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var m=a.createContext({}),p=function(e){var t=a.useContext(m),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(m.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,m=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),d=p(n),u=i,h=d["".concat(m,".").concat(u)]||d[u]||s[u]||r;return n?a.createElement(h,o(o({ref:t},c),{},{components:n})):a.createElement(h,o({ref:t},c))}));function u(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,o=new Array(r);o[0]=d;var l={};for(var m in t)hasOwnProperty.call(t,m)&&(l[m]=t[m]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var p=2;p<r;p++)o[p]=n[p];return a.createElement.apply(null,o)}return a.createElement.apply(null,n)}d.displayName="MDXCreateElement"},45607:function(e,t,n){n.r(t),n.d(t,{frontMatter:function(){return l},contentTitle:function(){return m},metadata:function(){return p},toc:function(){return c},default:function(){return d}});var a=n(83117),i=n(80102),r=(n(67294),n(3905)),o=["components"],l={sidebar_position:1,slug:"/math_module"},m="Math Module",p={unversionedId:"lang/articles/math/math_module",id:"version-v1.5.0/lang/articles/math/math_module",title:"Math Module",description:"Taichi provides a built-in math module that supports frequently used mathematical functions and utility functions, including:",source:"@site/versioned_docs/version-v1.5.0/lang/articles/math/math_module.md",sourceDirName:"lang/articles/math",slug:"/math_module",permalink:"/docs/v1.5.0/math_module",editUrl:"https://github.com/taichi-dev/taichi/edit/master/docs/lang/articles/math/math_module.md",tags:[],version:"v1.5.0",lastUpdatedBy:"Taichi Gardener",lastUpdatedAt:1679941743,formattedLastUpdatedAt:"3/27/2023",sidebarPosition:1,frontMatter:{sidebar_position:1,slug:"/math_module"},sidebar:"langSidebar",previous:{title:"Vulkan Backend Features",permalink:"/docs/v1.5.0/taichi_vulkan"},next:{title:"Sparse Matrix",permalink:"/docs/v1.5.0/sparse_matrix"}},c=[{value:"Mathematical functions",id:"mathematical-functions",children:[],level:2},{value:"Small vector and matrix types",id:"small-vector-and-matrix-types",children:[{value:"Relations between <code>ti.Vector</code>, <code>ti.types.vector</code> and <code>ti.math.vec3</code>",id:"relations-between-tivector-titypesvector-and-timathvec3",children:[],level:3}],level:2},{value:"GLSL-standard functions",id:"glsl-standard-functions",children:[],level:2},{value:"Complex number operations",id:"complex-number-operations",children:[],level:2}],s={toc:c};function d(e){var t=e.components,n=(0,i.Z)(e,o);return(0,r.kt)("wrapper",(0,a.Z)({},s,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"math-module"},"Math Module"),(0,r.kt)("p",null,"Taichi provides a built-in ",(0,r.kt)("inlineCode",{parentName:"p"},"math")," module that supports frequently used mathematical functions and utility functions, including:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Commonly-used mathematical functions that are analogous to those in Python's built-in ",(0,r.kt)("inlineCode",{parentName:"li"},"math")," module."),(0,r.kt)("li",{parentName:"ul"},"Small vector and matrix types that are analogous to those in the ",(0,r.kt)("a",{parentName:"li",href:"https://www.khronos.org/opengl/wiki/OpenGL_Shading_Language"},"OpenGL shading language")," (GLSL)."),(0,r.kt)("li",{parentName:"ul"},"Some GLSL-standard functions."),(0,r.kt)("li",{parentName:"ul"},"Complex number operations in the form of 2D vectors.")),(0,r.kt)("h2",{id:"mathematical-functions"},"Mathematical functions"),(0,r.kt)("p",null,"You must call the mathematical functions provided by Taichi's ",(0,r.kt)("inlineCode",{parentName:"p"},"math")," module from within the Taichi scope. For example:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python"},"import taichi as ti\nimport taichi.math as tm\nti.init()\n\n@ti.kernel\ndef test():\n    a = 1.0\n    x = tm.sin(a)\n    y = tm.floor(a)\n    z = tm.degrees(a)\n    w = tm.log2(a)\n    ...\n")),(0,r.kt)("p",null,"These functions also take vectors and matrices as arguments and operate on them element-wise:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python"},"@ti.kernel\ndef test():\n    a = ti.Vector([1.0, 2.0, 3.0])\n    x = tm.sin(a)  # [0.841471, 0.909297, 0.141120]\n    y = tm.floor(a)  #  [1.000000, 2.000000, 3.000000]\n    z = tm.degrees(a)  #  [57.295780, 114.591560, 171.887344]\n    b = ti.Vector([2.0, 3.0, 4.0])\n    w = tm.atan2(b, a)  # [1.107149, 0.982794, 0.927295]\n    ...\n")),(0,r.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,r.kt)("div",{parentName:"div",className:"admonition-heading"},(0,r.kt)("h5",{parentName:"div"},(0,r.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,r.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,r.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"note")),(0,r.kt)("div",{parentName:"div",className:"admonition-content"},(0,r.kt)("p",{parentName:"div"},"Taichi's math module overlaps to a large extent with Python's built-in math module. Ensure that you follow a few extra rules when using Taichi's math module:"),(0,r.kt)("ul",{parentName:"div"},(0,r.kt)("li",{parentName:"ul"},"You must call the functions provided by Taichi's math module from within the Taichi scope."),(0,r.kt)("li",{parentName:"ul"},"Functions in Taichi's math module also take vectors or matrices as arguments."),(0,r.kt)("li",{parentName:"ul"},"The precision of a function in Taichi's math module depends on the settings of ",(0,r.kt)("inlineCode",{parentName:"li"},"default_fp")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"arch")," (backend) in ",(0,r.kt)("inlineCode",{parentName:"li"},"ti.init()"),".")))),(0,r.kt)("h2",{id:"small-vector-and-matrix-types"},"Small vector and matrix types"),(0,r.kt)("p",null,"Taichi's math module provides a few small vector and matrix types:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"vec2/vec3/vec4"),": 2D/3D/4D floating-point vector types."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ivec2/ivec3/ivec4"),": 2D/3D/4D integer vector types."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"uvec2/uvec3/uvec4"),": 2D/3D/4D unsigned integer vector types."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"mat2/mat3/mat4"),": 2D/3D/4D floating-point square matrix types.")),(0,r.kt)("p",null,"To create one of the vector/matrix types above, use template function ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.types.vector()")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.types.matrix()"),". For example, ",(0,r.kt)("inlineCode",{parentName:"p"},"vec2")," is defined as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python"},"vec2 = ti.types.vector(2, float)\n")),(0,r.kt)("p",null,"The number of precision bits of such a type is determined by ",(0,r.kt)("inlineCode",{parentName:"p"},"default_fp")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"default_ip")," in the ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.init()")," method call. For example, if ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.init(default_fp=ti.f64)")," is called, then ",(0,r.kt)("inlineCode",{parentName:"p"},"vec2/vec3/vec4")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"mat2/mat3/mat4")," defined in the Taichi scope all have a 64-bit floating-point precision."),(0,r.kt)("p",null,"You can use these types to instantiate vectors/matrices or annotate data types for function arguments and struct members. See the ",(0,r.kt)("a",{parentName:"p",href:"/docs/v1.5.0/type"},"Type System")," for more information. Here we emphasize that they have very flexible initialization routines:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python"},"mat2 = ti.math.mat2\nvec3 = ti.math.mat3\nvec4 = ti.math.vec4\n\nm = mat2(1)  # [[1., 1.], [1., 1.]]\nm = mat2(1, 2, 3, 4)  # [[1., 2.], [3, 4.]]\nm = mat2([1, 2], [3, 4])  # [[1., 2.], [3, 4.]]\nm = mat2([1, 2, 3, 4])  # [[1., 2.], [3, 4.]]\nv = vec3(1, 2, 3)\nm = mat2(v, 4)  # [[1., 2.], [3, 4.]]\nu = vec4([1, 2], [3, 4])\nu = vec4(v, 4.0)\n")),(0,r.kt)("p",null,"Another important feature of vector types created by ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.types.vector()")," is that they support ",(0,r.kt)("strong",{parentName:"p"},"vector swizzling")," just as GLSL vectors do. This means you can use ",(0,r.kt)("inlineCode",{parentName:"p"},"xyzw"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"rgba"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"stpq")," to access their elements with indices ","\u2264"," four:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python"},"v = ti.math.vec4(1, 2, 3, 4)\nu = v.xyz  # vec3(1, 2, 3)\nu = v.xxx  # vec3(1, 1, 1)\nu = v.wzyx  # vec4(4, 3, 2, 1)\nu = v.rraa  # vec4(1, 1, 2, 2)\n")),(0,r.kt)("h3",{id:"relations-between-tivector-titypesvector-and-timathvec3"},"Relations between ",(0,r.kt)("inlineCode",{parentName:"h3"},"ti.Vector"),", ",(0,r.kt)("inlineCode",{parentName:"h3"},"ti.types.vector")," and ",(0,r.kt)("inlineCode",{parentName:"h3"},"ti.math.vec3")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"ti.Vector")," is a function that accepts a 1D array and returns a matrix instance that has only one column. For example, ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.Vector([1, 2, 3, 4, 5])"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"ti.types.vector")," is a function that accepts an integer and a primitive type and returns a vector type. For example: ",(0,r.kt)("inlineCode",{parentName:"p"},"vec5f = ti.types.vector(5, float)"),". ",(0,r.kt)("inlineCode",{parentName:"p"},"vec5f")," can then be used to instantiate 5D vectors or annotate data types of function arguments and struct members:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-python"},"@ti.kernel\ndef test(v: vec5f):\n    print(v.xyz)\n")),(0,r.kt)("p",{parentName:"li"},"  Unlike ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.Vector"),", whose input data must be a 1D array, vector types created by ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.types.vector()")," have more flexible ways to initialize, as explained above.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"ti.math.vec3")," is created by ",(0,r.kt)("inlineCode",{parentName:"p"},"vec3 = ti.types.vector(3, float)"),"."))),(0,r.kt)("h2",{id:"glsl-standard-functions"},"GLSL-standard functions"),(0,r.kt)("p",null,"Taichi's math module also supports a few ",(0,r.kt)("a",{parentName:"p",href:"https://registry.khronos.org/OpenGL-Refpages/gl4/index.php"},"GLSL standard functions"),". These functions follow the GLSL standard, except that they accept arbitrary vectors and matrices as arguments and operate on them element-wise. For example:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python"},"import taichi as ti\nimport taichi.math as tm\n\n@ti.kernel\ndef example():\n    v = tm.vec3(0., 1., 2.)\n    w = tm.smoothstep(0.0, 1.0, v)\n    w = tm.clamp(w, 0.2, 0.8)\n    w = tm.reflect(v, tm.normalize(tm.vec3(1)))\n")),(0,r.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,r.kt)("div",{parentName:"div",className:"admonition-heading"},(0,r.kt)("h5",{parentName:"div"},(0,r.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,r.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,r.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"note")),(0,r.kt)("div",{parentName:"div",className:"admonition-content"},(0,r.kt)("p",{parentName:"div"},"Texture support in Taichi is implemented in the ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.types.texture_types")," module."))),(0,r.kt)("h2",{id:"complex-number-operations"},"Complex number operations"),(0,r.kt)("p",null,"Taichi's math module also supports basic complex arithmetic operations on 2D vectors."),(0,r.kt)("p",null,"You can use a 2D vector of type ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.math.vec2")," to represent a complex number. In this way, additions and subtractions of complex numbers come in the form of 2D vector additions and subtractions. You can call ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.math.cmul()")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"ti.math.cdiv()")," to conduct multiplication and division of complex numbers:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python"},"import taichi as ti\nimport taichi.math as tm\nti.init()\n\n@ti.kernel\ndef test():\n    x = tm.vec2(1, 1)  # complex number 1+1j\n    y = tm.vec2(0, 1)  # complex number 1j\n    z = tm.cmul(x, y)  # vec2(-1, 1) = -1+1j\n    w = tm.cdiv(x, y)  #  vec2(2, 0) = 2+0j\n")),(0,r.kt)("p",null,"You can also compute the power, logarithm, and exponential of a complex number:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python"},"@ti.kernel\ndef test():\n    x = tm.vec2(1, 1)  # complex number 1 + 1j\n    y = tm.cpow(x, 2)  # complex number (1 + 1j)**2 = 2j\n    z = tm.clog(x)     # complex number (0.346574 + 0.785398j)\n    w = tm.cexp(x)     # complex number (1.468694 + 2.287355j)\n")))}d.isMDXComponent=!0}}]);